Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2455 mario79 3
;; Copyright (C) KolibriOS team 2006-2011. All rights reserved. ;;
2288 clevermous 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
 
2694 Serge 351
        mov     eax, [ebx+4]
352
        mov     ebx, [ebx+8]
353
 
354
        pushfd
355
        cli
2288 clevermous 356
        mov     dword [edx+STREAM.time_base], eax
357
        mov     dword [edx+STREAM.time_base+4], ebx
358
        xor     eax, eax
2694 Serge 359
        mov     dword [edx+STREAM.time_stamp], eax
360
        mov     dword [edx+STREAM.time_stamp+4], eax
361
        popfd
362
 
2288 clevermous 363
        ret
364
 
2694 Serge 365
align 4
2288 clevermous 366
.snd_gettimestamp:
367
        cmp     [edi+out_size], 8
368
        jne     .fail
369
 
370
        pushfd
371
        cli
372
 
373
        xor     ebx, ebx
374
        push    48
375
        push    ebx            ; local storage
376
 
377
        cmp     [edx+STREAM.flags], SND_STOP
378
        je      @F
379
 
380
        mov     eax, esp
381
 
2694 Serge 382
        push    ebx
383
        push    ecx
2288 clevermous 384
        push    edx
2694 Serge 385
        push    esi
2288 clevermous 386
        push    edi
387
 
388
        push    4              ;.out_size
389
        push    eax            ;.output
390
        push    ebx            ;.inp_size
391
        push    ebx            ;.input
392
        push    DEV_GET_POS    ;.code
393
        push    dword [hSound] ;.handle
394
        mov     eax, esp
395
 
396
        stdcall ServiceHandler, eax
397
        add     esp, 6*4
398
 
399
        pop     edi
2694 Serge 400
        pop     esi
2288 clevermous 401
        pop     edx
2694 Serge 402
        pop     ecx
403
        pop     ebx
2288 clevermous 404
 
405
        test    eax, eax
406
        jz      @F
407
 
408
        mov     dword [esp], 0  ; clear offset
409
@@:
410
        mov     edi, [edi+output]
411
 
412
        emms
413
        fild    qword [edx+STREAM.time_stamp]
414
        fiadd   dword [esp]     ; primary buffer offset
415
        fidiv   dword [esp+4]   ; total_samples / frequency
416
        fadd    qword [edx+STREAM.time_base]
417
        fstp    qword [edi]
418
        add     esp, 8
419
 
420
        popfd
421
 
422
        xor     eax, eax
423
        ret
424
endp
425
 
426
 
427
restore   handle
428
restore   io_code
429
restore   input
430
restore   inp_size
431
restore   output
432
restore   out_size
433
 
434
align 4
435
proc CreateBuffer stdcall, format:dword, size:dword
436
           locals
437
        str     dd ?
438
             ring_size   dd ?
439
             ring_pages  dd ?
440
           endl
441
 
442
        mov     eax, [format]
443
        cmp     ax, PCM_1_8_8
444
        ja      .fail
445
 
446
        test    eax, PCM_OUT
447
        jnz     .test_out
448
        test    eax, PCM_RING
449
        jnz     .test_ring
450
;staic
451
        test    eax, PCM_STATIC
452
        jz      .test_out                 ;use PCM_OUT as default format
453
        jmp     .test_ok
454
.test_out:
455
        test    eax, PCM_RING+PCM_STATIC
456
        jnz     .fail
457
        or      [format], PCM_OUT         ;force set
458
        jmp     .test_ok
459
.test_ring:
460
        test    eax, PCM_OUT+PCM_STATIC
461
        jnz     .fail
462
.test_ok:
463
 
464
        call    GetPid
465
        mov     ebx, eax
466
        mov     eax, STREAM.sizeof
467
 
468
        call    CreateObject
469
        test    eax, eax
470
        jz      .fail
471
        mov     [str], eax
472
 
473
        mov     ebx, [format]
474
        mov     [eax+STREAM.format], ebx
475
 
476
        xor     ecx, ecx
477
        movzx   ebx, bx
478
        cmp     ebx, 19
479
        jb      @f
480
        mov     ecx, 0x80808080
481
@@:
482
        mov     [eax+STREAM.r_silence], ecx
483
 
484
        shl     ebx, 2
485
        lea     ebx, [ebx+ebx*2]    ;ebx*=12
486
 
487
        mov     ecx, [resampler_params+ebx]
488
        mov     edx, [resampler_params+ebx+4]
489
        mov     esi, [resampler_params+ebx+8]
490
 
491
        mov     [eax+STREAM.r_size], ecx
492
        mov     [eax+STREAM.r_dt], edx
493
        mov     [eax+STREAM.resample], esi
494
        xor     ecx, ecx
495
        mov     [eax+STREAM.l_vol], ecx
496
        mov     [eax+STREAM.r_vol], ecx
497
        mov     dword [eax+STREAM.l_amp], 0x7FFF7FFF
498
        mov     [eax+STREAM.pan], ecx
499
 
500
        test    [format], PCM_STATIC
501
        jnz     .static
502
 
503
; ring and waveout
504
 
505
        mov     ebx, 0x10000
506
        test    [format], PCM_RING
507
        jz      .waveout
508
 
509
        mov     ebx, [eax+STREAM.r_size]
510
        add     ebx, 4095
511
        and     ebx, -4096
512
        add     ebx, ebx
513
.waveout:
514
        mov     [ring_size], ebx
515
        mov     eax, ebx
516
        shr     ebx, 12
517
        mov     [ring_pages], ebx
518
 
519
        stdcall CreateRingBuffer, eax, PG_SW
520
 
521
        mov     edi, [str]
522
        mov     ecx, [ring_size]
523
        mov     [edi+STREAM.in_base], eax
524
        mov     [edi+STREAM.in_size], ecx
525
        add     eax, 128
526
        mov     [edi+STREAM.in_wp], eax
527
        mov     [edi+STREAM.in_rp], eax
528
        mov     [edi+STREAM.in_count], 0
529
 
530
        mov     [edi+STREAM.in_free], ecx
531
        add     eax, ecx
532
        mov     [edi+STREAM.in_top], eax
533
 
534
        jmp     .out_buff
535
.static:
536
        mov     ecx, [size]
537
        add     ecx, 128         ;resampler required
538
        mov     [eax+STREAM.in_size], ecx
539
        stdcall KernelAlloc, ecx
540
 
541
        mov     edi, [str]
542
        mov     [edi+STREAM.in_base], eax
543
        add     eax, 128
544
        mov     [edi+STREAM.in_wp], eax
545
        mov     [edi+STREAM.in_rp], eax
546
        mov     ebx, [size]
547
        mov     [edi+STREAM.in_count], ebx
548
        mov     [edi+STREAM.in_free], ebx
549
        add     eax, ebx
550
        mov     [edi+STREAM.in_top], eax
551
 
552
.out_buff:
553
        stdcall AllocKernelSpace, dword 128*1024
554
 
555
        mov     edi, [str]
556
        xor     ebx, ebx
557
 
558
        mov     [edi+STREAM.out_base], eax
559
        mov     [edi+STREAM.out_wp], eax
560
        mov     [edi+STREAM.out_rp], eax
561
        mov     [edi+STREAM.out_count], ebx
562
        add     eax, 64*1024
563
        mov     [edi+STREAM.out_top], eax
564
 
565
        mov     dword [edi+STREAM.time_base], ebx
566
        mov     dword [edi+STREAM.time_base+4], ebx
567
 
568
        mov     dword [edi+STREAM.time_stamp], ebx
569
        mov     dword [edi+STREAM.time_stamp+4], ebx
570
        mov     dword [edi+STREAM.last_ts], ebx
571
 
572
        stdcall AllocPages, dword 64/4
573
        mov     edi, [str]
574
        mov     ebx, [edi+STREAM.out_base]
575
        mov     ecx, 16
576
        or      eax, PG_SW
577
        push    eax
578
        push    ebx
579
        call    CommitPages ;eax, ebx, ecx
580
        mov     ecx, 16
581
        pop     ebx
582
        pop     eax
583
        add     ebx, 64*1024
584
        call    CommitPages    ;double mapped
585
 
586
        mov     edi, [str]
587
        mov     ecx, [edi+STREAM.in_top]
588
        mov     edi, [edi+STREAM.in_base]
589
        sub     ecx, edi
590
        xor     eax, eax
591
        shr     ecx, 2
592
        cld
593
        rep stosd
594
 
595
        mov     edi, [str]
596
        mov     edi, [edi+STREAM.out_base]
597
        mov     ecx, (64*1024)/4
598
        rep stosd
599
 
600
        xor     esi, esi
601
        mov     ecx, MANUAL_DESTROY
602
        call    CreateEvent
603
 
604
        mov     ebx, [str]
605
        mov     [ebx+STREAM.notify_event], eax
606
        mov     [ebx+STREAM.notify_id], edx
607
 
608
        mov     [ebx+STREAM.magic], 'WAVE'
609
        mov     [ebx+STREAM.destroy], DestroyBuffer.destroy
610
        mov     [ebx+STREAM.size], STREAM.sizeof
611
        mov     [ebx+STREAM.flags], SND_STOP
612
 
613
        pushf
614
        cli
615
        mov     eax, str.fd-FD_OFFSET
616
        mov     edx, [eax+STREAM.str_fd]
617
        mov     [ebx+STREAM.str_fd], edx
618
        mov     [ebx+STREAM.str_bk], eax
619
        mov     [eax+STREAM.str_fd], ebx
620
        mov     [edx+STREAM.str_bk], ebx
621
        popf
622
 
623
        xor     eax, eax
624
        ret
625
.fail:
626
        xor     ebx, ebx
627
        or      eax, -1
628
        ret
629
endp
630
 
631
;param
632
; eax= buffer handle
633
 
634
align 4
635
DestroyBuffer:
636
           .handle  equ esp       ;local
637
 
638
        mov     [eax+STREAM.flags], SND_STOP
639
.destroy:
640
        push    eax
641
 
642
        pushfd
643
        cli
644
        mov     ebx, [eax+STREAM.str_fd]
645
        mov     ecx, [eax+STREAM.str_bk]
646
        mov     [ebx+STREAM.str_bk], ecx
647
        mov     [ecx+STREAM.str_fd], ebx
648
        popf
649
 
650
        stdcall KernelFree, [eax+STREAM.in_base]
651
        mov     eax, [.handle]
652
        stdcall KernelFree, [eax+STREAM.out_base]
653
 
654
        pop     eax              ;restore stack
655
        call    DestroyObject    ;eax= stream
656
        xor     eax, eax
657
        ret
658
.fail:
659
        or      eax, -1
660
        ret
661
restore .handle
662
 
663
align 4
664
proc SetFormat stdcall, str:dword, format:dword
665
 
666
        cmp     word [format], PCM_1_8_8
667
        ja      .fail
668
 
669
        mov     edx, [str]
670
        mov     [edx+STREAM.flags], SND_STOP
671
 
672
        test    [edx+STREAM.format], PCM_RING
673
        jnz     .fail
674
 
675
;           mov eax,[edx+STREAM.out_base]
676
;           mov [edx+STREAM.out_wp], eax
677
;           mov [edx+STREAM.out_rp], eax
678
;           mov [edx+STREAM.out_count], 0
679
 
680
        movzx   eax, word [format]
681
        mov     word [edx+STREAM.format], ax
682
 
683
        xor     ebx, ebx
684
        cmp     eax, 19
685
        jb      @f
686
        mov     ebx, 0x80808080
687
@@:
688
        mov     [edx+STREAM.r_silence], ebx
689
 
690
        shl     eax, 2
691
        lea     eax, [eax+eax*2]    ;eax*=12
692
 
693
        mov     edi, [resampler_params+eax]
694
        mov     ecx, [resampler_params+eax+4]
695
        mov     ebx, [resampler_params+eax+8]
696
 
697
        mov     [edx+STREAM.r_size], edi
698
        mov     [edx+STREAM.r_dt], ecx
699
        mov     [edx+STREAM.resample], ebx
700
 
701
        mov     edi, [edx+STREAM.in_base]
702
        mov     ecx, 128/4
703
        mov     eax, [edx+STREAM.r_silence]
704
        cld
705
        rep stosd
706
        xor     eax, eax
707
        ret
708
.fail:
709
        or      eax, -1
710
        ret
711
endp
712
 
713
; for static buffers only
714
; use waveout for streams
715
 
716
align 4
717
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
718
 
719
        mov     edx, [str]
720
        test    [edx+STREAM.format], PCM_OUT
721
        jnz     .fail
722
 
723
        mov     esi, [src]
724
        mov     edi, [offs]
725
        add     edi, [edx+STREAM.in_base]
726
        add     edi, 128
727
 
728
        cmp     edi, [edx+STREAM.in_top]
729
        jae     .fail
730
 
731
        mov     ecx, [size]
732
        lea     ebx, [ecx+edi]
733
        sub     ebx, [edx+STREAM.in_top]
734
        jb      @F
735
        sub     ecx, ebx
736
@@:
737
        shr     ecx, 2
738
        cld
739
        rep movsd
740
        xor     eax, eax
741
        ret
742
.fail:
743
        or      eax, -1
744
        ret
745
endp
746
 
747
; for stream buffers only
748
 
749
align 4
750
proc wave_out stdcall, str:dword,src:dword,size:dword
751
           locals
752
             state_saved  dd ?
753
             fpu_state    rb 528
754
           endl
755
 
756
        mov     edx, [str]
757
        mov     eax, [edx+STREAM.format]
758
        test    eax, PCM_OUT
759
        jz      .fail
760
 
761
        cmp     ax, PCM_ALL
762
        je      .fail
763
 
764
        mov     esi, [src]
765
        test    esi, esi
766
        jz      .fail
767
 
768
        cmp     esi, OS_BASE
769
        jae     .fail
770
 
771
        mov     [state_saved], 0
772
 
773
.main_loop:
774
        mov     edx, [str]
775
 
776
        mov     ebx, [size]
777
        test    ebx, ebx
778
        jz      .done
779
 
780
        cmp     [edx+STREAM.flags], SND_STOP
781
        jne     .fill
782
 
783
        mov     edi, [edx+STREAM.in_base]
784
        mov     ecx, 128/4
785
        mov     eax, [edx+STREAM.r_silence]
786
        cld
787
        rep stosd
788
 
789
        mov     ecx, [edx+STREAM.in_size]
790
        sub     ecx, 128
791
        mov     [edx+STREAM.in_wp], edi
792
        mov     [edx+STREAM.in_rp], edi
793
        mov     [edx+STREAM.in_count], 0
794
        mov     [edx+STREAM.in_free], ecx
795
 
796
        mov     eax, [edx+STREAM.out_base]
797
        mov     [edx+STREAM.out_wp], eax
798
        mov     [edx+STREAM.out_rp], eax
799
        mov     [edx+STREAM.out_count], 0
800
.fill:
801
        cli
802
 
803
        mov     ecx, [edx+STREAM.in_free]
804
        test    ecx, ecx
805
        jz      .wait
806
 
807
        cmp     ecx, ebx
808
        jbe     @F
809
 
810
        mov     ecx, ebx
811
@@:
812
        sub     [size], ecx
813
        add     [edx+STREAM.in_count], ecx
814
        sub     [edx+STREAM.in_free], ecx
815
 
816
        shr     ecx, 2
817
        mov     edi, [edx+STREAM.in_wp]
818
        mov     esi, [src]
819
        cld
820
        rep movsd
821
 
822
        mov     [src], esi
823
        cmp     edi, [edx+STREAM.in_top]
824
        jb      @F
825
        sub     edi, [edx+STREAM.in_size]
826
@@:
827
        mov     [edx+STREAM.in_wp], edi
828
 
829
        cmp     [edx+STREAM.out_count], 32768
830
        jae     .skip
831
 
832
        cmp     [state_saved], 0
833
        jne     @F
834
        lea     eax, [fpu_state+15]
835
        and     eax, -16
836
        call    FpuSave
837
        mov     [state_saved], 1
838
@@:
839
        stdcall refill, edx
840
 
841
.skip:
842
        sti
843
        mov     edx, [str]
844
        mov     [edx+STREAM.flags], SND_PLAY
845
        cmp     [eng_state], SND_PLAY
846
        je      .main_loop
847
 
848
        stdcall dev_play, [hSound]
849
        mov     [eng_state], SND_PLAY
850
        jmp     .main_loop
851
.wait:
852
        sti
853
        mov     edx, [str]
854
        mov     eax, [edx+STREAM.notify_event]
855
        mov     ebx, [edx+STREAM.notify_id]
856
        call    WaitEvent   ;eax ebx
857
        jmp     .main_loop
858
.done:
859
        cmp     [state_saved], 1
860
        jne     @F
861
 
862
        lea     eax, [fpu_state+15]
863
        and     eax, -16
864
        call    FpuRestore
865
@@:
866
        xor     eax, eax
867
        ret
868
.fail:
869
        or      eax, -1
870
        ret
871
endp
872
 
873
; both static and stream
874
; reset all but not clear buffers
875
 
876
 
877
; flags reserved
878
;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
879
;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
880
;  RESET_ALL    equ 3
881
 
882
 
883
align 4
884
proc ResetBuffer stdcall, str:dword, flags:dword
885
 
886
        mov     edx, [str]
887
        mov     [edx+STREAM.flags], SND_STOP
888
 
889
        mov     edi, [edx+STREAM.in_base]
890
        mov     ecx, 128/4
891
        mov     eax, [edx+STREAM.r_silence]
892
        cld
893
        rep stosd
894
 
895
        mov     [edx+STREAM.in_wp], edi
896
        mov     [edx+STREAM.in_rp], edi
897
 
898
        test    [edx+STREAM.flags], PCM_STATIC
899
        jnz     .static
900
        mov     [edx+STREAM.in_count], 0
901
        jmp     @F
902
.static:
903
        mov     eax, [edx+STREAM.in_size]
904
        mov     [edx+STREAM.in_count], eax
905
@@:
906
 
907
        mov     eax, [edx+STREAM.in_size]
908
        sub     eax, 128
909
        mov     [edx+STREAM.in_free], eax
910
 
911
        xor     eax, eax
912
        mov     ebx, [edx+STREAM.out_base]
913
        mov     [edx+STREAM.out_wp], ebx
914
        mov     [edx+STREAM.out_rp], ebx
915
        mov     [edx+STREAM.out_count], eax
916
        ret
917
.fail:
918
        or      eax, -1
919
        ret
920
endp
921
 
922
; for static buffers only
923
 
924
align 4
925
proc SetBufferPos stdcall, str:dword, pos:dword
926
 
927
        mov     edx, [str]
928
        test    [edx+STREAM.format], PCM_STATIC
929
        jz      .fail
930
 
931
        mov     [edx+STREAM.flags], SND_STOP
932
 
933
        mov     eax, [pos]
934
        add     eax, [edx+STREAM.in_base]
935
        mov     ebx, [edx+STREAM.in_top]
936
        add     eax, 128
937
 
938
        cmp     eax, ebx
939
        jae     .fail
940
 
941
        mov     [edx+STREAM.in_rp], eax
942
        sub     ebx, eax
943
        mov     [edx+STREAM.in_count], ebx
944
        xor     eax, eax
945
        ret
946
.fail:
947
        or      eax, -1
948
        ret
949
endp
950
 
951
align 4
952
proc GetBufferPos stdcall, str:dword
953
 
954
        mov     edx, [str]
955
        test    [edx+STREAM.format], PCM_STATIC
956
        jz      .fail
957
 
958
        mov     ebx, [edx+STREAM.in_rp]
959
        sub     ebx, [edx+STREAM.in_base]
960
        sub     ebx, 128
961
        xor     eax, eax
962
        ret
963
.fail:
964
        xor     ebx, ebx
965
        or      eax, -1
966
        ret
967
endp
968
 
969
; both
970
 
971
align 4
972
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
973
 
974
        mov     edx, [str]
975
        stdcall set_vol_param, [l_vol], [r_vol], [edx+STREAM.pan]
976
        ret
977
endp
978
 
979
 
980
proc minw stdcall, arg1:dword, arg2:dword
981
        mov     ax, word [arg1]
982
        cmp     ax, word [arg2]
983
        jle     @f
984
        mov     eax, [arg2]
985
@@:
986
        ret
987
endp
988
 
989
proc maxw stdcall, arg1:dword, arg2:dword
990
        mov     ax, word [arg1]
991
        cmp     ax, word [arg2]
992
        jge     @f
993
        mov     eax, [arg2]
994
@@:
995
        ret
996
endp
997
 
998
 
999
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
1000
           locals
1001
             _600    dd ?
1002
             _32767  dd ?
1003
             state   rb 108
1004
           endl
1005
 
1006
        mov     [_600], 0x44160000  ;600.0
1007
        mov     [_32767], 32767
1008
 
1009
        lea     ebx, [state]
1010
        fnsave  [ebx]
1011
 
1012
        stdcall minw, [l_vol], [vol_max]
1013
        stdcall maxw, eax, [vol_min]
1014
        mov     [l_vol], eax
1015
        mov     [edx+STREAM.l_vol], eax
1016
        stdcall minw, [r_vol], [vol_max+4]
1017
        stdcall maxw, eax, [vol_min+4]
1018
        mov     [r_vol], eax
1019
        mov     [edx+STREAM.r_vol], eax
1020
 
1021
        stdcall minw, [pan], [pan_max]
1022
        stdcall maxw, eax, [vol_min]
1023
        mov     [edx+STREAM.pan], eax
1024
 
1025
        cmp     word [edx+STREAM.pan], 0
1026
        jl      @f
1027
 
1028
        mov     ebx, [l_vol]
1029
        sub     ebx, eax
1030
        stdcall minw, ebx, [vol_max]
1031
        stdcall maxw, eax, [vol_min]
1032
        mov     [l_vol], eax
1033
        jmp     .calc_amp
1034
@@:
1035
        mov     ebx, [r_vol]
1036
        add     ebx, [pan]
1037
        stdcall minw, ebx, [vol_max+4]
1038
        stdcall maxw, eax, [vol_min+4]
1039
        mov     [r_vol], eax
1040
.calc_amp:
1041
        emms
1042
        fild    word [l_vol]
1043
 
1044
        call    .calc
1045
 
1046
        fistp   word [edx+STREAM.l_amp]
1047
        fstp    dword [edx+STREAM.l_amp_f]
1048
        fstp    st0
1049
 
1050
        fild    word [r_vol]
1051
 
1052
        call    .calc
1053
 
1054
        fistp   word [edx+STREAM.r_amp]
1055
        fstp    dword [edx+STREAM.r_amp_f]
1056
        fstp    st0
1057
 
1058
        fnclex
1059
        lea     ebx, [state]
1060
        frstor  [ebx]
1061
 
1062
        xor     eax, eax
1063
        inc     eax
1064
        ret
1065
.calc:
1066
        fdiv    dword [_600]
1067
        fld     st0
1068
        frndint
1069
        fxch    st1
1070
        fsub    st, st1
1071
        f2xm1
1072
        fld1
1073
        faddp   st1, st0
1074
        fscale
1075
        fld     st0
1076
        fimul   dword [_32767]
1077
        ret     0
1078
endp
1079
 
1080
 
1081
align 4
1082
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
1083
 
1084
        mov     edx, [str]
1085
        mov     eax, [p_lvol]
1086
        movsx   ecx, word [edx+STREAM.l_vol]
1087
        mov     [eax], ecx
1088
 
1089
        mov     eax, [p_rvol]
1090
        movsx   ecx, word [edx+STREAM.r_vol]
1091
        mov     [eax], ecx
1092
        xor     eax, eax
1093
        ret
1094
endp
1095
 
1096
align 4
1097
proc SetBufferPan stdcall, str:dword,pan:dword
1098
 
1099
        mov     edx, [str]
1100
        stdcall set_vol_param, [edx+STREAM.l_vol], \
1101
                [edx+STREAM.r_vol],[pan]
1102
        ret
1103
endp
1104
 
1105
; for static and ring buffers only
1106
 
1107
align 4
1108
proc play_buffer stdcall, str:dword, flags:dword
1109
 
1110
        mov     ebx, [str]
1111
        mov     eax, [ebx+STREAM.format]
1112
        test    eax, PCM_OUT
1113
        jnz     .fail
1114
 
1115
        cmp     ax, PCM_ALL
1116
        je      .fail
1117
 
1118
        mov     [ebx+STREAM.flags], SND_PLAY
1119
        cmp     [eng_state], SND_PLAY
1120
        je      .done
1121
 
1122
        stdcall dev_play, [hSound]
1123
        mov     [eng_state], SND_PLAY
1124
.done:
1125
        test    [flags], PLAY_SYNC
1126
        jz      @F
1127
 
1128
        mov     edx, [str]
1129
.wait:
1130
        mov     eax, [edx+STREAM.notify_event]
1131
        mov     ebx, [edx+STREAM.notify_id]
1132
        call    WaitEvent   ;eax ebx
1133
 
1134
        mov     edx, [str]
1135
        cmp     [edx+STREAM.flags], SND_STOP
1136
        jne     .wait
1137
@@:
1138
        xor     eax, eax
1139
        ret
1140
.fail:
1141
        or      eax, -1
1142
        ret
1143
endp
1144
 
1145
; for static and ring buffers only
1146
 
1147
align 4
1148
proc stop_buffer stdcall, str:dword
1149
 
1150
        mov     edx, [str]
1151
        test    [edx+STREAM.format], PCM_STATIC+PCM_RING
1152
        jz      .fail
1153
 
1154
        mov     [edx+STREAM.flags], SND_STOP
1155
 
1156
;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
1157
 
1158
        mov     eax, [edx+STREAM.notify_event]
1159
        mov     ebx, [edx+STREAM.notify_id]
1160
        call    ClearEvent   ;eax ebx
1161
 
1162
        xor     eax, eax
1163
        ret
1164
.fail:
1165
        or      eax, -1
1166
        ret
1167
endp
1168
 
1169
; param
1170
;  eax= mix_list
1171
 
1172
align 4
1173
do_mix_list:
1174
 
1175
        xor     edx, edx
1176
        mov     esi, str.fd-FD_OFFSET
1177
        mov     ebx, [esi+STREAM.str_fd]
1178
@@:
1179
        cmp     ebx, esi
1180
        je      .done
1181
 
1182
        cmp     [ebx+STREAM.magic], 'WAVE'
1183
        jne     .next
1184
 
1185
        cmp     [ebx+STREAM.size], STREAM.sizeof
1186
        jne     .next
1187
 
1188
        cmp     [ebx+STREAM.flags], SND_PLAY;
1189
        jne     .next
1190
 
1191
        mov     ecx, [ebx+STREAM.out_count]
1192
        test    ecx, ecx
1193
        jnz     .l1
1194
 
1195
        test    [ebx+STREAM.format], PCM_RING
1196
        jnz     .next
1197
        mov     [ebx+STREAM.flags], SND_STOP
1198
        jmp     .next
1199
.l1:
1200
        cmp     ecx, 512
1201
        jae     .add_buff
1202
 
1203
        mov     edi, [ebx+STREAM.out_rp]
1204
        add     edi, ecx
1205
        sub     ecx, 512
1206
        neg     ecx
1207
        push    eax
1208
        xor     eax, eax
1209
        cld
1210
        rep stosb
1211
        pop     eax
1212
 
1213
        mov     [ebx+STREAM.out_count], 512
1214
 
1215
.add_buff:
1216
        mov     ecx, [ebx+STREAM.out_rp]
1217
        mov     [eax], ecx
1218
 
1219
if USE_SSE2_MIXER
1220
        mov     edi, dword [ebx+STREAM.l_amp_f]
1221
        mov     [eax+4], edi
1222
        mov     edi, dword [ebx+STREAM.r_amp_f]
1223
        mov     [eax+8], edi
1224
else
1225
        mov     edi, dword [ebx+STREAM.l_amp]
1226
        mov     [eax+4], edi
1227
end if
1228
        add     [ebx+STREAM.out_rp], 512
1229
        sub     [ebx+STREAM.out_count], 512
1230
 
1231
        add     eax, 12
1232
        inc     edx
1233
.next:
1234
        mov     ebx, [ebx+STREAM.str_fd]
1235
        jmp     @B
1236
.done:
1237
        mov     eax, edx
1238
        ret
1239
 
1240
align 4
1241
prepare_playlist:
1242
 
1243
        xor     edx, edx
1244
        mov     [play_count], edx
1245
        mov     esi, str.fd-FD_OFFSET
1246
        mov     edi, [esi+STREAM.str_fd]
1247
@@:
1248
        cmp     edi, esi
1249
        je      .done
1250
 
1251
        cmp     [edi+STREAM.magic], 'WAVE'
1252
        jne     .next
1253
 
1254
        cmp     [edi+STREAM.size], STREAM.sizeof
1255
        jne     .next
1256
 
1257
        cmp     [edi+STREAM.flags], SND_PLAY;
1258
        jne     .next
1259
 
1260
        mov     [play_list+edx], edi
1261
        inc     [play_count]
1262
        add     edx, 4
1263
.next:
1264
        mov     edi, [edi+STREAM.str_fd]
1265
        jmp     @B
1266
.done:
1267
        ret
1268
 
1269
align 4
1270
proc set_handler stdcall, hsrv:dword, handler_proc:dword
1271
           locals
1272
             handler    dd ?
1273
             io_code    dd ?
1274
             input      dd ?
1275
             inp_size   dd ?
1276
             output     dd ?
1277
             out_size   dd ?
1278
             val        dd ?
1279
           endl
1280
 
1281
        mov     eax, [hsrv]
1282
        lea     ecx, [handler_proc]
1283
        xor     ebx, ebx
1284
 
1285
        mov     [handler], eax
1286
        mov     [io_code], DEV_CALLBACK
1287
        mov     [input], ecx
1288
        mov     [inp_size], 4
1289
        mov     [output], ebx
1290
        mov     [out_size], 0
1291
 
1292
        lea     eax, [handler]
1293
        stdcall ServiceHandler, eax
1294
        ret
1295
endp
1296
 
1297
align 4
1298
proc dev_play stdcall, hsrv:dword
1299
           locals
1300
             handle     dd ?
1301
             io_code    dd ?
1302
             input      dd ?
1303
             inp_size   dd ?
1304
             output     dd ?
1305
             out_size   dd ?
1306
             val        dd ?
1307
           endl
1308
 
1309
        mov     eax, [hsrv]
1310
        xor     ebx, ebx
1311
 
1312
        mov     [handle], eax
1313
        mov     [io_code], DEV_PLAY
1314
        mov     [input], ebx
1315
        mov     [inp_size], ebx
1316
        mov     [output], ebx
1317
        mov     [out_size], ebx
1318
 
1319
        lea     eax, [handle]
1320
        stdcall ServiceHandler, eax
1321
        ret
1322
endp
1323
 
1324
if 0
1325
align 4
1326
dword2str:
1327
        mov     esi, hex_buff
1328
        mov     ecx, -8
1329
@@:
1330
        rol     eax, 4
1331
        mov     ebx, eax
1332
        and     ebx, 0x0F
1333
        mov     bl, [ebx+hexletters]
1334
        mov     [8+esi+ecx], bl
1335
        inc     ecx
1336
        jnz     @B
1337
        ret
1338
 
1339
hexletters   db '0123456789ABCDEF'
1340
hex_buff     db 8 dup(0),13,10,0
1341
 
1342
end if
1343
 
1344
include 'mixer.asm'
1345
include 'mix_mmx.inc'
1346
include 'mix_sse2.inc'
1347
 
1348
;if USE_SSE
1349
; include 'mix_sse.inc'
1350
;end if
1351
 
1352
align 16
1353
resampler_params:
1354
     ;r_size    r_dt   resampler_func
1355
     dd 0,0,0                                  ; 0  PCM_ALL
1356
     dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
1357
     dd  8192,      0, m16_stereo     ; 2  PCM_1_16_48
1358
 
1359
     dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
1360
     dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
1361
 
1362
     dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
1363
     dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
1364
 
1365
     dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
1366
     dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
1367
 
1368
     dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
1369
     dd  4096,  15052, resample_1     ;10  PCM_1_16_22
1370
 
1371
     dd  8192,  10923, resample_2     ;11  PCM_2_16_16
1372
     dd  4096,  10923, resample_1     ;12  PCM_1_16_16
1373
 
1374
     dd  8192,   8192, resample_2     ;13  PCM_2_16_12
1375
     dd  4096,   8192, resample_1     ;14  PCM_1_16_12
1376
 
1377
     dd  4096,   7527, resample_2     ;15  PCM_2_16_11
1378
     dd  2048,   7527, resample_1     ;16  PCM_1_16_11
1379
 
1380
     dd  4096,   5462, resample_2     ;17  PCM_2_16_8
1381
     dd  2048,   5462, resample_1     ;18  PCM_1_16_8
1382
 
1383
     dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
1384
     dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
1385
 
1386
     dd  8192,  30109, resample_28    ;21  PCM_2_8_44
1387
     dd  4096,  30109, resample_18    ;22  PCM_1_8_44
1388
 
1389
     dd  8192,  21846, resample_28    ;23  PCM_2_8_32
1390
     dd  4096,  21846, resample_18    ;24  PCM_1_8_32
1391
 
1392
     dd  8192,  16384, resample_28    ;25  PCM_2_8_24
1393
     dd  4096,  16384, resample_18    ;26  PCM_1_8_24
1394
 
1395
     dd  4096,  15052, resample_28    ;27  PCM_2_8_22
1396
     dd  2048,  15052, resample_18    ;28  PCM_1_8_22
1397
 
1398
     dd  4096,  10923, resample_28    ;29  PCM_2_8_16
1399
     dd  2048,  10923, resample_18    ;30  PCM_1_8_16
1400
 
1401
     dd  4096,   8192, resample_28    ;31  PCM_2_8_12
1402
     dd  2048,   8192, resample_18    ;32  PCM_1_8_12
1403
 
1404
     dd  2048,   7527, resample_28    ;33  PCM_2_8_11
1405
     dd  1024,   7527, resample_18    ;34  PCM_1_8_11
1406
 
1407
     dd  2048,   5462, resample_28    ;35  PCM_2_8_8
1408
     dd  1024,   5462, resample_18    ;36  PCM_1_8_8
1409
 
1410
m7            dw 0x8000,0x8000,0x8000,0x8000
1411
mm80          dq 0x8080808080808080
1412
mm_mask       dq 0xFF00FF00FF00FF00
1413
 
1414
vol_max       dd 0x00000000,0x00000000
1415
vol_min       dd 0x0000D8F0,0x0000D8F0
1416
pan_max       dd 0x00002710,0x00002710
1417
 
1418
;stream_map    dd 0xFFFF       ; 16
1419
version       dd (5 shl 16) or SOUND_VERSION
1420
 
1421
szInfinity    db 'INFINITY',0
1422
szSound       db 'SOUND',0
1423
 
1424
if DEBUG
1425
msgFail       db 'Sound service not loaded',13,10,0
1426
msgPlay       db 'Play buffer',13,10,0
1427
msgStop       db 'Stop',13,10,0
1428
msgUser       db 'User callback',13,10,0
1429
msgMem        db 'Not enough memory',13,10,0
1430
msgDestroy    db 'Destroy sound buffer', 13,10,0
1431
msgWaveout    db 'Play waveout', 13,10,0
1432
msgSetVolume  db 'Set volume',13,10,0
1433
end if
1434
 
1435
section '.data' data readable writable align 16
1436
 
1437
play_list     rd 16
1438
mix_input     rd 16
1439
play_count    rd 1
1440
hSound        rd 1
1441
eng_state     rd 1
1442
mix_buff      rd 1
1443
mix_buff_map  rd 1
1444
str.fd        rd 1
1445
str.bk        rd 1
1446
 
1447
mix_2_core    rd 1
1448
mix_3_core    rd 1
1449
mix_4_core    rd 1