Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
454 trolly 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
 
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'
15
include 'imports.inc'
16
 
17
FORCE_MMX         equ 0  ;set to 1 to force use mmx or
18
FORCE_MMX_128     equ 0  ;integer sse2 extensions
19
                        ;and reduce driver size
20
;USE_SSE          equ 0
21
 
22
DEBUG             equ 1
23
 
24
 
25
OS_BASE           equ 0
26
new_app_base      equ 0x80000000
27
SLOT_BASE         equ OS_BASE+0x0080000
28
 
29
CAPS_SSE2         equ 26
30
PG_SW             equ 0x003
31
 
32
public START
33
public service_proc
34
public version
35
 
36
RT_INP_EMPTY      equ 0xFF000001
37
RT_OUT_EMPTY      equ 0xFF000002
38
RT_INP_FULL       equ 0xFF000003
39
RT_OUT_FULL       equ 0xFF000004
40
 
41
EVENT_WATCHED     equ 0x10000000
42
EVENT_SIGNALED    equ 0x20000000
43
MANUAL_RESET      equ 0x40000000
44
MANUAL_DESTROY    equ 0x80000000
45
 
46
DEV_PLAY          equ 1
47
DEV_STOP          equ 2
48
DEV_CALLBACK      equ 3
49
 
50
struc IOCTL
51
{  .handle        dd ?
52
   .io_code       dd ?
53
   .input         dd ?
54
   .inp_size      dd ?
55
   .output        dd ?
56
   .out_size      dd ?
57
}
58
 
59
virtual at 0
60
  IOCTL IOCTL
61
end virtual
62
 
63
section '.flat' code readable align 16
64
 
65
proc START stdcall, state:dword
66
 
67
           cmp [state], 1
68
           jne .exit
69
 
70
           stdcall GetService, szSound
71
           test eax, eax
72
           jz .fail
73
           mov [hSound], eax
74
 
75
           stdcall KernelAlloc, 16*512
76
           test eax, eax
77
           jz .out_of_mem
78
           mov [mix_buff], eax
79
 
80
           mov eax, str.fd-FD_OFFSET
81
           mov [str.fd], eax
82
           mov [str.bk], eax
83
 
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
 
104
if 0
105
 
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
116
.mmx128:                                   ;128-bit integer sse2 extensions
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
122
 
123
end if
124
           stdcall set_handler, [hSound], new_mix
125
           mov [eng_state], SND_STOP
126
           stdcall RegService, szInfinity, service_proc
127
           ret
128
.fail:
129
     if DEBUG
130
           mov esi, msgFail
131
           call SysMsgBoardStr
132
     end if
133
.exit:
134
           xor eax, eax
135
           ret
136
 
137
.out_of_mem:
138
     if DEBUG
139
           mov esi, msgMem
140
           call SysMsgBoardStr
141
     end if
142
           xor eax, eax
143
           ret
144
endp
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
 
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
@@:
167
           cmp eax, SND_CREATE_BUFF
168
           jne @F
169
           mov ebx, [edi+input]
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
176
           ret
177
@@:
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
188
           jne @F
189
           mov eax, edx
190
           call DestroyBuffer    ;edx= stream
191
           ret
192
@@:
193
           cmp eax, SND_SETFORMAT
194
           jne @F
195
           stdcall SetFormat,[ebx],[ebx+4]
196
           ret
197
@@:
198
           cmp eax, SND_GETFORMAT
199
           jne @F
200
 
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
206
           ret
207
@@:
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
@@:
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
234
@@:
235
           cmp eax, SND_SETVOLUME
236
           jne @F
237
           stdcall SetBufferVol,[ebx],[ebx+4],[ebx+8]
238
           ret
239
@@:
240
           cmp eax, SND_GETVOLUME
241
           jne @F
242
 
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
249
           ret
250
@@:
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
262
           xor eax, eax
263
           ret
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
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
 
309
 
310
align 4
311
proc CreateBuffer stdcall, format:dword, size:dword
312
           locals
313
             str         dd ?
314
             ring_size   dd ?
315
             ring_pages  dd ?
316
           endl
317
 
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:
338
           mov ebx, [CURRENT_TASK]      ;hack: direct accsess
339
           shl ebx, 5                   ;to kernel data
340
           mov ebx, [CURRENT_TASK+ebx+4]
341
           mov eax, STREAM_SIZE
342
 
343
           call CreateObject
344
           test eax, eax
345
           jz .fail
346
           mov [str], eax
347
 
348
           mov ebx, [format]
349
           mov [eax+STREAM.format], ebx
350
 
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
358
 
359
           shl ebx, 2
360
           lea ebx, [ebx+ebx*2]     ;ebx*=12
361
 
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
 
397
           mov edi, [str]
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
406
 
407
           mov [edi+STREAM.in_free], ecx
408
           add eax, ecx
409
           mov [edi+STREAM.in_top], eax
410
 
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:
445
           stdcall AllocKernelSpace, dword 128*1024
446
 
447
           mov edi, [str]
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
452
           add eax, 64*1024
453
           mov [edi+STREAM.out_top], eax
454
 
455
           stdcall AllocPages, dword 64/4
456
           mov edi, [str]
457
           mov ebx, [edi+STREAM.out_base]
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]
470
           mov ecx, [edi+STREAM.in_top]
471
           mov edi, [edi+STREAM.in_base]
472
           sub ecx, edi
473
           xor eax, eax
474
           shr ecx, 2
475
           cld
476
           rep stosd
477
 
478
           mov edi, [str]
479
           mov edi, [edi+STREAM.out_base]
480
           mov ecx, (64*1024)/4
481
           rep stosd
482
 
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
507
           ret
508
.fail:
509
           xor ebx, ebx
510
           or eax, -1
511
           ret
512
endp
513
 
514
;param
515
; eax= buffer handle
516
 
517
align 4
518
DestroyBuffer:
519
           .handle  equ esp       ;local
520
 
521
           mov [eax+STREAM.flags], SND_STOP
522
.destroy:
523
           push eax
524
 
525
           pushfd
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
532
 
533
           stdcall KernelFree, [eax+STREAM.in_base]
534
           mov eax, [.handle]
535
           stdcall KernelFree, [eax+STREAM.out_base]
536
 
537
           pop eax               ;restore stack
538
           call DestroyObject    ;eax= stream
539
           xor eax, eax
540
           ret
541
.fail:
542
           or eax, -1
543
           ret
544
restore .handle
545
 
546
align 4
547
proc SetFormat stdcall, str:dword, format:dword
548
 
549
           cmp word [format], PCM_1_8_8
550
           ja .fail
551
 
552
           mov edx, [str]
553
           mov [edx+STREAM.flags], SND_STOP
554
 
555
           test [edx+STREAM.format], PCM_RING
556
           jnz .fail
557
 
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
562
 
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
570
@@:
571
           mov [edx+STREAM.r_silence], ebx
572
 
573
           shl eax, 2
574
           lea eax, [eax+eax*2]     ;eax*=12
575
 
576
           mov edi, [resampler_params+eax]
577
           mov ecx, [resampler_params+eax+4]
578
           mov ebx, [resampler_params+eax+8]
579
 
580
           mov [edx+STREAM.r_size],edi
581
           mov [edx+STREAM.r_dt],  ecx
582
           mov [edx+STREAM.resample], ebx
583
 
584
           mov edi, [edx+STREAM.in_base]
585
           mov ecx, 128/4
586
           mov eax, [edx+STREAM.r_silence]
587
           cld
588
           rep stosd
589
           xor eax, eax
590
           ret
591
.fail:
592
           or eax, -1
593
           ret
594
endp
595
 
596
; for static buffers only
597
; use waveout for streams
598
 
599
align 4
600
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
601
 
602
           mov edx, [str]
603
           test [edx+STREAM.format], PCM_OUT
604
           jnz .fail
605
 
606
           mov esi, [src]
607
           mov edi, [offs]
608
           add edi, [edx+STREAM.in_base]
609
           add edi, 128
610
 
611
           cmp edi, [edx+STREAM.in_top]
612
           jae .fail
613
 
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
624
           ret
625
.fail:
626
           or eax, -1
627
           ret
628
endp
629
 
630
; for stream buffers only
631
 
632
align 4
633
proc wave_out stdcall, str:dword,src:dword,size:dword
634
           locals
635
             state_saved  dd ?
636
             fpu_state    rb 528
637
           endl
638
 
639
           mov edx, [str]
640
           mov eax, [edx+STREAM.format]
641
           test eax, PCM_STATIC+PCM_RING
642
           jnz .fail
643
 
644
           cmp ax, PCM_ALL
645
           je .fail
646
 
647
           mov esi,[src]
648
           test esi, esi
649
           jz .fail
650
 
651
           cmp esi, new_app_base
652
           jb .fail
653
 
654
           mov [state_saved], 0
655
 
656
.main_loop:
657
           mov edx, [str]
658
 
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
@@:
693
           sub [size], ecx
694
           add [edx+STREAM.in_count], ecx
695
           sub [edx+STREAM.in_free], ecx
696
 
697
           shr ecx, 2
698
           mov edi, [edx+STREAM.in_wp]
699
           mov esi, [src]
700
           cld
701
           rep movsd
702
 
703
           mov [src], esi
704
           cmp edi, [edx+STREAM.in_top]
705
           jb @F
706
           sub edi, [edx+STREAM.in_size]
707
@@:
708
           mov [edx+STREAM.in_wp], edi
709
 
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
736
.done:
737
           cmp [state_saved], 1
738
           jne @F
739
 
740
           lea eax, [fpu_state+15]
741
           and eax, -16
742
           call FpuRestore
743
@@:
744
           xor eax, eax
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
906
           inc eax
907
           ret
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
984
.fail:
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
 
1006
           xor eax, eax
1007
           ret
1008
.fail:
1009
           or eax, -1
1010
           ret
1011
endp
1012
 
1013
; parm
1014
;  eax= mix_list
1015
 
1016
align 4
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
1077
prepare_playlist:
1078
 
1079
           xor edx, edx
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
1086
 
1087
           cmp [edi+STREAM.magic], 'WAVE'
1088
           jne .next
1089
 
1090
           cmp [edi+STREAM.size], STREAM_SIZE
1091
           jne .next
1092
 
1093
           cmp [edi+STREAM.flags], SND_PLAY;
1094
           jne .next
1095
 
1096
           mov [play_list+edx], edi
1097
           inc [play_count]
1098
           add edx, 4
1099
.next:
1100
           mov edi, [edi+STREAM.str_fd]
1101
           jmp @B
1102
.done:
1103
           ret
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]
1129
           stdcall ServiceHandler, eax
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]
1156
           stdcall ServiceHandler, eax
1157
           ret
1158
endp
1159
 
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
 
1180
include 'mixer.asm'
1181
include 'mix_mmx.inc'
1182
include 'mix_sse2.inc'
1183
 
1184
;if USE_SSE
1185
; include 'mix_sse.inc'
1186
;end if
1187
 
1188
align 16
1189
resampler_params:
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
1194
 
1195
     dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
1196
     dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
1197
 
1198
     dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
1199
     dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
1200
 
1201
     dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
1202
     dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
1203
 
1204
     dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
1205
     dd  4096,  15052, resample_1     ;10  PCM_1_16_22
1206
 
1207
     dd  8192,  10923, resample_2     ;11  PCM_2_16_16
1208
     dd  4096,  10923, resample_1     ;12  PCM_1_16_16
1209
 
1210
     dd  8192,   8192, resample_2     ;13  PCM_2_16_12
1211
     dd  4096,   8192, resample_1     ;14  PCM_1_16_12
1212
 
1213
     dd  4096,   7527, resample_2     ;15  PCM_2_16_11
1214
     dd  2048,   7527, resample_1     ;16  PCM_1_16_11
1215
 
1216
     dd  4096,   5462, resample_2     ;17  PCM_2_16_8
1217
     dd  2048,   5462, resample_1     ;18  PCM_1_16_8
1218
 
1219
     dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
1220
     dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
1221
 
1222
     dd  8192,  30109, resample_28    ;21  PCM_2_8_44
1223
     dd  4096,  30109, resample_18    ;22  PCM_1_8_44
1224
 
1225
     dd  8192,  21846, resample_28    ;23  PCM_2_8_32
1226
     dd  4096,  21846, resample_18    ;24  PCM_1_8_32
1227
 
1228
     dd  8192,  16384, resample_28    ;25  PCM_2_8_24
1229
     dd  4096,  16384, resample_18    ;26  PCM_1_8_24
1230
 
1231
     dd  4096,  15052, resample_28    ;27  PCM_2_8_22
1232
     dd  2048,  15052, resample_18    ;28  PCM_1_8_22
1233
 
1234
     dd  4096,  10923, resample_28    ;29  PCM_2_8_16
1235
     dd  2048,  10923, resample_18    ;30  PCM_1_8_16
1236
 
1237
     dd  4096,   8192, resample_28    ;31  PCM_2_8_12
1238
     dd  2048,   8192, resample_18    ;32  PCM_1_8_12
1239
 
1240
     dd  2048,   7527, resample_28    ;33  PCM_2_8_11
1241
     dd  1024,   7527, resample_18    ;34  PCM_1_8_11
1242
 
1243
     dd  2048,   5462, resample_28    ;35  PCM_2_8_8
1244
     dd  1024,   5462, resample_18    ;36  PCM_1_8_8
1245
 
1246
m7            dw 0x8000,0x8000,0x8000,0x8000
1247
mm80          dq 0x8080808080808080
1248
mm_mask       dq 0xFF00FF00FF00FF00
1249
 
1250
vol_max       dd 0x00000000,0x00000000
1251
vol_min       dd 0x0000D8F0,0x0000D8F0
1252
pan_max       dd 0x00002710,0x00002710
1253
 
1254
;stream_map    dd 0xFFFF       ; 16
1255
version       dd (4 shl 16) or (SOUND_VERSION and 0xFFFF)
1256
 
1257
szInfinity    db 'INFINITY',0
1258
szSound       db 'SOUND',0
1259
 
1260
if DEBUG
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
1266
msgDestroy    db 'Destroy sound buffer', 13,10,0
1267
msgWaveout    db 'Play waveout', 13,10,0
1268
msgSetVolume  db 'Set volume',13,10,0
1269
end if
1270
 
1271
section '.data' data readable writable align 16
1272
 
1273
play_list     rd 16
1274
mix_input     rd 16
1275
play_count    rd 1
1276
hSound        rd 1
1277
eng_state     rd 1
1278
mix_buff      rd 1
1279
mix_buff_map  rd 1
1280
str.fd        rd 1
1281
str.bk        rd 1
1282
 
1283
mix_2_core    rd 1
1284
mix_3_core    rd 1
1285
mix_4_core    rd 1
1286