Subversion Repositories Kolibri OS

Rev

Rev 2694 | 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
2991 Serge 878
;  RESET_INPUT  equ 1   ;reset and clear input buffer
879
;  RESET_OUTPUT equ 2   ;reset and clear output buffer
2288 clevermous 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
2991 Serge 916
 
917
        mov     dword [edx+STREAM.time_base], eax
918
        mov     dword [edx+STREAM.time_base+4], eax
919
 
920
        mov     dword [edx+STREAM.time_stamp], eax
921
        mov     dword [edx+STREAM.time_stamp+4], eax
922
        mov     dword [edx+STREAM.last_ts], eax
923
 
924
 
925
        mov     eax, [edx+STREAM.r_silence]
926
        test    [flags], 1
927
        jz      @F
928
 
929
        mov     ecx, [edx+STREAM.in_top]
930
        mov     edi, [edx+STREAM.in_base]
931
        sub     ecx, edi
932
        shr     ecx, 2
933
        cld
934
        rep stosd
935
@@:
936
        test    [flags], 2
937
        jz      @F
938
 
939
        mov     edi, [edx+STREAM.out_base]
940
        mov     ecx, (64*1024)/4
941
        rep stosd
942
@@:
2288 clevermous 943
        ret
944
.fail:
945
        or      eax, -1
946
        ret
947
endp
948
 
949
; for static buffers only
950
 
951
align 4
952
proc SetBufferPos stdcall, str:dword, pos:dword
953
 
954
        mov     edx, [str]
955
        test    [edx+STREAM.format], PCM_STATIC
956
        jz      .fail
957
 
958
        mov     [edx+STREAM.flags], SND_STOP
959
 
960
        mov     eax, [pos]
961
        add     eax, [edx+STREAM.in_base]
962
        mov     ebx, [edx+STREAM.in_top]
963
        add     eax, 128
964
 
965
        cmp     eax, ebx
966
        jae     .fail
967
 
968
        mov     [edx+STREAM.in_rp], eax
969
        sub     ebx, eax
970
        mov     [edx+STREAM.in_count], ebx
971
        xor     eax, eax
972
        ret
973
.fail:
974
        or      eax, -1
975
        ret
976
endp
977
 
978
align 4
979
proc GetBufferPos stdcall, str:dword
980
 
981
        mov     edx, [str]
982
        test    [edx+STREAM.format], PCM_STATIC
983
        jz      .fail
984
 
985
        mov     ebx, [edx+STREAM.in_rp]
986
        sub     ebx, [edx+STREAM.in_base]
987
        sub     ebx, 128
988
        xor     eax, eax
989
        ret
990
.fail:
991
        xor     ebx, ebx
992
        or      eax, -1
993
        ret
994
endp
995
 
996
; both
997
 
998
align 4
999
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
1000
 
1001
        mov     edx, [str]
1002
        stdcall set_vol_param, [l_vol], [r_vol], [edx+STREAM.pan]
1003
        ret
1004
endp
1005
 
1006
 
1007
proc minw stdcall, arg1:dword, arg2:dword
1008
        mov     ax, word [arg1]
1009
        cmp     ax, word [arg2]
1010
        jle     @f
1011
        mov     eax, [arg2]
1012
@@:
1013
        ret
1014
endp
1015
 
1016
proc maxw stdcall, arg1:dword, arg2:dword
1017
        mov     ax, word [arg1]
1018
        cmp     ax, word [arg2]
1019
        jge     @f
1020
        mov     eax, [arg2]
1021
@@:
1022
        ret
1023
endp
1024
 
1025
 
1026
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
1027
           locals
1028
             _600    dd ?
1029
             _32767  dd ?
1030
             state   rb 108
1031
           endl
1032
 
1033
        mov     [_600], 0x44160000  ;600.0
1034
        mov     [_32767], 32767
1035
 
1036
        lea     ebx, [state]
1037
        fnsave  [ebx]
1038
 
1039
        stdcall minw, [l_vol], [vol_max]
1040
        stdcall maxw, eax, [vol_min]
1041
        mov     [l_vol], eax
1042
        mov     [edx+STREAM.l_vol], eax
1043
        stdcall minw, [r_vol], [vol_max+4]
1044
        stdcall maxw, eax, [vol_min+4]
1045
        mov     [r_vol], eax
1046
        mov     [edx+STREAM.r_vol], eax
1047
 
1048
        stdcall minw, [pan], [pan_max]
1049
        stdcall maxw, eax, [vol_min]
1050
        mov     [edx+STREAM.pan], eax
1051
 
1052
        cmp     word [edx+STREAM.pan], 0
1053
        jl      @f
1054
 
1055
        mov     ebx, [l_vol]
1056
        sub     ebx, eax
1057
        stdcall minw, ebx, [vol_max]
1058
        stdcall maxw, eax, [vol_min]
1059
        mov     [l_vol], eax
1060
        jmp     .calc_amp
1061
@@:
1062
        mov     ebx, [r_vol]
1063
        add     ebx, [pan]
1064
        stdcall minw, ebx, [vol_max+4]
1065
        stdcall maxw, eax, [vol_min+4]
1066
        mov     [r_vol], eax
1067
.calc_amp:
1068
        emms
1069
        fild    word [l_vol]
1070
 
1071
        call    .calc
1072
 
1073
        fistp   word [edx+STREAM.l_amp]
1074
        fstp    dword [edx+STREAM.l_amp_f]
1075
        fstp    st0
1076
 
1077
        fild    word [r_vol]
1078
 
1079
        call    .calc
1080
 
1081
        fistp   word [edx+STREAM.r_amp]
1082
        fstp    dword [edx+STREAM.r_amp_f]
1083
        fstp    st0
1084
 
1085
        fnclex
1086
        lea     ebx, [state]
1087
        frstor  [ebx]
1088
 
1089
        xor     eax, eax
1090
        inc     eax
1091
        ret
1092
.calc:
1093
        fdiv    dword [_600]
1094
        fld     st0
1095
        frndint
1096
        fxch    st1
1097
        fsub    st, st1
1098
        f2xm1
1099
        fld1
1100
        faddp   st1, st0
1101
        fscale
1102
        fld     st0
1103
        fimul   dword [_32767]
1104
        ret     0
1105
endp
1106
 
1107
 
1108
align 4
1109
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
1110
 
1111
        mov     edx, [str]
1112
        mov     eax, [p_lvol]
1113
        movsx   ecx, word [edx+STREAM.l_vol]
1114
        mov     [eax], ecx
1115
 
1116
        mov     eax, [p_rvol]
1117
        movsx   ecx, word [edx+STREAM.r_vol]
1118
        mov     [eax], ecx
1119
        xor     eax, eax
1120
        ret
1121
endp
1122
 
1123
align 4
1124
proc SetBufferPan stdcall, str:dword,pan:dword
1125
 
1126
        mov     edx, [str]
1127
        stdcall set_vol_param, [edx+STREAM.l_vol], \
1128
                [edx+STREAM.r_vol],[pan]
1129
        ret
1130
endp
1131
 
1132
; for static and ring buffers only
1133
 
1134
align 4
1135
proc play_buffer stdcall, str:dword, flags:dword
1136
 
1137
        mov     ebx, [str]
1138
        mov     eax, [ebx+STREAM.format]
1139
        test    eax, PCM_OUT
1140
        jnz     .fail
1141
 
1142
        cmp     ax, PCM_ALL
1143
        je      .fail
1144
 
1145
        mov     [ebx+STREAM.flags], SND_PLAY
1146
        cmp     [eng_state], SND_PLAY
1147
        je      .done
1148
 
1149
        stdcall dev_play, [hSound]
1150
        mov     [eng_state], SND_PLAY
1151
.done:
1152
        test    [flags], PLAY_SYNC
1153
        jz      @F
1154
 
1155
        mov     edx, [str]
1156
.wait:
1157
        mov     eax, [edx+STREAM.notify_event]
1158
        mov     ebx, [edx+STREAM.notify_id]
1159
        call    WaitEvent   ;eax ebx
1160
 
1161
        mov     edx, [str]
1162
        cmp     [edx+STREAM.flags], SND_STOP
1163
        jne     .wait
1164
@@:
1165
        xor     eax, eax
1166
        ret
1167
.fail:
1168
        or      eax, -1
1169
        ret
1170
endp
1171
 
1172
; for static and ring buffers only
1173
 
1174
align 4
1175
proc stop_buffer stdcall, str:dword
1176
 
1177
        mov     edx, [str]
1178
        test    [edx+STREAM.format], PCM_STATIC+PCM_RING
1179
        jz      .fail
1180
 
1181
        mov     [edx+STREAM.flags], SND_STOP
1182
 
1183
        mov     eax, [edx+STREAM.notify_event]
1184
        mov     ebx, [edx+STREAM.notify_id]
1185
        call    ClearEvent   ;eax ebx
1186
 
1187
        xor     eax, eax
1188
        ret
1189
.fail:
1190
        or      eax, -1
1191
        ret
1192
endp
1193
 
1194
; param
1195
;  eax= mix_list
1196
 
1197
align 4
1198
do_mix_list:
1199
 
1200
        xor     edx, edx
1201
        mov     esi, str.fd-FD_OFFSET
1202
        mov     ebx, [esi+STREAM.str_fd]
1203
@@:
1204
        cmp     ebx, esi
1205
        je      .done
1206
 
1207
        cmp     [ebx+STREAM.magic], 'WAVE'
1208
        jne     .next
1209
 
1210
        cmp     [ebx+STREAM.size], STREAM.sizeof
1211
        jne     .next
1212
 
1213
        cmp     [ebx+STREAM.flags], SND_PLAY;
1214
        jne     .next
1215
 
1216
        mov     ecx, [ebx+STREAM.out_count]
1217
        test    ecx, ecx
1218
        jnz     .l1
1219
 
1220
        test    [ebx+STREAM.format], PCM_RING
1221
        jnz     .next
1222
        mov     [ebx+STREAM.flags], SND_STOP
1223
        jmp     .next
1224
.l1:
1225
        cmp     ecx, 512
1226
        jae     .add_buff
1227
 
1228
        mov     edi, [ebx+STREAM.out_rp]
1229
        add     edi, ecx
1230
        sub     ecx, 512
1231
        neg     ecx
1232
        push    eax
1233
        xor     eax, eax
1234
        cld
1235
        rep stosb
1236
        pop     eax
1237
 
1238
        mov     [ebx+STREAM.out_count], 512
1239
 
1240
.add_buff:
1241
        mov     ecx, [ebx+STREAM.out_rp]
1242
        mov     [eax], ecx
1243
 
1244
if USE_SSE2_MIXER
1245
        mov     edi, dword [ebx+STREAM.l_amp_f]
1246
        mov     [eax+4], edi
1247
        mov     edi, dword [ebx+STREAM.r_amp_f]
1248
        mov     [eax+8], edi
1249
else
1250
        mov     edi, dword [ebx+STREAM.l_amp]
1251
        mov     [eax+4], edi
1252
end if
1253
        add     [ebx+STREAM.out_rp], 512
1254
        sub     [ebx+STREAM.out_count], 512
1255
 
1256
        add     eax, 12
1257
        inc     edx
1258
.next:
1259
        mov     ebx, [ebx+STREAM.str_fd]
1260
        jmp     @B
1261
.done:
1262
        mov     eax, edx
1263
        ret
1264
 
1265
align 4
1266
prepare_playlist:
1267
 
1268
        xor     edx, edx
1269
        mov     [play_count], edx
1270
        mov     esi, str.fd-FD_OFFSET
1271
        mov     edi, [esi+STREAM.str_fd]
1272
@@:
1273
        cmp     edi, esi
1274
        je      .done
1275
 
1276
        cmp     [edi+STREAM.magic], 'WAVE'
1277
        jne     .next
1278
 
1279
        cmp     [edi+STREAM.size], STREAM.sizeof
1280
        jne     .next
1281
 
1282
        cmp     [edi+STREAM.flags], SND_PLAY;
1283
        jne     .next
1284
 
1285
        mov     [play_list+edx], edi
1286
        inc     [play_count]
1287
        add     edx, 4
1288
.next:
1289
        mov     edi, [edi+STREAM.str_fd]
1290
        jmp     @B
1291
.done:
1292
        ret
1293
 
1294
align 4
1295
proc set_handler stdcall, hsrv:dword, handler_proc:dword
1296
           locals
1297
             handler    dd ?
1298
             io_code    dd ?
1299
             input      dd ?
1300
             inp_size   dd ?
1301
             output     dd ?
1302
             out_size   dd ?
1303
             val        dd ?
1304
           endl
1305
 
1306
        mov     eax, [hsrv]
1307
        lea     ecx, [handler_proc]
1308
        xor     ebx, ebx
1309
 
1310
        mov     [handler], eax
1311
        mov     [io_code], DEV_CALLBACK
1312
        mov     [input], ecx
1313
        mov     [inp_size], 4
1314
        mov     [output], ebx
1315
        mov     [out_size], 0
1316
 
1317
        lea     eax, [handler]
1318
        stdcall ServiceHandler, eax
1319
        ret
1320
endp
1321
 
1322
align 4
1323
proc dev_play stdcall, hsrv:dword
1324
           locals
1325
             handle     dd ?
1326
             io_code    dd ?
1327
             input      dd ?
1328
             inp_size   dd ?
1329
             output     dd ?
1330
             out_size   dd ?
1331
             val        dd ?
1332
           endl
1333
 
1334
        mov     eax, [hsrv]
1335
        xor     ebx, ebx
1336
 
1337
        mov     [handle], eax
1338
        mov     [io_code], DEV_PLAY
1339
        mov     [input], ebx
1340
        mov     [inp_size], ebx
1341
        mov     [output], ebx
1342
        mov     [out_size], ebx
1343
 
1344
        lea     eax, [handle]
1345
        stdcall ServiceHandler, eax
1346
        ret
1347
endp
1348
 
1349
if 0
1350
align 4
1351
dword2str:
1352
        mov     esi, hex_buff
1353
        mov     ecx, -8
1354
@@:
1355
        rol     eax, 4
1356
        mov     ebx, eax
1357
        and     ebx, 0x0F
1358
        mov     bl, [ebx+hexletters]
1359
        mov     [8+esi+ecx], bl
1360
        inc     ecx
1361
        jnz     @B
1362
        ret
1363
 
1364
hexletters   db '0123456789ABCDEF'
1365
hex_buff     db 8 dup(0),13,10,0
1366
 
1367
end if
1368
 
1369
include 'mixer.asm'
1370
include 'mix_mmx.inc'
1371
include 'mix_sse2.inc'
1372
 
1373
;if USE_SSE
1374
; include 'mix_sse.inc'
1375
;end if
1376
 
1377
align 16
1378
resampler_params:
1379
     ;r_size    r_dt   resampler_func
1380
     dd 0,0,0                                  ; 0  PCM_ALL
1381
     dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
1382
     dd  8192,      0, m16_stereo     ; 2  PCM_1_16_48
1383
 
1384
     dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
1385
     dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
1386
 
1387
     dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
1388
     dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
1389
 
1390
     dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
1391
     dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
1392
 
1393
     dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
1394
     dd  4096,  15052, resample_1     ;10  PCM_1_16_22
1395
 
1396
     dd  8192,  10923, resample_2     ;11  PCM_2_16_16
1397
     dd  4096,  10923, resample_1     ;12  PCM_1_16_16
1398
 
1399
     dd  8192,   8192, resample_2     ;13  PCM_2_16_12
1400
     dd  4096,   8192, resample_1     ;14  PCM_1_16_12
1401
 
1402
     dd  4096,   7527, resample_2     ;15  PCM_2_16_11
1403
     dd  2048,   7527, resample_1     ;16  PCM_1_16_11
1404
 
1405
     dd  4096,   5462, resample_2     ;17  PCM_2_16_8
1406
     dd  2048,   5462, resample_1     ;18  PCM_1_16_8
1407
 
1408
     dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
1409
     dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
1410
 
1411
     dd  8192,  30109, resample_28    ;21  PCM_2_8_44
1412
     dd  4096,  30109, resample_18    ;22  PCM_1_8_44
1413
 
1414
     dd  8192,  21846, resample_28    ;23  PCM_2_8_32
1415
     dd  4096,  21846, resample_18    ;24  PCM_1_8_32
1416
 
1417
     dd  8192,  16384, resample_28    ;25  PCM_2_8_24
1418
     dd  4096,  16384, resample_18    ;26  PCM_1_8_24
1419
 
1420
     dd  4096,  15052, resample_28    ;27  PCM_2_8_22
1421
     dd  2048,  15052, resample_18    ;28  PCM_1_8_22
1422
 
1423
     dd  4096,  10923, resample_28    ;29  PCM_2_8_16
1424
     dd  2048,  10923, resample_18    ;30  PCM_1_8_16
1425
 
1426
     dd  4096,   8192, resample_28    ;31  PCM_2_8_12
1427
     dd  2048,   8192, resample_18    ;32  PCM_1_8_12
1428
 
1429
     dd  2048,   7527, resample_28    ;33  PCM_2_8_11
1430
     dd  1024,   7527, resample_18    ;34  PCM_1_8_11
1431
 
1432
     dd  2048,   5462, resample_28    ;35  PCM_2_8_8
1433
     dd  1024,   5462, resample_18    ;36  PCM_1_8_8
1434
 
1435
m7            dw 0x8000,0x8000,0x8000,0x8000
1436
mm80          dq 0x8080808080808080
1437
mm_mask       dq 0xFF00FF00FF00FF00
1438
 
1439
vol_max       dd 0x00000000,0x00000000
1440
vol_min       dd 0x0000D8F0,0x0000D8F0
1441
pan_max       dd 0x00002710,0x00002710
1442
 
1443
;stream_map    dd 0xFFFF       ; 16
1444
version       dd (5 shl 16) or SOUND_VERSION
1445
 
1446
szInfinity    db 'INFINITY',0
1447
szSound       db 'SOUND',0
1448
 
1449
if DEBUG
1450
msgFail       db 'Sound service not loaded',13,10,0
1451
msgPlay       db 'Play buffer',13,10,0
1452
msgStop       db 'Stop',13,10,0
1453
msgUser       db 'User callback',13,10,0
1454
msgMem        db 'Not enough memory',13,10,0
1455
msgDestroy    db 'Destroy sound buffer', 13,10,0
1456
msgWaveout    db 'Play waveout', 13,10,0
1457
msgSetVolume  db 'Set volume',13,10,0
1458
end if
1459
 
1460
section '.data' data readable writable align 16
1461
 
1462
play_list     rd 16
1463
mix_input     rd 16
1464
play_count    rd 1
1465
hSound        rd 1
1466
eng_state     rd 1
1467
mix_buff      rd 1
1468
mix_buff_map  rd 1
1469
str.fd        rd 1
1470
str.bk        rd 1
1471
 
1472
mix_2_core    rd 1
1473
mix_3_core    rd 1
1474
mix_4_core    rd 1