Subversion Repositories Kolibri OS

Rev

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

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