Subversion Repositories Kolibri OS

Rev

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