Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
168 serge 8
;   (C) copyright Serge 2006
9
;   email: infinity_sound@mail.ru
10
 
11
format MS COFF
12
 
465 serge 13
 
574 serge 14
CURRENT_API     equ   0x0101      ;1.01
15
COMPATIBLE_API  equ   0x0100      ;1.00
465 serge 16
 
574 serge 17
API_VERSION     equ   (COMPATIBLE_API shl 16) or CURRENT_API
18
SOUND_VERSION   equ   CURRENT_API
19
 
20
 
168 serge 21
include 'proc32.inc'
520 serge 22
 
23
;include 'system.inc'
168 serge 24
include 'main.inc'
520 serge 25
 
281 serge 26
include 'imports.inc'
168 serge 27
 
378 serge 28
FORCE_MMX         equ 0  ;set to 1 to force use mmx or
29
FORCE_MMX_128     equ 0  ;integer sse2 extensions
293 serge 30
                        ;and reduce driver size
378 serge 31
;USE_SSE          equ 0
168 serge 32
 
378 serge 33
DEBUG             equ 1
168 serge 34
 
291 serge 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]
900
           fstp st0
901
 
902
           fild word [r_vol]
903
 
904
           call .calc
905
 
906
           fistp word [edx+STREAM.r_amp]
907
           fstp st0
908
 
909
           fnclex
910
           lea ebx, [state]
911
           frstor [ebx]
912
 
913
           xor eax, eax
227 serge 914
           inc eax
915
           ret
378 serge 916
.calc:
917
           fdiv dword [_600]
918
           fld st0
919
           frndint
920
           fxch st1
921
           fsub st, st1
922
           f2xm1
923
           fld1
924
           faddp st1, st0
925
           fscale
926
           fimul dword [_32767]
927
           ret 0
928
endp
929
 
930
align 4
931
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
932
 
933
           mov edx, [str]
934
           mov eax, [p_lvol]
935
           movsx ecx, word [edx+STREAM.l_vol]
936
           mov [eax], ecx
937
 
938
           mov eax, [p_rvol]
939
           movsx ecx, word [edx+STREAM.r_vol]
940
           mov [eax], ecx
941
           xor eax, eax
942
           ret
943
endp
944
 
945
align 4
946
proc SetBufferPan stdcall, str:dword,pan:dword
947
 
948
           mov edx, [str]
949
           stdcall set_vol_param,[edx+STREAM.l_vol],\
950
                                 [edx+STREAM.r_vol],[pan]
951
           ret
952
endp
953
 
954
; for static and ring buffers only
955
 
956
align 4
957
proc play_buffer stdcall, str:dword, flags:dword
958
 
959
           mov ebx, [str]
960
           mov eax, [ebx+STREAM.format]
961
           test eax, PCM_OUT
962
           jnz .fail
963
 
964
           cmp ax, PCM_ALL
965
           je .fail
966
 
967
           mov [ebx+STREAM.flags], SND_PLAY
968
           cmp [eng_state], SND_PLAY
969
           je .done
970
 
971
           stdcall  dev_play, [hSound]
972
           mov [eng_state], SND_PLAY
973
.done:
974
           test [flags], PLAY_SYNC
975
           jz @F
976
 
977
           mov edx, [str]
978
.wait:
979
           mov eax, [edx+STREAM.notify_event]
980
           mov ebx, [edx+STREAM.notify_id]
981
           call WaitEvent   ;eax ebx
982
 
983
           mov edx, [str]
984
           cmp [edx+STREAM.flags], SND_STOP
985
           jne .wait
986
@@:
987
           xor eax, eax
988
           ret
168 serge 989
.fail:
378 serge 990
           or eax, -1
991
           ret
992
endp
993
 
567 serge 994
; for static and ring buffers only
378 serge 995
 
996
align 4
997
proc stop_buffer stdcall, str:dword
998
 
999
           mov edx, [str]
1000
           test [edx+STREAM.format], PCM_STATIC+PCM_RING
1001
           jz .fail
1002
 
1003
           mov [edx+STREAM.flags], SND_STOP
1004
 
1005
;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
1006
 
1007
           mov eax, [edx+STREAM.notify_event]
1008
           mov ebx, [edx+STREAM.notify_id]
1009
           call ClearEvent   ;eax ebx
1010
 
227 serge 1011
           xor eax, eax
1012
           ret
378 serge 1013
.fail:
1014
           or eax, -1
1015
           ret
168 serge 1016
endp
1017
 
378 serge 1018
; parm
1019
;  eax= mix_list
1020
 
168 serge 1021
align 4
378 serge 1022
do_mix_list:
1023
 
1024
           xor edx, edx
1025
           mov esi, str.fd-FD_OFFSET
1026
           mov ebx, [esi+STREAM.str_fd]
1027
@@:
1028
           cmp ebx, esi
1029
           je .done
1030
 
1031
           cmp [ebx+STREAM.magic], 'WAVE'
1032
           jne .next
1033
 
1034
           cmp [ebx+STREAM.size], STREAM_SIZE
1035
           jne .next
1036
 
1037
           cmp [ebx+STREAM.flags], SND_PLAY;
1038
           jne .next
1039
 
1040
           mov ecx, [ebx+STREAM.out_count]
1041
           test ecx, ecx
1042
           jnz .l1
1043
 
1044
           test [ebx+STREAM.format], PCM_RING
1045
           jnz .next
1046
           mov [ebx+STREAM.flags], SND_STOP
1047
           jmp .next
1048
.l1:
1049
           cmp ecx, 512
1050
           jae .add_buff
1051
 
1052
           mov edi, [ebx+STREAM.out_rp]
1053
           add edi, ecx
1054
           sub ecx, 512
1055
           neg ecx
1056
           push eax
1057
           xor eax, eax
1058
           cld
1059
           rep stosb
1060
           pop eax
1061
 
1062
           mov [ebx+STREAM.out_count], 512
1063
 
1064
.add_buff:
1065
           mov ecx, [ebx+STREAM.out_rp]
1066
           mov [eax],ecx
1067
           mov edi, dword [ebx+STREAM.l_amp]
1068
           mov [eax+4], edi
1069
           add [ebx+STREAM.out_rp], 512
1070
           sub [ebx+STREAM.out_count], 512
1071
 
1072
           add eax, 8
1073
           inc edx
1074
.next:
1075
           mov ebx, [ebx+STREAM.str_fd]
1076
           jmp @B
1077
.done:
1078
           mov eax, edx
1079
           ret
1080
 
1081
align 4
291 serge 1082
prepare_playlist:
168 serge 1083
 
227 serge 1084
           xor edx, edx
291 serge 1085
           mov [play_count], edx
1086
           mov esi, str.fd-FD_OFFSET
1087
           mov edi, [esi+STREAM.str_fd]
1088
@@:
1089
           cmp edi, esi
1090
           je .done
168 serge 1091
 
291 serge 1092
           cmp [edi+STREAM.magic], 'WAVE'
168 serge 1093
           jne .next
1094
 
291 serge 1095
           cmp [edi+STREAM.size], STREAM_SIZE
168 serge 1096
           jne .next
1097
 
291 serge 1098
           cmp [edi+STREAM.flags], SND_PLAY;
227 serge 1099
           jne .next
168 serge 1100
 
291 serge 1101
           mov [play_list+edx], edi
227 serge 1102
           inc [play_count]
1103
           add edx, 4
168 serge 1104
.next:
291 serge 1105
           mov edi, [edi+STREAM.str_fd]
1106
           jmp @B
1107
.done:
227 serge 1108
           ret
168 serge 1109
 
1110
align 4
1111
proc set_handler stdcall, hsrv:dword, handler_proc:dword
1112
           locals
1113
             handler    dd ?
1114
             io_code    dd ?
1115
             input      dd ?
1116
             inp_size   dd ?
1117
             output     dd ?
1118
             out_size   dd ?
1119
             val        dd ?
1120
           endl
1121
 
1122
           mov eax, [hsrv]
1123
           lea ecx, [handler_proc]
1124
           xor ebx, ebx
1125
 
1126
           mov [handler], eax
1127
           mov [io_code], DEV_CALLBACK
1128
           mov [input], ecx
1129
           mov [inp_size], 4
1130
           mov [output], ebx
1131
           mov [out_size], 0
1132
 
1133
           lea eax, [handler]
188 serge 1134
           stdcall ServiceHandler, eax
168 serge 1135
           ret
1136
endp
1137
 
1138
align 4
1139
proc dev_play stdcall, hsrv:dword
1140
           locals
1141
             handle     dd ?
1142
             io_code    dd ?
1143
             input      dd ?
1144
             inp_size   dd ?
1145
             output     dd ?
1146
             out_size   dd ?
1147
             val        dd ?
1148
           endl
1149
 
1150
           mov eax, [hsrv]
1151
           xor ebx, ebx
1152
 
1153
           mov [handle], eax
1154
           mov [io_code], DEV_PLAY
1155
           mov [input], ebx
1156
           mov [inp_size], ebx
1157
           mov [output], ebx
1158
           mov [out_size], ebx
1159
 
1160
           lea eax, [handle]
188 serge 1161
           stdcall ServiceHandler, eax
168 serge 1162
           ret
1163
endp
1164
 
378 serge 1165
if 0
1166
align 4
1167
dword2str:
1168
      mov  esi, hex_buff
1169
      mov ecx, -8
1170
@@:
1171
      rol eax, 4
1172
      mov ebx, eax
1173
      and ebx, 0x0F
1174
      mov bl, [ebx+hexletters]
1175
      mov [8+esi+ecx], bl
1176
      inc ecx
1177
      jnz @B
1178
      ret
1179
 
1180
hexletters   db '0123456789ABCDEF'
1181
hex_buff     db 8 dup(0),13,10,0
1182
 
1183
end if
1184
 
168 serge 1185
include 'mixer.asm'
293 serge 1186
include 'mix_mmx.inc'
1187
include 'mix_sse2.inc'
168 serge 1188
 
291 serge 1189
;if USE_SSE
1190
; include 'mix_sse.inc'
1191
;end if
1192
 
168 serge 1193
align 16
1194
resampler_params:
378 serge 1195
     ;r_size    r_dt   resampler_func
1196
     dd 0,0,0                                  ; 0  PCM_ALL
1197
     dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
1198
     dd 16384,      0, m16_stereo     ; 2  PCM_1_16_48
168 serge 1199
 
378 serge 1200
     dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
1201
     dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
168 serge 1202
 
378 serge 1203
     dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
1204
     dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
168 serge 1205
 
378 serge 1206
     dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
1207
     dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
168 serge 1208
 
378 serge 1209
     dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
1210
     dd  4096,  15052, resample_1     ;10  PCM_1_16_22
168 serge 1211
 
378 serge 1212
     dd  8192,  10923, resample_2     ;11  PCM_2_16_16
1213
     dd  4096,  10923, resample_1     ;12  PCM_1_16_16
168 serge 1214
 
378 serge 1215
     dd  8192,   8192, resample_2     ;13  PCM_2_16_12
1216
     dd  4096,   8192, resample_1     ;14  PCM_1_16_12
168 serge 1217
 
378 serge 1218
     dd  4096,   7527, resample_2     ;15  PCM_2_16_11
1219
     dd  2048,   7527, resample_1     ;16  PCM_1_16_11
168 serge 1220
 
378 serge 1221
     dd  4096,   5462, resample_2     ;17  PCM_2_16_8
1222
     dd  2048,   5462, resample_1     ;18  PCM_1_16_8
168 serge 1223
 
378 serge 1224
     dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
1225
     dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
168 serge 1226
 
378 serge 1227
     dd  8192,  30109, resample_28    ;21  PCM_2_8_44
1228
     dd  4096,  30109, resample_18    ;22  PCM_1_8_44
168 serge 1229
 
378 serge 1230
     dd  8192,  21846, resample_28    ;23  PCM_2_8_32
1231
     dd  4096,  21846, resample_18    ;24  PCM_1_8_32
168 serge 1232
 
378 serge 1233
     dd  8192,  16384, resample_28    ;25  PCM_2_8_24
1234
     dd  4096,  16384, resample_18    ;26  PCM_1_8_24
168 serge 1235
 
378 serge 1236
     dd  4096,  15052, resample_28    ;27  PCM_2_8_22
1237
     dd  2048,  15052, resample_18    ;28  PCM_1_8_22
168 serge 1238
 
378 serge 1239
     dd  4096,  10923, resample_28    ;29  PCM_2_8_16
1240
     dd  2048,  10923, resample_18    ;30  PCM_1_8_16
168 serge 1241
 
378 serge 1242
     dd  4096,   8192, resample_28    ;31  PCM_2_8_12
1243
     dd  2048,   8192, resample_18    ;32  PCM_1_8_12
168 serge 1244
 
378 serge 1245
     dd  2048,   7527, resample_28    ;33  PCM_2_8_11
1246
     dd  1024,   7527, resample_18    ;34  PCM_1_8_11
168 serge 1247
 
378 serge 1248
     dd  2048,   5462, resample_28    ;35  PCM_2_8_8
1249
     dd  1024,   5462, resample_18    ;36  PCM_1_8_8
168 serge 1250
 
281 serge 1251
m7            dw 0x8000,0x8000,0x8000,0x8000
1252
mm80          dq 0x8080808080808080
1253
mm_mask       dq 0xFF00FF00FF00FF00
168 serge 1254
 
378 serge 1255
vol_max       dd 0x00000000,0x00000000
1256
vol_min       dd 0x0000D8F0,0x0000D8F0
1257
pan_max       dd 0x00002710,0x00002710
1258
 
291 serge 1259
;stream_map    dd 0xFFFF       ; 16
574 serge 1260
version       dd (5 shl 16) or SOUND_VERSION
168 serge 1261
 
281 serge 1262
szInfinity    db 'INFINITY',0
1263
szSound       db 'SOUND',0
168 serge 1264
 
1265
if DEBUG
281 serge 1266
msgFail       db 'Sound service not loaded',13,10,0
1267
msgPlay       db 'Play buffer',13,10,0
1268
msgStop       db 'Stop',13,10,0
1269
msgUser       db 'User callback',13,10,0
1270
msgMem        db 'Not enough memory',13,10,0
291 serge 1271
msgDestroy    db 'Destroy sound buffer', 13,10,0
378 serge 1272
msgWaveout    db 'Play waveout', 13,10,0
1273
msgSetVolume  db 'Set volume',13,10,0
168 serge 1274
end if
188 serge 1275
 
1276
section '.data' data readable writable align 16
1277
 
281 serge 1278
play_list     rd 16
1279
mix_input     rd 16
1280
play_count    rd 1
1281
hSound        rd 1
378 serge 1282
eng_state     rd 1
281 serge 1283
mix_buff      rd 1
1284
mix_buff_map  rd 1
291 serge 1285
str.fd        rd 1
1286
str.bk        rd 1
188 serge 1287
 
293 serge 1288
mix_2_core    rd 1
1289
mix_3_core    rd 1
1290
mix_4_core    rd 1
291 serge 1291