Subversion Repositories Kolibri OS

Rev

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