Subversion Repositories Kolibri OS

Rev

Rev 695 | 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
 
378 serge 481
           xor edx, edx
482
           mov ebx, MANUAL_DESTROY
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:
682
           mov ecx, [edx+STREAM.in_free]
683
           test ecx, ecx
684
           jz .wait
685
 
686
           cmp ecx, ebx
687
           jbe @F
688
 
689
           mov ecx, ebx
690
@@:
285 serge 691
           sub [size], ecx
378 serge 692
           add [edx+STREAM.in_count], ecx
693
           sub [edx+STREAM.in_free], ecx
168 serge 694
 
285 serge 695
           shr ecx, 2
378 serge 696
           mov edi, [edx+STREAM.in_wp]
697
           mov esi, [src]
285 serge 698
           cld
699
           rep movsd
378 serge 700
 
701
           mov [src], esi
702
           cmp edi, [edx+STREAM.in_top]
703
           jb @F
704
           sub edi, [edx+STREAM.in_size]
285 serge 705
@@:
378 serge 706
           mov [edx+STREAM.in_wp], edi
168 serge 707
 
378 serge 708
           cmp [edx+STREAM.out_count], 32768
709
           jae .skip
710
 
711
           cmp [state_saved], 0
712
           jne @F
713
           lea eax, [fpu_state+15]
714
           and eax, -16
715
           call FpuSave
716
           mov [state_saved], 1
717
@@:
718
           stdcall refill, edx
719
.skip:
575 serge 720
           mov edx, [str]
721
           mov [edx+STREAM.flags], SND_PLAY
378 serge 722
           cmp [eng_state], SND_PLAY
723
           je .main_loop
724
 
725
           stdcall dev_play, [hSound]
726
           mov [eng_state], SND_PLAY
727
           jmp .main_loop
728
.wait:
729
           mov edx, [str]
730
           mov eax, [edx+STREAM.notify_event]
731
           mov ebx, [edx+STREAM.notify_id]
732
           call WaitEvent   ;eax ebx
733
           jmp .main_loop
285 serge 734
.done:
378 serge 735
           cmp [state_saved], 1
736
           jne @F
737
 
738
           lea eax, [fpu_state+15]
739
           and eax, -16
740
           call FpuRestore
741
@@:
227 serge 742
           xor eax, eax
378 serge 743
           ret
744
.fail:
745
           or eax, -1
746
           ret
747
endp
748
 
749
; both static and stream
750
; reset all but not clear buffers
751
 
752
 
753
; flags reserved
754
;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
755
;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
756
;  RESET_ALL    equ 3
757
 
758
 
759
align 4
760
proc ResetBuffer stdcall, str:dword, flags:dword
761
 
762
           mov edx, [str]
763
           mov [edx+STREAM.flags], SND_STOP
764
 
765
           mov edi, [edx+STREAM.in_base]
766
           mov ecx, 128/4
767
           mov eax, [edx+STREAM.r_silence]
768
           cld
769
           rep stosd
770
 
771
           mov [edx+STREAM.in_wp], edi
772
           mov [edx+STREAM.in_rp], edi
773
 
567 serge 774
           test [edx+STREAM.flags], PCM_STATIC
775
           jnz .static
378 serge 776
           mov [edx+STREAM.in_count], 0
567 serge 777
           jmp @F
778
.static:
378 serge 779
           mov eax, [edx+STREAM.in_size]
567 serge 780
           mov [edx+STREAM.in_count], eax
781
@@:
782
 
783
           mov eax, [edx+STREAM.in_size]
378 serge 784
           sub eax, 128
785
           mov [edx+STREAM.in_free], eax
786
 
787
           xor eax, eax
788
           mov ebx,[edx+STREAM.out_base]
789
           mov [edx+STREAM.out_wp], ebx
790
           mov [edx+STREAM.out_rp], ebx
791
           mov [edx+STREAM.out_count], eax
792
           ret
793
.fail:
794
           or eax, -1
795
           ret
796
endp
797
 
798
; for static buffers only
799
 
800
align 4
801
proc SetBufferPos stdcall, str:dword, pos:dword
802
 
803
           mov edx, [str]
568 serge 804
           test [edx+STREAM.format], PCM_STATIC
805
           jz .fail
378 serge 806
 
807
           mov [edx+STREAM.flags], SND_STOP
808
 
809
           mov eax, [pos]
810
           add eax, [edx+STREAM.in_base]
811
           mov ebx, [edx+STREAM.in_top]
812
           add eax, 128
813
 
814
           cmp eax, ebx
815
           jae .fail
816
 
817
           mov [edx+STREAM.in_rp], eax
818
           sub ebx, eax
819
           mov [edx+STREAM.in_count], ebx
820
           xor eax, eax
821
           ret
822
.fail:
823
           or eax, -1
824
           ret
825
endp
826
 
827
align 4
828
proc GetBufferPos stdcall, str:dword
829
 
830
           mov edx, [str]
568 serge 831
           test [edx+STREAM.format], PCM_STATIC
832
           jz .fail
378 serge 833
 
834
           mov ebx, [edx+STREAM.in_rp]
567 serge 835
           sub ebx, [edx+STREAM.in_base]
836
           sub ebx, 128
378 serge 837
           xor eax, eax
838
           ret
839
.fail:
840
           xor ebx,ebx
841
           or eax, -1
842
           ret
843
endp
844
 
845
; both
846
 
847
align 4
848
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
849
 
850
           mov edx, [str]
851
           stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
852
           ret
853
endp
854
 
855
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
856
           locals
857
             _600    dd ?
858
             _32767  dd ?
859
             state   rb 108
860
           endl
861
 
862
           mov [_600], 0x44160000   ;600.0
863
           mov [_32767], 32767
864
 
865
           lea ebx, [state]
866
           fnsave [ebx]
867
 
868
           movq mm0, qword [l_vol]
869
           pminsw mm0, qword [vol_max]
870
           pmaxsw mm0, qword [vol_min]
871
           movq qword [l_vol], mm0
872
           movq qword [edx+STREAM.l_vol], mm0
873
 
874
           movd mm1,[pan]
875
           pminsw mm1, qword [pan_max]
876
           pmaxsw mm1, qword [vol_min]
877
           movd [edx+STREAM.pan], mm1
878
 
879
           cmp word [edx+STREAM.pan], 0
880
           jl @F
881
 
882
           psubsw mm0,mm1
883
           pminsw mm0, qword [vol_max]
884
           pmaxsw mm0, qword [vol_min]
885
           movd [l_vol],mm0
886
           jmp .calc_amp
887
@@:
888
           punpckhdq mm0,mm0
889
           paddsw mm0,mm1
890
           pminsw mm0, qword [vol_max]
891
           pmaxsw mm0, qword [vol_min]
892
           movd [r_vol], mm0
893
.calc_amp:
894
           emms
895
           fild word [l_vol]
896
 
897
           call .calc
898
 
899
           fistp word [edx+STREAM.l_amp]
694 serge 900
           fstp dword [edx+STREAM.l_amp_f]
378 serge 901
           fstp st0
902
 
903
           fild word [r_vol]
904
 
905
           call .calc
906
 
907
           fistp word [edx+STREAM.r_amp]
694 serge 908
           fstp dword [edx+STREAM.r_amp_f]
378 serge 909
           fstp st0
910
 
911
           fnclex
912
           lea ebx, [state]
913
           frstor [ebx]
914
 
915
           xor eax, eax
227 serge 916
           inc eax
917
           ret
378 serge 918
.calc:
919
           fdiv dword [_600]
920
           fld st0
921
           frndint
922
           fxch st1
923
           fsub st, st1
924
           f2xm1
925
           fld1
926
           faddp st1, st0
927
           fscale
694 serge 928
           fld st0
378 serge 929
           fimul dword [_32767]
930
           ret 0
931
endp
932
 
933
align 4
934
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
935
 
936
           mov edx, [str]
937
           mov eax, [p_lvol]
938
           movsx ecx, word [edx+STREAM.l_vol]
939
           mov [eax], ecx
940
 
941
           mov eax, [p_rvol]
942
           movsx ecx, word [edx+STREAM.r_vol]
943
           mov [eax], ecx
944
           xor eax, eax
945
           ret
946
endp
947
 
948
align 4
949
proc SetBufferPan stdcall, str:dword,pan:dword
950
 
951
           mov edx, [str]
952
           stdcall set_vol_param,[edx+STREAM.l_vol],\
953
                                 [edx+STREAM.r_vol],[pan]
954
           ret
955
endp
956
 
957
; for static and ring buffers only
958
 
959
align 4
960
proc play_buffer stdcall, str:dword, flags:dword
961
 
962
           mov ebx, [str]
963
           mov eax, [ebx+STREAM.format]
964
           test eax, PCM_OUT
965
           jnz .fail
966
 
967
           cmp ax, PCM_ALL
968
           je .fail
969
 
970
           mov [ebx+STREAM.flags], SND_PLAY
971
           cmp [eng_state], SND_PLAY
972
           je .done
973
 
974
           stdcall  dev_play, [hSound]
975
           mov [eng_state], SND_PLAY
976
.done:
977
           test [flags], PLAY_SYNC
978
           jz @F
979
 
980
           mov edx, [str]
981
.wait:
982
           mov eax, [edx+STREAM.notify_event]
983
           mov ebx, [edx+STREAM.notify_id]
984
           call WaitEvent   ;eax ebx
985
 
986
           mov edx, [str]
987
           cmp [edx+STREAM.flags], SND_STOP
988
           jne .wait
989
@@:
990
           xor eax, eax
991
           ret
168 serge 992
.fail:
378 serge 993
           or eax, -1
994
           ret
995
endp
996
 
567 serge 997
; for static and ring buffers only
378 serge 998
 
999
align 4
1000
proc stop_buffer stdcall, str:dword
1001
 
1002
           mov edx, [str]
1003
           test [edx+STREAM.format], PCM_STATIC+PCM_RING
1004
           jz .fail
1005
 
1006
           mov [edx+STREAM.flags], SND_STOP
1007
 
1008
;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
1009
 
1010
           mov eax, [edx+STREAM.notify_event]
1011
           mov ebx, [edx+STREAM.notify_id]
1012
           call ClearEvent   ;eax ebx
1013
 
227 serge 1014
           xor eax, eax
1015
           ret
378 serge 1016
.fail:
1017
           or eax, -1
1018
           ret
168 serge 1019
endp
1020
 
695 serge 1021
; param
378 serge 1022
;  eax= mix_list
1023
 
168 serge 1024
align 4
378 serge 1025
do_mix_list:
1026
 
1027
           xor edx, edx
1028
           mov esi, str.fd-FD_OFFSET
1029
           mov ebx, [esi+STREAM.str_fd]
1030
@@:
1031
           cmp ebx, esi
1032
           je .done
1033
 
1034
           cmp [ebx+STREAM.magic], 'WAVE'
1035
           jne .next
1036
 
1037
           cmp [ebx+STREAM.size], STREAM_SIZE
1038
           jne .next
1039
 
1040
           cmp [ebx+STREAM.flags], SND_PLAY;
1041
           jne .next
1042
 
1043
           mov ecx, [ebx+STREAM.out_count]
1044
           test ecx, ecx
1045
           jnz .l1
1046
 
1047
           test [ebx+STREAM.format], PCM_RING
1048
           jnz .next
1049
           mov [ebx+STREAM.flags], SND_STOP
1050
           jmp .next
1051
.l1:
1052
           cmp ecx, 512
1053
           jae .add_buff
1054
 
1055
           mov edi, [ebx+STREAM.out_rp]
1056
           add edi, ecx
1057
           sub ecx, 512
1058
           neg ecx
1059
           push eax
1060
           xor eax, eax
1061
           cld
1062
           rep stosb
1063
           pop eax
1064
 
1065
           mov [ebx+STREAM.out_count], 512
1066
 
1067
.add_buff:
1068
           mov ecx, [ebx+STREAM.out_rp]
1069
           mov [eax],ecx
694 serge 1070
 
1071
if USE_SSE2_MIXER
1072
           mov edi, dword [ebx+STREAM.l_amp_f]
1073
           mov [eax+4], edi
1074
           mov edi, dword [ebx+STREAM.r_amp_f]
1075
           mov [eax+8], edi
1076
else
378 serge 1077
           mov edi, dword [ebx+STREAM.l_amp]
1078
           mov [eax+4], edi
694 serge 1079
end if
378 serge 1080
           add [ebx+STREAM.out_rp], 512
1081
           sub [ebx+STREAM.out_count], 512
1082
 
694 serge 1083
           add eax, 12
378 serge 1084
           inc edx
1085
.next:
1086
           mov ebx, [ebx+STREAM.str_fd]
1087
           jmp @B
1088
.done:
1089
           mov eax, edx
1090
           ret
1091
 
1092
align 4
291 serge 1093
prepare_playlist:
168 serge 1094
 
227 serge 1095
           xor edx, edx
291 serge 1096
           mov [play_count], edx
1097
           mov esi, str.fd-FD_OFFSET
1098
           mov edi, [esi+STREAM.str_fd]
1099
@@:
1100
           cmp edi, esi
1101
           je .done
168 serge 1102
 
291 serge 1103
           cmp [edi+STREAM.magic], 'WAVE'
168 serge 1104
           jne .next
1105
 
291 serge 1106
           cmp [edi+STREAM.size], STREAM_SIZE
168 serge 1107
           jne .next
1108
 
291 serge 1109
           cmp [edi+STREAM.flags], SND_PLAY;
227 serge 1110
           jne .next
168 serge 1111
 
291 serge 1112
           mov [play_list+edx], edi
227 serge 1113
           inc [play_count]
1114
           add edx, 4
168 serge 1115
.next:
291 serge 1116
           mov edi, [edi+STREAM.str_fd]
1117
           jmp @B
1118
.done:
227 serge 1119
           ret
168 serge 1120
 
1121
align 4
1122
proc set_handler stdcall, hsrv:dword, handler_proc:dword
1123
           locals
1124
             handler    dd ?
1125
             io_code    dd ?
1126
             input      dd ?
1127
             inp_size   dd ?
1128
             output     dd ?
1129
             out_size   dd ?
1130
             val        dd ?
1131
           endl
1132
 
1133
           mov eax, [hsrv]
1134
           lea ecx, [handler_proc]
1135
           xor ebx, ebx
1136
 
1137
           mov [handler], eax
1138
           mov [io_code], DEV_CALLBACK
1139
           mov [input], ecx
1140
           mov [inp_size], 4
1141
           mov [output], ebx
1142
           mov [out_size], 0
1143
 
1144
           lea eax, [handler]
188 serge 1145
           stdcall ServiceHandler, eax
168 serge 1146
           ret
1147
endp
1148
 
1149
align 4
1150
proc dev_play stdcall, hsrv:dword
1151
           locals
1152
             handle     dd ?
1153
             io_code    dd ?
1154
             input      dd ?
1155
             inp_size   dd ?
1156
             output     dd ?
1157
             out_size   dd ?
1158
             val        dd ?
1159
           endl
1160
 
1161
           mov eax, [hsrv]
1162
           xor ebx, ebx
1163
 
1164
           mov [handle], eax
1165
           mov [io_code], DEV_PLAY
1166
           mov [input], ebx
1167
           mov [inp_size], ebx
1168
           mov [output], ebx
1169
           mov [out_size], ebx
1170
 
1171
           lea eax, [handle]
188 serge 1172
           stdcall ServiceHandler, eax
168 serge 1173
           ret
1174
endp
1175
 
378 serge 1176
if 0
1177
align 4
1178
dword2str:
1179
      mov  esi, hex_buff
1180
      mov ecx, -8
1181
@@:
1182
      rol eax, 4
1183
      mov ebx, eax
1184
      and ebx, 0x0F
1185
      mov bl, [ebx+hexletters]
1186
      mov [8+esi+ecx], bl
1187
      inc ecx
1188
      jnz @B
1189
      ret
1190
 
1191
hexletters   db '0123456789ABCDEF'
1192
hex_buff     db 8 dup(0),13,10,0
1193
 
1194
end if
1195
 
168 serge 1196
include 'mixer.asm'
293 serge 1197
include 'mix_mmx.inc'
1198
include 'mix_sse2.inc'
168 serge 1199
 
291 serge 1200
;if USE_SSE
1201
; include 'mix_sse.inc'
1202
;end if
1203
 
168 serge 1204
align 16
1205
resampler_params:
378 serge 1206
     ;r_size    r_dt   resampler_func
1207
     dd 0,0,0                                  ; 0  PCM_ALL
1208
     dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
802 serge 1209
     dd  8192,      0, m16_stereo     ; 2  PCM_1_16_48
168 serge 1210
 
378 serge 1211
     dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
1212
     dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
168 serge 1213
 
378 serge 1214
     dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
1215
     dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
168 serge 1216
 
378 serge 1217
     dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
1218
     dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
168 serge 1219
 
378 serge 1220
     dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
1221
     dd  4096,  15052, resample_1     ;10  PCM_1_16_22
168 serge 1222
 
378 serge 1223
     dd  8192,  10923, resample_2     ;11  PCM_2_16_16
1224
     dd  4096,  10923, resample_1     ;12  PCM_1_16_16
168 serge 1225
 
378 serge 1226
     dd  8192,   8192, resample_2     ;13  PCM_2_16_12
1227
     dd  4096,   8192, resample_1     ;14  PCM_1_16_12
168 serge 1228
 
378 serge 1229
     dd  4096,   7527, resample_2     ;15  PCM_2_16_11
1230
     dd  2048,   7527, resample_1     ;16  PCM_1_16_11
168 serge 1231
 
378 serge 1232
     dd  4096,   5462, resample_2     ;17  PCM_2_16_8
1233
     dd  2048,   5462, resample_1     ;18  PCM_1_16_8
168 serge 1234
 
378 serge 1235
     dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
1236
     dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
168 serge 1237
 
378 serge 1238
     dd  8192,  30109, resample_28    ;21  PCM_2_8_44
1239
     dd  4096,  30109, resample_18    ;22  PCM_1_8_44
168 serge 1240
 
378 serge 1241
     dd  8192,  21846, resample_28    ;23  PCM_2_8_32
1242
     dd  4096,  21846, resample_18    ;24  PCM_1_8_32
168 serge 1243
 
378 serge 1244
     dd  8192,  16384, resample_28    ;25  PCM_2_8_24
1245
     dd  4096,  16384, resample_18    ;26  PCM_1_8_24
168 serge 1246
 
378 serge 1247
     dd  4096,  15052, resample_28    ;27  PCM_2_8_22
1248
     dd  2048,  15052, resample_18    ;28  PCM_1_8_22
168 serge 1249
 
378 serge 1250
     dd  4096,  10923, resample_28    ;29  PCM_2_8_16
1251
     dd  2048,  10923, resample_18    ;30  PCM_1_8_16
168 serge 1252
 
378 serge 1253
     dd  4096,   8192, resample_28    ;31  PCM_2_8_12
1254
     dd  2048,   8192, resample_18    ;32  PCM_1_8_12
168 serge 1255
 
378 serge 1256
     dd  2048,   7527, resample_28    ;33  PCM_2_8_11
1257
     dd  1024,   7527, resample_18    ;34  PCM_1_8_11
168 serge 1258
 
378 serge 1259
     dd  2048,   5462, resample_28    ;35  PCM_2_8_8
1260
     dd  1024,   5462, resample_18    ;36  PCM_1_8_8
168 serge 1261
 
281 serge 1262
m7            dw 0x8000,0x8000,0x8000,0x8000
1263
mm80          dq 0x8080808080808080
1264
mm_mask       dq 0xFF00FF00FF00FF00
168 serge 1265
 
378 serge 1266
vol_max       dd 0x00000000,0x00000000
1267
vol_min       dd 0x0000D8F0,0x0000D8F0
1268
pan_max       dd 0x00002710,0x00002710
1269
 
291 serge 1270
;stream_map    dd 0xFFFF       ; 16
574 serge 1271
version       dd (5 shl 16) or SOUND_VERSION
168 serge 1272
 
281 serge 1273
szInfinity    db 'INFINITY',0
1274
szSound       db 'SOUND',0
168 serge 1275
 
1276
if DEBUG
281 serge 1277
msgFail       db 'Sound service not loaded',13,10,0
1278
msgPlay       db 'Play buffer',13,10,0
1279
msgStop       db 'Stop',13,10,0
1280
msgUser       db 'User callback',13,10,0
1281
msgMem        db 'Not enough memory',13,10,0
291 serge 1282
msgDestroy    db 'Destroy sound buffer', 13,10,0
378 serge 1283
msgWaveout    db 'Play waveout', 13,10,0
1284
msgSetVolume  db 'Set volume',13,10,0
168 serge 1285
end if
188 serge 1286
 
1287
section '.data' data readable writable align 16
1288
 
281 serge 1289
play_list     rd 16
1290
mix_input     rd 16
1291
play_count    rd 1
1292
hSound        rd 1
378 serge 1293
eng_state     rd 1
281 serge 1294
mix_buff      rd 1
1295
mix_buff_map  rd 1
291 serge 1296
str.fd        rd 1
1297
str.bk        rd 1
188 serge 1298
 
293 serge 1299
mix_2_core    rd 1
1300
mix_3_core    rd 1
1301
mix_4_core    rd 1
291 serge 1302