Subversion Repositories Kolibri OS

Rev

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