Subversion Repositories Kolibri OS

Rev

Rev 575 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
694 serge 3
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
694 serge 8
; Serge 2006-2008
9
; email: infinity_sound@mail.ru
168 serge 10
 
11
format MS COFF
12
 
465 serge 13
 
574 serge 14
CURRENT_API     equ   0x0101      ;1.01
15
COMPATIBLE_API  equ   0x0100      ;1.00
465 serge 16
 
574 serge 17
API_VERSION     equ   (COMPATIBLE_API shl 16) or CURRENT_API
18
SOUND_VERSION   equ   CURRENT_API
19
 
20
 
168 serge 21
include 'proc32.inc'
520 serge 22
 
23
;include 'system.inc'
168 serge 24
include 'main.inc'
520 serge 25
 
281 serge 26
include 'imports.inc'
168 serge 27
 
378 serge 28
FORCE_MMX         equ 0  ;set to 1 to force use mmx or
29
FORCE_MMX_128     equ 0  ;integer sse2 extensions
694 serge 30
                         ;and reduce driver size
31
 
378 serge 32
;USE_SSE          equ 0
168 serge 33
 
694 serge 34
USE_SSE2_MIXER    equ 0  ;floating point mixer. Disabled by default
35
 
378 serge 36
DEBUG             equ 1
168 serge 37
 
291 serge 38
 
465 serge 39
OS_BASE           equ 0x80000000
168 serge 40
 
378 serge 41
CAPS_SSE2         equ 26
42
PG_SW             equ 0x003
293 serge 43
 
188 serge 44
public START
168 serge 45
public service_proc
227 serge 46
public version
168 serge 47
 
378 serge 48
RT_INP_EMPTY      equ 0xFF000001
49
RT_OUT_EMPTY      equ 0xFF000002
50
RT_INP_FULL       equ 0xFF000003
51
RT_OUT_FULL       equ 0xFF000004
168 serge 52
 
378 serge 53
EVENT_WATCHED     equ 0x10000000
54
EVENT_SIGNALED    equ 0x20000000
55
MANUAL_RESET      equ 0x40000000
56
MANUAL_DESTROY    equ 0x80000000
168 serge 57
 
378 serge 58
DEV_PLAY          equ 1
59
DEV_STOP          equ 2
60
DEV_CALLBACK      equ 3
61
 
168 serge 62
struc IOCTL
378 serge 63
{  .handle        dd ?
64
   .io_code       dd ?
65
   .input         dd ?
66
   .inp_size      dd ?
67
   .output        dd ?
68
   .out_size      dd ?
168 serge 69
}
70
 
71
virtual at 0
72
  IOCTL IOCTL
73
end virtual
74
 
188 serge 75
section '.flat' code readable align 16
168 serge 76
 
214 serge 77
proc START stdcall, state:dword
78
 
227 serge 79
           cmp [state], 1
80
           jne .exit
81
 
188 serge 82
           stdcall GetService, szSound
168 serge 83
           test eax, eax
84
           jz .fail
85
           mov [hSound], eax
86
 
188 serge 87
           stdcall KernelAlloc, 16*512
168 serge 88
           test eax, eax
89
           jz .out_of_mem
90
           mov [mix_buff], eax
91
 
291 serge 92
           mov eax, str.fd-FD_OFFSET
93
           mov [str.fd], eax
94
           mov [str.bk], eax
168 serge 95
 
293 serge 96
if FORCE_MMX
97
 if FORCE_MMX_128
98
  display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10
99
  stop
100
 end if
101
           mov [mix_2_core], mmx_mix_2
102
           mov [mix_3_core], mmx_mix_3
103
           mov [mix_4_core], mmx_mix_4
104
end if
105
 
106
if FORCE_MMX_128
107
 if FORCE_MMX
108
  display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10
109
  stop
110
 end if
111
           mov [mix_2_core], mmx128_mix_2
112
           mov [mix_3_core], mmx128_mix_3
113
           mov [mix_4_core], mmx128_mix_4
114
end if
115
 
378 serge 116
if 0
117
 
293 serge 118
if ~(FORCE_MMX or FORCE_MMX_128)  ;autodetect
119
           mov eax, 1
120
           cpuid
121
           bt edx, CAPS_SSE2
122
           jc .mmx128
123
                                           ;old 64-bit mmx
124
           mov [mix_2_core], mmx_mix_2
125
           mov [mix_3_core], mmx_mix_3
126
           mov [mix_4_core], mmx_mix_4
127
           jmp @F
328 serge 128
.mmx128:                                   ;128-bit integer sse2 extensions
293 serge 129
           mov [mix_2_core], mmx128_mix_2
130
           mov [mix_3_core], mmx128_mix_3
131
           mov [mix_4_core], mmx128_mix_4
132
@@:
133
end if
378 serge 134
 
135
end if
168 serge 136
           stdcall set_handler, [hSound], new_mix
378 serge 137
           mov [eng_state], SND_STOP
188 serge 138
           stdcall RegService, szInfinity, service_proc
227 serge 139
           ret
168 serge 140
.fail:
141
     if DEBUG
227 serge 142
           mov esi, msgFail
188 serge 143
           call SysMsgBoardStr
168 serge 144
     end if
214 serge 145
.exit:
227 serge 146
           xor eax, eax
147
           ret
168 serge 148
 
149
.out_of_mem:
150
     if DEBUG
151
           mov esi, msgMem
188 serge 152
           call SysMsgBoardStr
168 serge 153
     end if
227 serge 154
           xor eax, eax
188 serge 155
           ret
214 serge 156
endp
168 serge 157
 
158
handle     equ  IOCTL.handle
159
io_code    equ  IOCTL.io_code
160
input      equ  IOCTL.input
161
inp_size   equ  IOCTL.inp_size
162
output     equ  IOCTL.output
163
out_size   equ  IOCTL.out_size
164
 
165
align 4
166
proc service_proc stdcall, ioctl:dword
167
 
168
           mov edi, [ioctl]
169
           mov eax, [edi+io_code]
170
 
378 serge 171
           cmp eax, SRV_GETVERSION
172
           jne @F
173
           mov eax, [edi+output]
465 serge 174
           cmp [edi+out_size], 4
175
           jne .fail
378 serge 176
           mov eax, [eax]
574 serge 177
           mov [eax], dword API_VERSION
378 serge 178
           xor eax, eax
179
           ret
180
@@:
227 serge 181
           cmp eax, SND_CREATE_BUFF
182
           jne @F
168 serge 183
           mov ebx, [edi+input]
378 serge 184
           stdcall CreateBuffer,[ebx],[ebx+4]
561 serge 185
           mov edi, [ioctl]
378 serge 186
           mov ecx, [edi+output]
187
           mov ecx, [ecx]
465 serge 188
           mov [ecx], ebx
227 serge 189
           ret
168 serge 190
@@:
378 serge 191
           mov ebx, [edi+input]
192
           mov edx, [ebx]
193
 
194
           cmp [edx+STREAM.magic], 'WAVE'
195
           jne .fail
196
 
197
           cmp [edx+STREAM.size], STREAM_SIZE
198
           jne .fail
199
 
200
           cmp eax, SND_DESTROY_BUFF
227 serge 201
           jne @F
378 serge 202
           mov eax, edx
203
           call DestroyBuffer    ;edx= stream
227 serge 204
           ret
168 serge 205
@@:
378 serge 206
           cmp eax, SND_SETFORMAT
227 serge 207
           jne @F
572 serge 208
           stdcall SetFormat,edx,[ebx+4]
378 serge 209
           ret
210
@@:
211
           cmp eax, SND_GETFORMAT
212
           jne @F
168 serge 213
 
378 serge 214
           movzx eax, word [edx+STREAM.format]
215
           mov ecx, [edi+output]
216
           mov ecx, [ecx]
465 serge 217
           mov [ecx], eax
378 serge 218
           xor eax, eax
227 serge 219
           ret
168 serge 220
@@:
378 serge 221
           cmp eax, SND_RESET
222
           jne @F
572 serge 223
           stdcall ResetBuffer,edx,[ebx+4]
378 serge 224
           ret
225
@@:
226
           cmp eax, SND_SETPOS
227
           jne @F
572 serge 228
           stdcall SetBufferPos,edx,[ebx+4]
378 serge 229
           ret
230
@@:
231
           cmp eax, SND_GETPOS
232
           jne @F
572 serge 233
           stdcall GetBufferPos, edx
561 serge 234
           mov edi, [ioctl]
378 serge 235
           mov ecx, [edi+output]
236
           mov ecx, [ecx]
465 serge 237
           mov [ecx], ebx
378 serge 238
           ret
239
@@:
227 serge 240
           cmp eax, SND_SETBUFF
241
           jne @F
242
           mov eax, [ebx+4]
572 serge 243
           stdcall set_buffer, edx,eax,[ebx+8],[ebx+12]
227 serge 244
           ret
168 serge 245
@@:
378 serge 246
           cmp eax, SND_SETVOLUME
227 serge 247
           jne @F
572 serge 248
           stdcall SetBufferVol,edx,[ebx+4],[ebx+8]
378 serge 249
           ret
250
@@:
251
           cmp eax, SND_GETVOLUME
252
           jne @F
168 serge 253
 
378 serge 254
           mov eax, [edi+output]
255
           mov ecx, [eax]
256
           mov eax, [eax+4]
572 serge 257
           stdcall GetBufferVol,edx,ecx,eax
227 serge 258
           ret
168 serge 259
@@:
378 serge 260
           cmp eax, SND_SETPAN
261
           jne @F
572 serge 262
           stdcall SetBufferPan,edx,[ebx+4]
378 serge 263
           ret
264
@@:
265
           cmp eax, SND_GETPAN
266
           jne @F
267
           mov eax, [edx+STREAM.pan]
268
           mov ebx, [edi+output]
269
           mov ebx, [ebx]
465 serge 270
           mov [ebx], eax
227 serge 271
           xor eax, eax
272
           ret
378 serge 273
@@:
274
           cmp eax, SND_OUT
275
           jne @F
276
 
277
           mov eax, [ebx+4]
572 serge 278
           stdcall wave_out, edx,eax,[ebx+8]
378 serge 279
           ret
280
@@:
281
           cmp eax, SND_PLAY
282
           jne @F
283
 
572 serge 284
           stdcall play_buffer, edx,[ebx+4]
378 serge 285
           ret
286
@@:
287
           cmp eax, SND_STOP
288
           jne @F
289
 
572 serge 290
           stdcall stop_buffer, edx
378 serge 291
           ret
292
@@:
293
           cmp eax, SND_GETBUFFSIZE
294
           jne @F
295
           mov eax, [edx+STREAM.in_size]
296
           mov ecx, [edi+output]
297
           mov ecx, [ecx]
465 serge 298
           mov [ecx], eax
378 serge 299
           xor eax, eax
300
           ret
301
@@:
572 serge 302
           cmp eax, SND_GETFREESPACE
303
           jne @F
304
 
305
           test [edx+STREAM.format], PCM_OUT
306
           jz .fail
307
 
308
           mov ebx, [edx+STREAM.in_free]
309
           mov ecx, [edi+output]
310
           mov [ecx], ebx
311
           xor eax, eax
312
           ret
313
@@:
378 serge 314
.fail:
315
           or eax, -1
316
           ret
168 serge 317
endp
318
 
319
restore   handle
320
restore   io_code
321
restore   input
322
restore   inp_size
323
restore   output
324
restore   out_size
325
 
328 serge 326
align 4
378 serge 327
proc CreateBuffer stdcall, format:dword, size:dword
227 serge 328
           locals
378 serge 329
             str         dd ?
330
             ring_size   dd ?
331
             ring_pages  dd ?
227 serge 332
           endl
168 serge 333
 
378 serge 334
           mov eax, [format]
335
           cmp ax, PCM_1_8_8
336
           ja .fail
337
 
338
           test eax, PCM_OUT
339
           jnz .test_out
340
           test eax, PCM_RING
341
           jnz .test_ring
342
;staic
567 serge 343
           test eax, PCM_STATIC
568 serge 344
           jz .test_out                   ;use PCM_OUT as default format
378 serge 345
           jmp .test_ok
346
.test_out:
347
           test eax, PCM_RING+PCM_STATIC
348
           jnz .fail
568 serge 349
           or [format], PCM_OUT           ;force set
378 serge 350
           jmp .test_ok
351
.test_ring:
352
           test eax, PCM_OUT+PCM_STATIC
353
           jnz .fail
354
.test_ok:
520 serge 355
 
356
           call GetPid
357
           mov ebx, eax
291 serge 358
           mov eax, STREAM_SIZE
359
 
360
           call CreateObject
361
           test eax, eax
227 serge 362
           jz .fail
363
           mov [str], eax
168 serge 364
 
378 serge 365
           mov ebx, [format]
366
           mov [eax+STREAM.format], ebx
168 serge 367
 
378 serge 368
           xor ecx, ecx
369
           movzx ebx, bx
370
           cmp ebx, 19
371
           jb @f
372
           mov ecx, 0x80808080
373
@@:
374
           mov [eax+STREAM.r_silence], ecx
168 serge 375
 
378 serge 376
           shl ebx, 2
377
           lea ebx, [ebx+ebx*2]     ;ebx*=12
168 serge 378
 
378 serge 379
           mov ecx, [resampler_params+ebx]
380
           mov edx, [resampler_params+ebx+4]
381
           mov esi, [resampler_params+ebx+8]
382
 
383
           mov [eax+STREAM.r_size],ecx
384
           mov [eax+STREAM.r_dt],  edx
385
           mov [eax+STREAM.resample], esi
386
           xor ecx, ecx
387
           mov [eax+STREAM.l_vol], ecx
388
           mov [eax+STREAM.r_vol], ecx
389
           mov dword [eax+STREAM.l_amp], 0x7FFF7FFF
390
           mov [eax+STREAM.pan], ecx
391
 
392
           test [format], PCM_STATIC
393
           jnz .static
394
 
395
; ring and waveout
396
 
465 serge 397
           mov ebx, 0x10000
378 serge 398
           test [format], PCM_RING
399
           jz .waveout
400
 
465 serge 401
           mov ebx, [eax+STREAM.r_size]
402
           add ebx, 4095
403
           and ebx, -4096
404
           add ebx, ebx
378 serge 405
.waveout:
465 serge 406
           mov [ring_size], ebx
407
           mov eax, ebx
378 serge 408
           shr ebx, 12
409
           mov [ring_pages], ebx
410
 
520 serge 411
           stdcall CreateRingBuffer, eax, PG_SW
412
 
227 serge 413
           mov edi, [str]
378 serge 414
           mov ecx, [ring_size]
415
           mov [edi+STREAM.in_base], eax
416
           mov [edi+STREAM.in_size], ecx
417
           add eax, 128
561 serge 418
        ;   sub ecx, 128
378 serge 419
           mov [edi+STREAM.in_wp], eax
420
           mov [edi+STREAM.in_rp], eax
421
           mov [edi+STREAM.in_count], 0
168 serge 422
 
378 serge 423
           mov [edi+STREAM.in_free], ecx
424
           add eax, ecx
425
           mov [edi+STREAM.in_top], eax
328 serge 426
 
378 serge 427
           jmp .out_buff
428
.static:
429
           mov ecx, [size]
430
           add ecx, 128          ;resampler required
431
           mov [eax+STREAM.in_size], ecx
432
           stdcall KernelAlloc, ecx
433
 
434
           mov edi, [str]
435
           mov [edi+STREAM.in_base], eax
436
           add eax, 128
437
           mov [edi+STREAM.in_wp], eax
438
           mov [edi+STREAM.in_rp], eax
439
           mov ebx, [size]
440
           mov [edi+STREAM.in_count], ebx
441
           mov [edi+STREAM.in_free], ebx
442
           add eax, ebx
443
           mov [edi+STREAM.in_top], eax
444
 
445
.out_buff:
328 serge 446
           stdcall AllocKernelSpace, dword 128*1024
447
 
448
           mov edi, [str]
378 serge 449
           mov [edi+STREAM.out_base], eax
450
           mov [edi+STREAM.out_wp], eax
451
           mov [edi+STREAM.out_rp], eax
452
           mov [edi+STREAM.out_count], 0
328 serge 453
           add eax, 64*1024
378 serge 454
           mov [edi+STREAM.out_top], eax
168 serge 455
 
328 serge 456
           stdcall AllocPages, dword 64/4
457
           mov edi, [str]
378 serge 458
           mov ebx, [edi+STREAM.out_base]
328 serge 459
           mov ecx, 16
460
           or eax, PG_SW
461
           push eax
462
           push ebx
463
           call CommitPages ;eax, ebx, ecx
464
           mov ecx, 16
465
           pop ebx
466
           pop eax
467
           add ebx, 64*1024
468
           call CommitPages    ;double mapped
469
 
470
           mov edi, [str]
378 serge 471
           mov ecx, [edi+STREAM.in_top]
472
           mov edi, [edi+STREAM.in_base]
473
           sub ecx, edi
227 serge 474
           xor eax, eax
378 serge 475
           shr ecx, 2
328 serge 476
           cld
227 serge 477
           rep stosd
168 serge 478
 
328 serge 479
           mov edi, [str]
378 serge 480
           mov edi, [edi+STREAM.out_base]
328 serge 481
           mov ecx, (64*1024)/4
482
           rep stosd
483
 
378 serge 484
           xor edx, edx
485
           mov ebx, MANUAL_DESTROY
486
           call CreateEvent
487
 
488
           mov ebx, [str]
489
           mov [ebx+STREAM.notify_event], eax
490
           mov [ebx+STREAM.notify_id], edx
491
 
492
           mov [ebx+STREAM.magic], 'WAVE'
493
           mov [ebx+STREAM.destroy], DestroyBuffer.destroy
494
           mov [ebx+STREAM.size], STREAM_SIZE
495
           mov [ebx+STREAM.flags], SND_STOP
496
 
497
           pushf
498
           cli
499
           mov eax, str.fd-FD_OFFSET
500
           mov edx, [eax+STREAM.str_fd]
501
           mov [ebx+STREAM.str_fd], edx
502
           mov [ebx+STREAM.str_bk], eax
503
           mov [eax+STREAM.str_fd], ebx
504
           mov [edx+STREAM.str_bk], ebx
505
           popf
506
 
507
           xor eax, eax
227 serge 508
           ret
168 serge 509
.fail:
378 serge 510
           xor ebx, ebx
511
           or eax, -1
227 serge 512
           ret
168 serge 513
endp
514
 
291 serge 515
;param
516
; eax= buffer handle
517
 
168 serge 518
align 4
291 serge 519
DestroyBuffer:
328 serge 520
           .handle  equ esp       ;local
168 serge 521
 
378 serge 522
           mov [eax+STREAM.flags], SND_STOP
291 serge 523
.destroy:
328 serge 524
           push eax
525
 
378 serge 526
           pushfd
291 serge 527
           cli
528
           mov ebx, [eax+STREAM.str_fd]
529
           mov ecx, [eax+STREAM.str_bk]
530
           mov [ebx+STREAM.str_bk], ecx
531
           mov [ecx+STREAM.str_fd], ebx
532
           popf
168 serge 533
 
378 serge 534
           stdcall KernelFree, [eax+STREAM.in_base]
328 serge 535
           mov eax, [.handle]
378 serge 536
           stdcall KernelFree, [eax+STREAM.out_base]
328 serge 537
 
538
           pop eax               ;restore stack
378 serge 539
           call DestroyObject    ;eax= stream
540
           xor eax, eax
541
           ret
168 serge 542
.fail:
378 serge 543
           or eax, -1
227 serge 544
           ret
378 serge 545
restore .handle
168 serge 546
 
547
align 4
378 serge 548
proc SetFormat stdcall, str:dword, format:dword
168 serge 549
 
378 serge 550
           cmp word [format], PCM_1_8_8
551
           ja .fail
168 serge 552
 
378 serge 553
           mov edx, [str]
554
           mov [edx+STREAM.flags], SND_STOP
168 serge 555
 
378 serge 556
           test [edx+STREAM.format], PCM_RING
557
           jnz .fail
168 serge 558
 
378 serge 559
;           mov eax,[edx+STREAM.out_base]
560
;           mov [edx+STREAM.out_wp], eax
561
;           mov [edx+STREAM.out_rp], eax
562
;           mov [edx+STREAM.out_count], 0
168 serge 563
 
378 serge 564
           movzx eax, word [format]
565
           mov word [edx+STREAM.format], ax
566
 
567
           xor ebx, ebx
568
           cmp eax, 19
569
           jb @f
570
           mov ebx, 0x80808080
168 serge 571
@@:
378 serge 572
           mov [edx+STREAM.r_silence], ebx
168 serge 573
 
378 serge 574
           shl eax, 2
575
           lea eax, [eax+eax*2]     ;eax*=12
168 serge 576
 
378 serge 577
           mov edi, [resampler_params+eax]
578
           mov ecx, [resampler_params+eax+4]
579
           mov ebx, [resampler_params+eax+8]
168 serge 580
 
378 serge 581
           mov [edx+STREAM.r_size],edi
582
           mov [edx+STREAM.r_dt],  ecx
583
           mov [edx+STREAM.resample], ebx
168 serge 584
 
378 serge 585
           mov edi, [edx+STREAM.in_base]
586
           mov ecx, 128/4
587
           mov eax, [edx+STREAM.r_silence]
285 serge 588
           cld
589
           rep stosd
227 serge 590
           xor eax, eax
591
           ret
168 serge 592
.fail:
378 serge 593
           or eax, -1
227 serge 594
           ret
168 serge 595
endp
596
 
378 serge 597
; for static buffers only
598
; use waveout for streams
599
 
168 serge 600
align 4
378 serge 601
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
168 serge 602
 
378 serge 603
           mov edx, [str]
604
           test [edx+STREAM.format], PCM_OUT
605
           jnz .fail
168 serge 606
 
378 serge 607
           mov esi, [src]
608
           mov edi, [offs]
609
           add edi, [edx+STREAM.in_base]
610
           add edi, 128
168 serge 611
 
378 serge 612
           cmp edi, [edx+STREAM.in_top]
613
           jae .fail
168 serge 614
 
378 serge 615
           mov ecx, [size]
616
           lea ebx, [ecx+edi]
617
           sub ebx, [edx+STREAM.in_top]
618
           jb @F
619
           sub ecx, ebx
620
@@:
621
           shr ecx, 2
622
           cld
623
           rep movsd
624
           xor eax,eax
227 serge 625
           ret
168 serge 626
.fail:
378 serge 627
           or eax, -1
227 serge 628
           ret
168 serge 629
endp
630
 
378 serge 631
; for stream buffers only
632
 
168 serge 633
align 4
378 serge 634
proc wave_out stdcall, str:dword,src:dword,size:dword
635
           locals
636
             state_saved  dd ?
637
             fpu_state    rb 528
638
           endl
168 serge 639
 
227 serge 640
           mov edx, [str]
378 serge 641
           mov eax, [edx+STREAM.format]
568 serge 642
           test eax, PCM_OUT
643
           jz .fail
168 serge 644
 
378 serge 645
           cmp ax, PCM_ALL
646
           je .fail
168 serge 647
 
227 serge 648
           mov esi,[src]
649
           test esi, esi
650
           jz .fail
168 serge 651
 
465 serge 652
           cmp esi, OS_BASE
575 serge 653
           jae .fail
168 serge 654
 
378 serge 655
           mov [state_saved], 0
168 serge 656
 
378 serge 657
.main_loop:
658
           mov edx, [str]
168 serge 659
 
378 serge 660
           mov ebx, [size]
661
           test ebx, ebx
662
           jz .done
663
 
664
           cmp [edx+STREAM.flags], SND_STOP
665
           jne .fill
666
 
667
           mov edi, [edx+STREAM.in_base]
668
           mov ecx, 128/4
669
           mov eax, [edx+STREAM.r_silence]
670
           cld
671
           rep stosd
672
 
673
           mov ecx, [edx+STREAM.in_size]
674
           sub ecx, 128
675
           mov [edx+STREAM.in_wp], edi
676
           mov [edx+STREAM.in_rp], edi
677
           mov [edx+STREAM.in_count], 0
678
           mov [edx+STREAM.in_free], ecx
679
 
680
           mov eax,[edx+STREAM.out_base]
681
           mov [edx+STREAM.out_wp], eax
682
           mov [edx+STREAM.out_rp], eax
683
           mov [edx+STREAM.out_count], 0
684
.fill:
685
           mov ecx, [edx+STREAM.in_free]
686
           test ecx, ecx
687
           jz .wait
688
 
689
           cmp ecx, ebx
690
           jbe @F
691
 
692
           mov ecx, ebx
693
@@:
285 serge 694
           sub [size], ecx
378 serge 695
           add [edx+STREAM.in_count], ecx
696
           sub [edx+STREAM.in_free], ecx
168 serge 697
 
285 serge 698
           shr ecx, 2
378 serge 699
           mov edi, [edx+STREAM.in_wp]
700
           mov esi, [src]
285 serge 701
           cld
702
           rep movsd
378 serge 703
 
704
           mov [src], esi
705
           cmp edi, [edx+STREAM.in_top]
706
           jb @F
707
           sub edi, [edx+STREAM.in_size]
285 serge 708
@@:
378 serge 709
           mov [edx+STREAM.in_wp], edi
168 serge 710
 
378 serge 711
           cmp [edx+STREAM.out_count], 32768
712
           jae .skip
713
 
714
           cmp [state_saved], 0
715
           jne @F
716
           lea eax, [fpu_state+15]
717
           and eax, -16
718
           call FpuSave
719
           mov [state_saved], 1
720
@@:
721
           stdcall refill, edx
722
.skip:
575 serge 723
           mov edx, [str]
724
           mov [edx+STREAM.flags], SND_PLAY
378 serge 725
           cmp [eng_state], SND_PLAY
726
           je .main_loop
727
 
728
           stdcall dev_play, [hSound]
729
           mov [eng_state], SND_PLAY
730
           jmp .main_loop
731
.wait:
732
           mov edx, [str]
733
           mov eax, [edx+STREAM.notify_event]
734
           mov ebx, [edx+STREAM.notify_id]
735
           call WaitEvent   ;eax ebx
736
           jmp .main_loop
285 serge 737
.done:
378 serge 738
           cmp [state_saved], 1
739
           jne @F
740
 
741
           lea eax, [fpu_state+15]
742
           and eax, -16
743
           call FpuRestore
744
@@:
227 serge 745
           xor eax, eax
378 serge 746
           ret
747
.fail:
748
           or eax, -1
749
           ret
750
endp
751
 
752
; both static and stream
753
; reset all but not clear buffers
754
 
755
 
756
; flags reserved
757
;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
758
;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
759
;  RESET_ALL    equ 3
760
 
761
 
762
align 4
763
proc ResetBuffer stdcall, str:dword, flags:dword
764
 
765
           mov edx, [str]
766
           mov [edx+STREAM.flags], SND_STOP
767
 
768
           mov edi, [edx+STREAM.in_base]
769
           mov ecx, 128/4
770
           mov eax, [edx+STREAM.r_silence]
771
           cld
772
           rep stosd
773
 
774
           mov [edx+STREAM.in_wp], edi
775
           mov [edx+STREAM.in_rp], edi
776
 
567 serge 777
           test [edx+STREAM.flags], PCM_STATIC
778
           jnz .static
378 serge 779
           mov [edx+STREAM.in_count], 0
567 serge 780
           jmp @F
781
.static:
378 serge 782
           mov eax, [edx+STREAM.in_size]
567 serge 783
           mov [edx+STREAM.in_count], eax
784
@@:
785
 
786
           mov eax, [edx+STREAM.in_size]
378 serge 787
           sub eax, 128
788
           mov [edx+STREAM.in_free], eax
789
 
790
           xor eax, eax
791
           mov ebx,[edx+STREAM.out_base]
792
           mov [edx+STREAM.out_wp], ebx
793
           mov [edx+STREAM.out_rp], ebx
794
           mov [edx+STREAM.out_count], eax
795
           ret
796
.fail:
797
           or eax, -1
798
           ret
799
endp
800
 
801
; for static buffers only
802
 
803
align 4
804
proc SetBufferPos stdcall, str:dword, pos:dword
805
 
806
           mov edx, [str]
568 serge 807
           test [edx+STREAM.format], PCM_STATIC
808
           jz .fail
378 serge 809
 
810
           mov [edx+STREAM.flags], SND_STOP
811
 
812
           mov eax, [pos]
813
           add eax, [edx+STREAM.in_base]
814
           mov ebx, [edx+STREAM.in_top]
815
           add eax, 128
816
 
817
           cmp eax, ebx
818
           jae .fail
819
 
820
           mov [edx+STREAM.in_rp], eax
821
           sub ebx, eax
822
           mov [edx+STREAM.in_count], ebx
823
           xor eax, eax
824
           ret
825
.fail:
826
           or eax, -1
827
           ret
828
endp
829
 
830
align 4
831
proc GetBufferPos stdcall, str:dword
832
 
833
           mov edx, [str]
568 serge 834
           test [edx+STREAM.format], PCM_STATIC
835
           jz .fail
378 serge 836
 
837
           mov ebx, [edx+STREAM.in_rp]
567 serge 838
           sub ebx, [edx+STREAM.in_base]
839
           sub ebx, 128
378 serge 840
           xor eax, eax
841
           ret
842
.fail:
843
           xor ebx,ebx
844
           or eax, -1
845
           ret
846
endp
847
 
848
; both
849
 
850
align 4
851
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
852
 
853
           mov edx, [str]
854
           stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
855
           ret
856
endp
857
 
858
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
859
           locals
860
             _600    dd ?
861
             _32767  dd ?
862
             state   rb 108
863
           endl
864
 
865
           mov [_600], 0x44160000   ;600.0
866
           mov [_32767], 32767
867
 
868
           lea ebx, [state]
869
           fnsave [ebx]
870
 
871
           movq mm0, qword [l_vol]
872
           pminsw mm0, qword [vol_max]
873
           pmaxsw mm0, qword [vol_min]
874
           movq qword [l_vol], mm0
875
           movq qword [edx+STREAM.l_vol], mm0
876
 
877
           movd mm1,[pan]
878
           pminsw mm1, qword [pan_max]
879
           pmaxsw mm1, qword [vol_min]
880
           movd [edx+STREAM.pan], mm1
881
 
882
           cmp word [edx+STREAM.pan], 0
883
           jl @F
884
 
885
           psubsw mm0,mm1
886
           pminsw mm0, qword [vol_max]
887
           pmaxsw mm0, qword [vol_min]
888
           movd [l_vol],mm0
889
           jmp .calc_amp
890
@@:
891
           punpckhdq mm0,mm0
892
           paddsw mm0,mm1
893
           pminsw mm0, qword [vol_max]
894
           pmaxsw mm0, qword [vol_min]
895
           movd [r_vol], mm0
896
.calc_amp:
897
           emms
898
           fild word [l_vol]
899
 
900
           call .calc
901
 
902
           fistp word [edx+STREAM.l_amp]
694 serge 903
           fstp dword [edx+STREAM.l_amp_f]
378 serge 904
           fstp st0
905
 
906
           fild word [r_vol]
907
 
908
           call .calc
909
 
910
           fistp word [edx+STREAM.r_amp]
694 serge 911
           fstp dword [edx+STREAM.r_amp_f]
378 serge 912
           fstp st0
913
 
914
           fnclex
915
           lea ebx, [state]
916
           frstor [ebx]
917
 
918
           xor eax, eax
227 serge 919
           inc eax
920
           ret
378 serge 921
.calc:
922
           fdiv dword [_600]
923
           fld st0
924
           frndint
925
           fxch st1
926
           fsub st, st1
927
           f2xm1
928
           fld1
929
           faddp st1, st0
930
           fscale
694 serge 931
           fld st0
378 serge 932
           fimul dword [_32767]
933
           ret 0
934
endp
935
 
936
align 4
937
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
938
 
939
           mov edx, [str]
940
           mov eax, [p_lvol]
941
           movsx ecx, word [edx+STREAM.l_vol]
942
           mov [eax], ecx
943
 
944
           mov eax, [p_rvol]
945
           movsx ecx, word [edx+STREAM.r_vol]
946
           mov [eax], ecx
947
           xor eax, eax
948
           ret
949
endp
950
 
951
align 4
952
proc SetBufferPan stdcall, str:dword,pan:dword
953
 
954
           mov edx, [str]
955
           stdcall set_vol_param,[edx+STREAM.l_vol],\
956
                                 [edx+STREAM.r_vol],[pan]
957
           ret
958
endp
959
 
960
; for static and ring buffers only
961
 
962
align 4
963
proc play_buffer stdcall, str:dword, flags:dword
964
 
965
           mov ebx, [str]
966
           mov eax, [ebx+STREAM.format]
967
           test eax, PCM_OUT
968
           jnz .fail
969
 
970
           cmp ax, PCM_ALL
971
           je .fail
972
 
973
           mov [ebx+STREAM.flags], SND_PLAY
974
           cmp [eng_state], SND_PLAY
975
           je .done
976
 
977
           stdcall  dev_play, [hSound]
978
           mov [eng_state], SND_PLAY
979
.done:
980
           test [flags], PLAY_SYNC
981
           jz @F
982
 
983
           mov edx, [str]
984
.wait:
985
           mov eax, [edx+STREAM.notify_event]
986
           mov ebx, [edx+STREAM.notify_id]
987
           call WaitEvent   ;eax ebx
988
 
989
           mov edx, [str]
990
           cmp [edx+STREAM.flags], SND_STOP
991
           jne .wait
992
@@:
993
           xor eax, eax
994
           ret
168 serge 995
.fail:
378 serge 996
           or eax, -1
997
           ret
998
endp
999
 
567 serge 1000
; for static and ring buffers only
378 serge 1001
 
1002
align 4
1003
proc stop_buffer stdcall, str:dword
1004
 
1005
           mov edx, [str]
1006
           test [edx+STREAM.format], PCM_STATIC+PCM_RING
1007
           jz .fail
1008
 
1009
           mov [edx+STREAM.flags], SND_STOP
1010
 
1011
;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
1012
 
1013
           mov eax, [edx+STREAM.notify_event]
1014
           mov ebx, [edx+STREAM.notify_id]
1015
           call ClearEvent   ;eax ebx
1016
 
227 serge 1017
           xor eax, eax
1018
           ret
378 serge 1019
.fail:
1020
           or eax, -1
1021
           ret
168 serge 1022
endp
1023
 
378 serge 1024
; parm
1025
;  eax= mix_list
1026
 
168 serge 1027
align 4
378 serge 1028
do_mix_list:
1029
 
1030
           xor edx, edx
1031
           mov esi, str.fd-FD_OFFSET
1032
           mov ebx, [esi+STREAM.str_fd]
1033
@@:
1034
           cmp ebx, esi
1035
           je .done
1036
 
1037
           cmp [ebx+STREAM.magic], 'WAVE'
1038
           jne .next
1039
 
1040
           cmp [ebx+STREAM.size], STREAM_SIZE
1041
           jne .next
1042
 
1043
           cmp [ebx+STREAM.flags], SND_PLAY;
1044
           jne .next
1045
 
1046
           mov ecx, [ebx+STREAM.out_count]
1047
           test ecx, ecx
1048
           jnz .l1
1049
 
1050
           test [ebx+STREAM.format], PCM_RING
1051
           jnz .next
1052
           mov [ebx+STREAM.flags], SND_STOP
1053
           jmp .next
1054
.l1:
1055
           cmp ecx, 512
1056
           jae .add_buff
1057
 
1058
           mov edi, [ebx+STREAM.out_rp]
1059
           add edi, ecx
1060
           sub ecx, 512
1061
           neg ecx
1062
           push eax
1063
           xor eax, eax
1064
           cld
1065
           rep stosb
1066
           pop eax
1067
 
1068
           mov [ebx+STREAM.out_count], 512
1069
 
1070
.add_buff:
1071
           mov ecx, [ebx+STREAM.out_rp]
1072
           mov [eax],ecx
694 serge 1073
 
1074
if USE_SSE2_MIXER
1075
           mov edi, dword [ebx+STREAM.l_amp_f]
1076
           mov [eax+4], edi
1077
           mov edi, dword [ebx+STREAM.r_amp_f]
1078
           mov [eax+8], edi
1079
else
378 serge 1080
           mov edi, dword [ebx+STREAM.l_amp]
1081
           mov [eax+4], edi
694 serge 1082
end if
378 serge 1083
           add [ebx+STREAM.out_rp], 512
1084
           sub [ebx+STREAM.out_count], 512
1085
 
694 serge 1086
           add eax, 12
378 serge 1087
           inc edx
1088
.next:
1089
           mov ebx, [ebx+STREAM.str_fd]
1090
           jmp @B
1091
.done:
1092
           mov eax, edx
1093
           ret
1094
 
1095
align 4
291 serge 1096
prepare_playlist:
168 serge 1097
 
227 serge 1098
           xor edx, edx
291 serge 1099
           mov [play_count], edx
1100
           mov esi, str.fd-FD_OFFSET
1101
           mov edi, [esi+STREAM.str_fd]
1102
@@:
1103
           cmp edi, esi
1104
           je .done
168 serge 1105
 
291 serge 1106
           cmp [edi+STREAM.magic], 'WAVE'
168 serge 1107
           jne .next
1108
 
291 serge 1109
           cmp [edi+STREAM.size], STREAM_SIZE
168 serge 1110
           jne .next
1111
 
291 serge 1112
           cmp [edi+STREAM.flags], SND_PLAY;
227 serge 1113
           jne .next
168 serge 1114
 
291 serge 1115
           mov [play_list+edx], edi
227 serge 1116
           inc [play_count]
1117
           add edx, 4
168 serge 1118
.next:
291 serge 1119
           mov edi, [edi+STREAM.str_fd]
1120
           jmp @B
1121
.done:
227 serge 1122
           ret
168 serge 1123
 
1124
align 4
1125
proc set_handler stdcall, hsrv:dword, handler_proc:dword
1126
           locals
1127
             handler    dd ?
1128
             io_code    dd ?
1129
             input      dd ?
1130
             inp_size   dd ?
1131
             output     dd ?
1132
             out_size   dd ?
1133
             val        dd ?
1134
           endl
1135
 
1136
           mov eax, [hsrv]
1137
           lea ecx, [handler_proc]
1138
           xor ebx, ebx
1139
 
1140
           mov [handler], eax
1141
           mov [io_code], DEV_CALLBACK
1142
           mov [input], ecx
1143
           mov [inp_size], 4
1144
           mov [output], ebx
1145
           mov [out_size], 0
1146
 
1147
           lea eax, [handler]
188 serge 1148
           stdcall ServiceHandler, eax
168 serge 1149
           ret
1150
endp
1151
 
1152
align 4
1153
proc dev_play stdcall, hsrv:dword
1154
           locals
1155
             handle     dd ?
1156
             io_code    dd ?
1157
             input      dd ?
1158
             inp_size   dd ?
1159
             output     dd ?
1160
             out_size   dd ?
1161
             val        dd ?
1162
           endl
1163
 
1164
           mov eax, [hsrv]
1165
           xor ebx, ebx
1166
 
1167
           mov [handle], eax
1168
           mov [io_code], DEV_PLAY
1169
           mov [input], ebx
1170
           mov [inp_size], ebx
1171
           mov [output], ebx
1172
           mov [out_size], ebx
1173
 
1174
           lea eax, [handle]
188 serge 1175
           stdcall ServiceHandler, eax
168 serge 1176
           ret
1177
endp
1178
 
378 serge 1179
if 0
1180
align 4
1181
dword2str:
1182
      mov  esi, hex_buff
1183
      mov ecx, -8
1184
@@:
1185
      rol eax, 4
1186
      mov ebx, eax
1187
      and ebx, 0x0F
1188
      mov bl, [ebx+hexletters]
1189
      mov [8+esi+ecx], bl
1190
      inc ecx
1191
      jnz @B
1192
      ret
1193
 
1194
hexletters   db '0123456789ABCDEF'
1195
hex_buff     db 8 dup(0),13,10,0
1196
 
1197
end if
1198
 
168 serge 1199
include 'mixer.asm'
293 serge 1200
include 'mix_mmx.inc'
1201
include 'mix_sse2.inc'
168 serge 1202
 
291 serge 1203
;if USE_SSE
1204
; include 'mix_sse.inc'
1205
;end if
1206
 
168 serge 1207
align 16
1208
resampler_params:
378 serge 1209
     ;r_size    r_dt   resampler_func
1210
     dd 0,0,0                                  ; 0  PCM_ALL
1211
     dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
1212
     dd 16384,      0, m16_stereo     ; 2  PCM_1_16_48
168 serge 1213
 
378 serge 1214
     dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
1215
     dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
168 serge 1216
 
378 serge 1217
     dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
1218
     dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
168 serge 1219
 
378 serge 1220
     dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
1221
     dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
168 serge 1222
 
378 serge 1223
     dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
1224
     dd  4096,  15052, resample_1     ;10  PCM_1_16_22
168 serge 1225
 
378 serge 1226
     dd  8192,  10923, resample_2     ;11  PCM_2_16_16
1227
     dd  4096,  10923, resample_1     ;12  PCM_1_16_16
168 serge 1228
 
378 serge 1229
     dd  8192,   8192, resample_2     ;13  PCM_2_16_12
1230
     dd  4096,   8192, resample_1     ;14  PCM_1_16_12
168 serge 1231
 
378 serge 1232
     dd  4096,   7527, resample_2     ;15  PCM_2_16_11
1233
     dd  2048,   7527, resample_1     ;16  PCM_1_16_11
168 serge 1234
 
378 serge 1235
     dd  4096,   5462, resample_2     ;17  PCM_2_16_8
1236
     dd  2048,   5462, resample_1     ;18  PCM_1_16_8
168 serge 1237
 
378 serge 1238
     dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
1239
     dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
168 serge 1240
 
378 serge 1241
     dd  8192,  30109, resample_28    ;21  PCM_2_8_44
1242
     dd  4096,  30109, resample_18    ;22  PCM_1_8_44
168 serge 1243
 
378 serge 1244
     dd  8192,  21846, resample_28    ;23  PCM_2_8_32
1245
     dd  4096,  21846, resample_18    ;24  PCM_1_8_32
168 serge 1246
 
378 serge 1247
     dd  8192,  16384, resample_28    ;25  PCM_2_8_24
1248
     dd  4096,  16384, resample_18    ;26  PCM_1_8_24
168 serge 1249
 
378 serge 1250
     dd  4096,  15052, resample_28    ;27  PCM_2_8_22
1251
     dd  2048,  15052, resample_18    ;28  PCM_1_8_22
168 serge 1252
 
378 serge 1253
     dd  4096,  10923, resample_28    ;29  PCM_2_8_16
1254
     dd  2048,  10923, resample_18    ;30  PCM_1_8_16
168 serge 1255
 
378 serge 1256
     dd  4096,   8192, resample_28    ;31  PCM_2_8_12
1257
     dd  2048,   8192, resample_18    ;32  PCM_1_8_12
168 serge 1258
 
378 serge 1259
     dd  2048,   7527, resample_28    ;33  PCM_2_8_11
1260
     dd  1024,   7527, resample_18    ;34  PCM_1_8_11
168 serge 1261
 
378 serge 1262
     dd  2048,   5462, resample_28    ;35  PCM_2_8_8
1263
     dd  1024,   5462, resample_18    ;36  PCM_1_8_8
168 serge 1264
 
281 serge 1265
m7            dw 0x8000,0x8000,0x8000,0x8000
1266
mm80          dq 0x8080808080808080
1267
mm_mask       dq 0xFF00FF00FF00FF00
168 serge 1268
 
378 serge 1269
vol_max       dd 0x00000000,0x00000000
1270
vol_min       dd 0x0000D8F0,0x0000D8F0
1271
pan_max       dd 0x00002710,0x00002710
1272
 
291 serge 1273
;stream_map    dd 0xFFFF       ; 16
574 serge 1274
version       dd (5 shl 16) or SOUND_VERSION
168 serge 1275
 
281 serge 1276
szInfinity    db 'INFINITY',0
1277
szSound       db 'SOUND',0
168 serge 1278
 
1279
if DEBUG
281 serge 1280
msgFail       db 'Sound service not loaded',13,10,0
1281
msgPlay       db 'Play buffer',13,10,0
1282
msgStop       db 'Stop',13,10,0
1283
msgUser       db 'User callback',13,10,0
1284
msgMem        db 'Not enough memory',13,10,0
291 serge 1285
msgDestroy    db 'Destroy sound buffer', 13,10,0
378 serge 1286
msgWaveout    db 'Play waveout', 13,10,0
1287
msgSetVolume  db 'Set volume',13,10,0
168 serge 1288
end if
188 serge 1289
 
1290
section '.data' data readable writable align 16
1291
 
281 serge 1292
play_list     rd 16
1293
mix_input     rd 16
1294
play_count    rd 1
1295
hSound        rd 1
378 serge 1296
eng_state     rd 1
281 serge 1297
mix_buff      rd 1
1298
mix_buff_map  rd 1
291 serge 1299
str.fd        rd 1
1300
str.bk        rd 1
188 serge 1301
 
293 serge 1302
mix_2_core    rd 1
1303
mix_3_core    rd 1
1304
mix_4_core    rd 1
291 serge 1305