Subversion Repositories Kolibri OS

Rev

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