Subversion Repositories Kolibri OS

Rev

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

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