Subversion Repositories Kolibri OS

Rev

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

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