Subversion Repositories Kolibri OS

Rev

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

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