Subversion Repositories Kolibri OS

Rev

Rev 568 | 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'
520 serge 18
 
19
;include 'system.inc'
168 serge 20
include 'main.inc'
520 serge 21
 
281 serge 22
include 'imports.inc'
168 serge 23
 
378 serge 24
FORCE_MMX         equ 0  ;set to 1 to force use mmx or
25
FORCE_MMX_128     equ 0  ;integer sse2 extensions
293 serge 26
                        ;and reduce driver size
378 serge 27
;USE_SSE          equ 0
168 serge 28
 
378 serge 29
DEBUG             equ 1
168 serge 30
 
291 serge 31
 
465 serge 32
OS_BASE           equ 0x80000000
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
           stdcall CreateBuffer,[ebx],[ebx+4]
561 serge 178
           mov edi, [ioctl]
378 serge 179
           mov ecx, [edi+output]
180
           mov ecx, [ecx]
465 serge 181
           mov [ecx], ebx
227 serge 182
           ret
168 serge 183
@@:
378 serge 184
           mov ebx, [edi+input]
185
           mov edx, [ebx]
186
 
187
           cmp [edx+STREAM.magic], 'WAVE'
188
           jne .fail
189
 
190
           cmp [edx+STREAM.size], STREAM_SIZE
191
           jne .fail
192
 
193
           cmp eax, SND_DESTROY_BUFF
227 serge 194
           jne @F
378 serge 195
           mov eax, edx
196
           call DestroyBuffer    ;edx= stream
227 serge 197
           ret
168 serge 198
@@:
378 serge 199
           cmp eax, SND_SETFORMAT
227 serge 200
           jne @F
572 serge 201
           stdcall SetFormat,edx,[ebx+4]
378 serge 202
           ret
203
@@:
204
           cmp eax, SND_GETFORMAT
205
           jne @F
168 serge 206
 
378 serge 207
           movzx eax, word [edx+STREAM.format]
208
           mov ecx, [edi+output]
209
           mov ecx, [ecx]
465 serge 210
           mov [ecx], eax
378 serge 211
           xor eax, eax
227 serge 212
           ret
168 serge 213
@@:
378 serge 214
           cmp eax, SND_RESET
215
           jne @F
572 serge 216
           stdcall ResetBuffer,edx,[ebx+4]
378 serge 217
           ret
218
@@:
219
           cmp eax, SND_SETPOS
220
           jne @F
572 serge 221
           stdcall SetBufferPos,edx,[ebx+4]
378 serge 222
           ret
223
@@:
224
           cmp eax, SND_GETPOS
225
           jne @F
572 serge 226
           stdcall GetBufferPos, edx
561 serge 227
           mov edi, [ioctl]
378 serge 228
           mov ecx, [edi+output]
229
           mov ecx, [ecx]
465 serge 230
           mov [ecx], ebx
378 serge 231
           ret
232
@@:
227 serge 233
           cmp eax, SND_SETBUFF
234
           jne @F
235
           mov eax, [ebx+4]
572 serge 236
           stdcall set_buffer, edx,eax,[ebx+8],[ebx+12]
227 serge 237
           ret
168 serge 238
@@:
378 serge 239
           cmp eax, SND_SETVOLUME
227 serge 240
           jne @F
572 serge 241
           stdcall SetBufferVol,edx,[ebx+4],[ebx+8]
378 serge 242
           ret
243
@@:
244
           cmp eax, SND_GETVOLUME
245
           jne @F
168 serge 246
 
378 serge 247
           mov eax, [edi+output]
248
           mov ecx, [eax]
249
           mov eax, [eax+4]
572 serge 250
           stdcall GetBufferVol,edx,ecx,eax
227 serge 251
           ret
168 serge 252
@@:
378 serge 253
           cmp eax, SND_SETPAN
254
           jne @F
572 serge 255
           stdcall SetBufferPan,edx,[ebx+4]
378 serge 256
           ret
257
@@:
258
           cmp eax, SND_GETPAN
259
           jne @F
260
           mov eax, [edx+STREAM.pan]
261
           mov ebx, [edi+output]
262
           mov ebx, [ebx]
465 serge 263
           mov [ebx], eax
227 serge 264
           xor eax, eax
265
           ret
378 serge 266
@@:
267
           cmp eax, SND_OUT
268
           jne @F
269
 
270
           mov eax, [ebx+4]
572 serge 271
           stdcall wave_out, edx,eax,[ebx+8]
378 serge 272
           ret
273
@@:
274
           cmp eax, SND_PLAY
275
           jne @F
276
 
572 serge 277
           stdcall play_buffer, edx,[ebx+4]
378 serge 278
           ret
279
@@:
280
           cmp eax, SND_STOP
281
           jne @F
282
 
572 serge 283
           stdcall stop_buffer, edx
378 serge 284
           ret
285
@@:
286
           cmp eax, SND_GETBUFFSIZE
287
           jne @F
288
           mov eax, [edx+STREAM.in_size]
289
           mov ecx, [edi+output]
290
           mov ecx, [ecx]
465 serge 291
           mov [ecx], eax
378 serge 292
           xor eax, eax
293
           ret
294
@@:
572 serge 295
           cmp eax, SND_GETFREESPACE
296
           jne @F
297
 
298
           test [edx+STREAM.format], PCM_OUT
299
           jz .fail
300
 
301
           mov ebx, [edx+STREAM.in_free]
302
           mov ecx, [edi+output]
303
           mov [ecx], ebx
304
           xor eax, eax
305
           ret
306
@@:
378 serge 307
.fail:
308
           or eax, -1
309
           ret
168 serge 310
endp
311
 
312
restore   handle
313
restore   io_code
314
restore   input
315
restore   inp_size
316
restore   output
317
restore   out_size
318
 
328 serge 319
align 4
378 serge 320
proc CreateBuffer stdcall, format:dword, size:dword
227 serge 321
           locals
378 serge 322
             str         dd ?
323
             ring_size   dd ?
324
             ring_pages  dd ?
227 serge 325
           endl
168 serge 326
 
378 serge 327
           mov eax, [format]
328
           cmp ax, PCM_1_8_8
329
           ja .fail
330
 
331
           test eax, PCM_OUT
332
           jnz .test_out
333
           test eax, PCM_RING
334
           jnz .test_ring
335
;staic
567 serge 336
           test eax, PCM_STATIC
568 serge 337
           jz .test_out                   ;use PCM_OUT as default format
378 serge 338
           jmp .test_ok
339
.test_out:
340
           test eax, PCM_RING+PCM_STATIC
341
           jnz .fail
568 serge 342
           or [format], PCM_OUT           ;force set
378 serge 343
           jmp .test_ok
344
.test_ring:
345
           test eax, PCM_OUT+PCM_STATIC
346
           jnz .fail
347
.test_ok:
520 serge 348
 
349
           call GetPid
350
           mov ebx, eax
291 serge 351
           mov eax, STREAM_SIZE
352
 
353
           call CreateObject
354
           test eax, eax
227 serge 355
           jz .fail
356
           mov [str], eax
168 serge 357
 
378 serge 358
           mov ebx, [format]
359
           mov [eax+STREAM.format], ebx
168 serge 360
 
378 serge 361
           xor ecx, ecx
362
           movzx ebx, bx
363
           cmp ebx, 19
364
           jb @f
365
           mov ecx, 0x80808080
366
@@:
367
           mov [eax+STREAM.r_silence], ecx
168 serge 368
 
378 serge 369
           shl ebx, 2
370
           lea ebx, [ebx+ebx*2]     ;ebx*=12
168 serge 371
 
378 serge 372
           mov ecx, [resampler_params+ebx]
373
           mov edx, [resampler_params+ebx+4]
374
           mov esi, [resampler_params+ebx+8]
375
 
376
           mov [eax+STREAM.r_size],ecx
377
           mov [eax+STREAM.r_dt],  edx
378
           mov [eax+STREAM.resample], esi
379
           xor ecx, ecx
380
           mov [eax+STREAM.l_vol], ecx
381
           mov [eax+STREAM.r_vol], ecx
382
           mov dword [eax+STREAM.l_amp], 0x7FFF7FFF
383
           mov [eax+STREAM.pan], ecx
384
 
385
           test [format], PCM_STATIC
386
           jnz .static
387
 
388
; ring and waveout
389
 
465 serge 390
           mov ebx, 0x10000
378 serge 391
           test [format], PCM_RING
392
           jz .waveout
393
 
465 serge 394
           mov ebx, [eax+STREAM.r_size]
395
           add ebx, 4095
396
           and ebx, -4096
397
           add ebx, ebx
378 serge 398
.waveout:
465 serge 399
           mov [ring_size], ebx
400
           mov eax, ebx
378 serge 401
           shr ebx, 12
402
           mov [ring_pages], ebx
403
 
520 serge 404
           stdcall CreateRingBuffer, eax, PG_SW
405
 
227 serge 406
           mov edi, [str]
378 serge 407
           mov ecx, [ring_size]
408
           mov [edi+STREAM.in_base], eax
409
           mov [edi+STREAM.in_size], ecx
410
           add eax, 128
561 serge 411
        ;   sub ecx, 128
378 serge 412
           mov [edi+STREAM.in_wp], eax
413
           mov [edi+STREAM.in_rp], eax
414
           mov [edi+STREAM.in_count], 0
168 serge 415
 
378 serge 416
           mov [edi+STREAM.in_free], ecx
417
           add eax, ecx
418
           mov [edi+STREAM.in_top], eax
328 serge 419
 
378 serge 420
           jmp .out_buff
421
.static:
422
           mov ecx, [size]
423
           add ecx, 128          ;resampler required
424
           mov [eax+STREAM.in_size], ecx
425
           stdcall KernelAlloc, ecx
426
 
427
           mov edi, [str]
428
           mov [edi+STREAM.in_base], eax
429
           add eax, 128
430
           mov [edi+STREAM.in_wp], eax
431
           mov [edi+STREAM.in_rp], eax
432
           mov ebx, [size]
433
           mov [edi+STREAM.in_count], ebx
434
           mov [edi+STREAM.in_free], ebx
435
           add eax, ebx
436
           mov [edi+STREAM.in_top], eax
437
 
438
.out_buff:
328 serge 439
           stdcall AllocKernelSpace, dword 128*1024
440
 
441
           mov edi, [str]
378 serge 442
           mov [edi+STREAM.out_base], eax
443
           mov [edi+STREAM.out_wp], eax
444
           mov [edi+STREAM.out_rp], eax
445
           mov [edi+STREAM.out_count], 0
328 serge 446
           add eax, 64*1024
378 serge 447
           mov [edi+STREAM.out_top], eax
168 serge 448
 
328 serge 449
           stdcall AllocPages, dword 64/4
450
           mov edi, [str]
378 serge 451
           mov ebx, [edi+STREAM.out_base]
328 serge 452
           mov ecx, 16
453
           or eax, PG_SW
454
           push eax
455
           push ebx
456
           call CommitPages ;eax, ebx, ecx
457
           mov ecx, 16
458
           pop ebx
459
           pop eax
460
           add ebx, 64*1024
461
           call CommitPages    ;double mapped
462
 
463
           mov edi, [str]
378 serge 464
           mov ecx, [edi+STREAM.in_top]
465
           mov edi, [edi+STREAM.in_base]
466
           sub ecx, edi
227 serge 467
           xor eax, eax
378 serge 468
           shr ecx, 2
328 serge 469
           cld
227 serge 470
           rep stosd
168 serge 471
 
328 serge 472
           mov edi, [str]
378 serge 473
           mov edi, [edi+STREAM.out_base]
328 serge 474
           mov ecx, (64*1024)/4
475
           rep stosd
476
 
378 serge 477
           xor edx, edx
478
           mov ebx, MANUAL_DESTROY
479
           call CreateEvent
480
 
481
           mov ebx, [str]
482
           mov [ebx+STREAM.notify_event], eax
483
           mov [ebx+STREAM.notify_id], edx
484
 
485
           mov [ebx+STREAM.magic], 'WAVE'
486
           mov [ebx+STREAM.destroy], DestroyBuffer.destroy
487
           mov [ebx+STREAM.size], STREAM_SIZE
488
           mov [ebx+STREAM.flags], SND_STOP
489
 
490
           pushf
491
           cli
492
           mov eax, str.fd-FD_OFFSET
493
           mov edx, [eax+STREAM.str_fd]
494
           mov [ebx+STREAM.str_fd], edx
495
           mov [ebx+STREAM.str_bk], eax
496
           mov [eax+STREAM.str_fd], ebx
497
           mov [edx+STREAM.str_bk], ebx
498
           popf
499
 
500
           xor eax, eax
227 serge 501
           ret
168 serge 502
.fail:
378 serge 503
           xor ebx, ebx
504
           or eax, -1
227 serge 505
           ret
168 serge 506
endp
507
 
291 serge 508
;param
509
; eax= buffer handle
510
 
168 serge 511
align 4
291 serge 512
DestroyBuffer:
328 serge 513
           .handle  equ esp       ;local
168 serge 514
 
378 serge 515
           mov [eax+STREAM.flags], SND_STOP
291 serge 516
.destroy:
328 serge 517
           push eax
518
 
378 serge 519
           pushfd
291 serge 520
           cli
521
           mov ebx, [eax+STREAM.str_fd]
522
           mov ecx, [eax+STREAM.str_bk]
523
           mov [ebx+STREAM.str_bk], ecx
524
           mov [ecx+STREAM.str_fd], ebx
525
           popf
168 serge 526
 
378 serge 527
           stdcall KernelFree, [eax+STREAM.in_base]
328 serge 528
           mov eax, [.handle]
378 serge 529
           stdcall KernelFree, [eax+STREAM.out_base]
328 serge 530
 
531
           pop eax               ;restore stack
378 serge 532
           call DestroyObject    ;eax= stream
533
           xor eax, eax
534
           ret
168 serge 535
.fail:
378 serge 536
           or eax, -1
227 serge 537
           ret
378 serge 538
restore .handle
168 serge 539
 
540
align 4
378 serge 541
proc SetFormat stdcall, str:dword, format:dword
168 serge 542
 
378 serge 543
           cmp word [format], PCM_1_8_8
544
           ja .fail
168 serge 545
 
378 serge 546
           mov edx, [str]
547
           mov [edx+STREAM.flags], SND_STOP
168 serge 548
 
378 serge 549
           test [edx+STREAM.format], PCM_RING
550
           jnz .fail
168 serge 551
 
378 serge 552
;           mov eax,[edx+STREAM.out_base]
553
;           mov [edx+STREAM.out_wp], eax
554
;           mov [edx+STREAM.out_rp], eax
555
;           mov [edx+STREAM.out_count], 0
168 serge 556
 
378 serge 557
           movzx eax, word [format]
558
           mov word [edx+STREAM.format], ax
559
 
560
           xor ebx, ebx
561
           cmp eax, 19
562
           jb @f
563
           mov ebx, 0x80808080
168 serge 564
@@:
378 serge 565
           mov [edx+STREAM.r_silence], ebx
168 serge 566
 
378 serge 567
           shl eax, 2
568
           lea eax, [eax+eax*2]     ;eax*=12
168 serge 569
 
378 serge 570
           mov edi, [resampler_params+eax]
571
           mov ecx, [resampler_params+eax+4]
572
           mov ebx, [resampler_params+eax+8]
168 serge 573
 
378 serge 574
           mov [edx+STREAM.r_size],edi
575
           mov [edx+STREAM.r_dt],  ecx
576
           mov [edx+STREAM.resample], ebx
168 serge 577
 
378 serge 578
           mov edi, [edx+STREAM.in_base]
579
           mov ecx, 128/4
580
           mov eax, [edx+STREAM.r_silence]
285 serge 581
           cld
582
           rep stosd
227 serge 583
           xor eax, eax
584
           ret
168 serge 585
.fail:
378 serge 586
           or eax, -1
227 serge 587
           ret
168 serge 588
endp
589
 
378 serge 590
; for static buffers only
591
; use waveout for streams
592
 
168 serge 593
align 4
378 serge 594
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
168 serge 595
 
378 serge 596
           mov edx, [str]
597
           test [edx+STREAM.format], PCM_OUT
598
           jnz .fail
168 serge 599
 
378 serge 600
           mov esi, [src]
601
           mov edi, [offs]
602
           add edi, [edx+STREAM.in_base]
603
           add edi, 128
168 serge 604
 
378 serge 605
           cmp edi, [edx+STREAM.in_top]
606
           jae .fail
168 serge 607
 
378 serge 608
           mov ecx, [size]
609
           lea ebx, [ecx+edi]
610
           sub ebx, [edx+STREAM.in_top]
611
           jb @F
612
           sub ecx, ebx
613
@@:
614
           shr ecx, 2
615
           cld
616
           rep movsd
617
           xor eax,eax
227 serge 618
           ret
168 serge 619
.fail:
378 serge 620
           or eax, -1
227 serge 621
           ret
168 serge 622
endp
623
 
378 serge 624
; for stream buffers only
625
 
168 serge 626
align 4
378 serge 627
proc wave_out stdcall, str:dword,src:dword,size:dword
628
           locals
629
             state_saved  dd ?
630
             fpu_state    rb 528
631
           endl
168 serge 632
 
227 serge 633
           mov edx, [str]
378 serge 634
           mov eax, [edx+STREAM.format]
568 serge 635
           test eax, PCM_OUT
636
           jz .fail
168 serge 637
 
378 serge 638
           cmp ax, PCM_ALL
639
           je .fail
168 serge 640
 
227 serge 641
           mov esi,[src]
642
           test esi, esi
643
           jz .fail
168 serge 644
 
465 serge 645
           cmp esi, OS_BASE
646
           ja .fail
168 serge 647
 
378 serge 648
           mov [state_saved], 0
168 serge 649
 
378 serge 650
.main_loop:
651
           mov edx, [str]
168 serge 652
 
378 serge 653
           mov ebx, [size]
654
           test ebx, ebx
655
           jz .done
656
 
657
           cmp [edx+STREAM.flags], SND_STOP
658
           jne .fill
659
 
660
           mov edi, [edx+STREAM.in_base]
661
           mov ecx, 128/4
662
           mov eax, [edx+STREAM.r_silence]
663
           cld
664
           rep stosd
665
 
666
           mov ecx, [edx+STREAM.in_size]
667
           sub ecx, 128
668
           mov [edx+STREAM.in_wp], edi
669
           mov [edx+STREAM.in_rp], edi
670
           mov [edx+STREAM.in_count], 0
671
           mov [edx+STREAM.in_free], ecx
672
 
673
           mov eax,[edx+STREAM.out_base]
674
           mov [edx+STREAM.out_wp], eax
675
           mov [edx+STREAM.out_rp], eax
676
           mov [edx+STREAM.out_count], 0
677
.fill:
678
           mov ecx, [edx+STREAM.in_free]
679
           test ecx, ecx
680
           jz .wait
681
 
682
           cmp ecx, ebx
683
           jbe @F
684
 
685
           mov ecx, ebx
686
@@:
285 serge 687
           sub [size], ecx
378 serge 688
           add [edx+STREAM.in_count], ecx
689
           sub [edx+STREAM.in_free], ecx
168 serge 690
 
285 serge 691
           shr ecx, 2
378 serge 692
           mov edi, [edx+STREAM.in_wp]
693
           mov esi, [src]
285 serge 694
           cld
695
           rep movsd
378 serge 696
 
697
           mov [src], esi
698
           cmp edi, [edx+STREAM.in_top]
699
           jb @F
700
           sub edi, [edx+STREAM.in_size]
285 serge 701
@@:
378 serge 702
           mov [edx+STREAM.in_wp], edi
168 serge 703
 
378 serge 704
           cmp [edx+STREAM.out_count], 32768
705
           jae .skip
706
 
707
           cmp [state_saved], 0
708
           jne @F
709
           lea eax, [fpu_state+15]
710
           and eax, -16
711
           call FpuSave
712
           mov [state_saved], 1
713
@@:
714
           stdcall refill, edx
715
.skip:
716
           mov ebx, [str]
717
           mov [ebx+STREAM.flags], SND_PLAY
718
           cmp [eng_state], SND_PLAY
719
           je .main_loop
720
 
721
           stdcall dev_play, [hSound]
722
           mov [eng_state], SND_PLAY
723
           jmp .main_loop
724
.wait:
725
           mov edx, [str]
726
           mov eax, [edx+STREAM.notify_event]
727
           mov ebx, [edx+STREAM.notify_id]
728
           call WaitEvent   ;eax ebx
729
           jmp .main_loop
285 serge 730
.done:
378 serge 731
           cmp [state_saved], 1
732
           jne @F
733
 
734
           lea eax, [fpu_state+15]
735
           and eax, -16
736
           call FpuRestore
737
@@:
227 serge 738
           xor eax, eax
378 serge 739
           ret
740
.fail:
741
           or eax, -1
742
           ret
743
endp
744
 
745
; both static and stream
746
; reset all but not clear buffers
747
 
748
 
749
; flags reserved
750
;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
751
;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
752
;  RESET_ALL    equ 3
753
 
754
 
755
align 4
756
proc ResetBuffer stdcall, str:dword, flags:dword
757
 
758
           mov edx, [str]
759
           mov [edx+STREAM.flags], SND_STOP
760
 
761
           mov edi, [edx+STREAM.in_base]
762
           mov ecx, 128/4
763
           mov eax, [edx+STREAM.r_silence]
764
           cld
765
           rep stosd
766
 
767
           mov [edx+STREAM.in_wp], edi
768
           mov [edx+STREAM.in_rp], edi
769
 
567 serge 770
           test [edx+STREAM.flags], PCM_STATIC
771
           jnz .static
378 serge 772
           mov [edx+STREAM.in_count], 0
567 serge 773
           jmp @F
774
.static:
378 serge 775
           mov eax, [edx+STREAM.in_size]
567 serge 776
           mov [edx+STREAM.in_count], eax
777
@@:
778
 
779
           mov eax, [edx+STREAM.in_size]
378 serge 780
           sub eax, 128
781
           mov [edx+STREAM.in_free], eax
782
 
783
           xor eax, eax
784
           mov ebx,[edx+STREAM.out_base]
785
           mov [edx+STREAM.out_wp], ebx
786
           mov [edx+STREAM.out_rp], ebx
787
           mov [edx+STREAM.out_count], eax
788
           ret
789
.fail:
790
           or eax, -1
791
           ret
792
endp
793
 
794
; for static buffers only
795
 
796
align 4
797
proc SetBufferPos stdcall, str:dword, pos:dword
798
 
799
           mov edx, [str]
568 serge 800
           test [edx+STREAM.format], PCM_STATIC
801
           jz .fail
378 serge 802
 
803
           mov [edx+STREAM.flags], SND_STOP
804
 
805
           mov eax, [pos]
806
           add eax, [edx+STREAM.in_base]
807
           mov ebx, [edx+STREAM.in_top]
808
           add eax, 128
809
 
810
           cmp eax, ebx
811
           jae .fail
812
 
813
           mov [edx+STREAM.in_rp], eax
814
           sub ebx, eax
815
           mov [edx+STREAM.in_count], ebx
816
           xor eax, eax
817
           ret
818
.fail:
819
           or eax, -1
820
           ret
821
endp
822
 
823
align 4
824
proc GetBufferPos stdcall, str:dword
825
 
826
           mov edx, [str]
568 serge 827
           test [edx+STREAM.format], PCM_STATIC
828
           jz .fail
378 serge 829
 
830
           mov ebx, [edx+STREAM.in_rp]
567 serge 831
           sub ebx, [edx+STREAM.in_base]
832
           sub ebx, 128
378 serge 833
           xor eax, eax
834
           ret
835
.fail:
836
           xor ebx,ebx
837
           or eax, -1
838
           ret
839
endp
840
 
841
; both
842
 
843
align 4
844
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
845
 
846
           mov edx, [str]
847
           stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
848
           ret
849
endp
850
 
851
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
852
           locals
853
             _600    dd ?
854
             _32767  dd ?
855
             state   rb 108
856
           endl
857
 
858
           mov [_600], 0x44160000   ;600.0
859
           mov [_32767], 32767
860
 
861
           lea ebx, [state]
862
           fnsave [ebx]
863
 
864
           movq mm0, qword [l_vol]
865
           pminsw mm0, qword [vol_max]
866
           pmaxsw mm0, qword [vol_min]
867
           movq qword [l_vol], mm0
868
           movq qword [edx+STREAM.l_vol], mm0
869
 
870
           movd mm1,[pan]
871
           pminsw mm1, qword [pan_max]
872
           pmaxsw mm1, qword [vol_min]
873
           movd [edx+STREAM.pan], mm1
874
 
875
           cmp word [edx+STREAM.pan], 0
876
           jl @F
877
 
878
           psubsw mm0,mm1
879
           pminsw mm0, qword [vol_max]
880
           pmaxsw mm0, qword [vol_min]
881
           movd [l_vol],mm0
882
           jmp .calc_amp
883
@@:
884
           punpckhdq mm0,mm0
885
           paddsw mm0,mm1
886
           pminsw mm0, qword [vol_max]
887
           pmaxsw mm0, qword [vol_min]
888
           movd [r_vol], mm0
889
.calc_amp:
890
           emms
891
           fild word [l_vol]
892
 
893
           call .calc
894
 
895
           fistp word [edx+STREAM.l_amp]
896
           fstp st0
897
 
898
           fild word [r_vol]
899
 
900
           call .calc
901
 
902
           fistp word [edx+STREAM.r_amp]
903
           fstp st0
904
 
905
           fnclex
906
           lea ebx, [state]
907
           frstor [ebx]
908
 
909
           xor eax, eax
227 serge 910
           inc eax
911
           ret
378 serge 912
.calc:
913
           fdiv dword [_600]
914
           fld st0
915
           frndint
916
           fxch st1
917
           fsub st, st1
918
           f2xm1
919
           fld1
920
           faddp st1, st0
921
           fscale
922
           fimul dword [_32767]
923
           ret 0
924
endp
925
 
926
align 4
927
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
928
 
929
           mov edx, [str]
930
           mov eax, [p_lvol]
931
           movsx ecx, word [edx+STREAM.l_vol]
932
           mov [eax], ecx
933
 
934
           mov eax, [p_rvol]
935
           movsx ecx, word [edx+STREAM.r_vol]
936
           mov [eax], ecx
937
           xor eax, eax
938
           ret
939
endp
940
 
941
align 4
942
proc SetBufferPan stdcall, str:dword,pan:dword
943
 
944
           mov edx, [str]
945
           stdcall set_vol_param,[edx+STREAM.l_vol],\
946
                                 [edx+STREAM.r_vol],[pan]
947
           ret
948
endp
949
 
950
; for static and ring buffers only
951
 
952
align 4
953
proc play_buffer stdcall, str:dword, flags:dword
954
 
955
           mov ebx, [str]
956
           mov eax, [ebx+STREAM.format]
957
           test eax, PCM_OUT
958
           jnz .fail
959
 
960
           cmp ax, PCM_ALL
961
           je .fail
962
 
963
           mov [ebx+STREAM.flags], SND_PLAY
964
           cmp [eng_state], SND_PLAY
965
           je .done
966
 
967
           stdcall  dev_play, [hSound]
968
           mov [eng_state], SND_PLAY
969
.done:
970
           test [flags], PLAY_SYNC
971
           jz @F
972
 
973
           mov edx, [str]
974
.wait:
975
           mov eax, [edx+STREAM.notify_event]
976
           mov ebx, [edx+STREAM.notify_id]
977
           call WaitEvent   ;eax ebx
978
 
979
           mov edx, [str]
980
           cmp [edx+STREAM.flags], SND_STOP
981
           jne .wait
982
@@:
983
           xor eax, eax
984
           ret
168 serge 985
.fail:
378 serge 986
           or eax, -1
987
           ret
988
endp
989
 
567 serge 990
; for static and ring buffers only
378 serge 991
 
992
align 4
993
proc stop_buffer stdcall, str:dword
994
 
995
           mov edx, [str]
996
           test [edx+STREAM.format], PCM_STATIC+PCM_RING
997
           jz .fail
998
 
999
           mov [edx+STREAM.flags], SND_STOP
1000
 
1001
;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
1002
 
1003
           mov eax, [edx+STREAM.notify_event]
1004
           mov ebx, [edx+STREAM.notify_id]
1005
           call ClearEvent   ;eax ebx
1006
 
227 serge 1007
           xor eax, eax
1008
           ret
378 serge 1009
.fail:
1010
           or eax, -1
1011
           ret
168 serge 1012
endp
1013
 
378 serge 1014
; parm
1015
;  eax= mix_list
1016
 
168 serge 1017
align 4
378 serge 1018
do_mix_list:
1019
 
1020
           xor edx, edx
1021
           mov esi, str.fd-FD_OFFSET
1022
           mov ebx, [esi+STREAM.str_fd]
1023
@@:
1024
           cmp ebx, esi
1025
           je .done
1026
 
1027
           cmp [ebx+STREAM.magic], 'WAVE'
1028
           jne .next
1029
 
1030
           cmp [ebx+STREAM.size], STREAM_SIZE
1031
           jne .next
1032
 
1033
           cmp [ebx+STREAM.flags], SND_PLAY;
1034
           jne .next
1035
 
1036
           mov ecx, [ebx+STREAM.out_count]
1037
           test ecx, ecx
1038
           jnz .l1
1039
 
1040
           test [ebx+STREAM.format], PCM_RING
1041
           jnz .next
1042
           mov [ebx+STREAM.flags], SND_STOP
1043
           jmp .next
1044
.l1:
1045
           cmp ecx, 512
1046
           jae .add_buff
1047
 
1048
           mov edi, [ebx+STREAM.out_rp]
1049
           add edi, ecx
1050
           sub ecx, 512
1051
           neg ecx
1052
           push eax
1053
           xor eax, eax
1054
           cld
1055
           rep stosb
1056
           pop eax
1057
 
1058
           mov [ebx+STREAM.out_count], 512
1059
 
1060
.add_buff:
1061
           mov ecx, [ebx+STREAM.out_rp]
1062
           mov [eax],ecx
1063
           mov edi, dword [ebx+STREAM.l_amp]
1064
           mov [eax+4], edi
1065
           add [ebx+STREAM.out_rp], 512
1066
           sub [ebx+STREAM.out_count], 512
1067
 
1068
           add eax, 8
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
1194
     dd 16384,      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
465 serge 1256
version       dd (5 shl 16) or (SOUND_VERSION and 0xFFFF)
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