Subversion Repositories Kolibri OS

Rev

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

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