Subversion Repositories Kolibri OS

Rev

Rev 465 | 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
           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:
520 serge 337
 
338
           call GetPid
339
           mov ebx, eax
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
 
520 serge 393
           stdcall CreateRingBuffer, eax, PG_SW
394
 
395
if 0
378 serge 396
           stdcall AllocKernelSpace, eax
520 serge 397
end if
227 serge 398
           mov edi, [str]
378 serge 399
           mov ecx, [ring_size]
400
           mov [edi+STREAM.in_base], eax
401
           mov [edi+STREAM.in_size], ecx
402
           add eax, 128
403
           sub ecx, 128
404
           mov [edi+STREAM.in_wp], eax
405
           mov [edi+STREAM.in_rp], eax
406
           mov [edi+STREAM.in_count], 0
168 serge 407
 
378 serge 408
           mov [edi+STREAM.in_free], ecx
409
           add eax, ecx
410
           mov [edi+STREAM.in_top], eax
328 serge 411
 
520 serge 412
if 0
378 serge 413
           mov ebx, [ring_pages]
414
           stdcall AllocPages, ebx
415
           mov edi, [str]
416
           mov ebx, [edi+STREAM.in_base]
417
           mov ecx, [ring_pages]
418
           or eax, PG_SW
419
           push eax
420
           push ebx
421
           call CommitPages ;eax, ebx, ecx
422
           mov ecx, [ring_pages]
423
           pop ebx
424
           pop eax
425
           add ebx, [ring_size]
426
           call CommitPages    ;double mapped
520 serge 427
end if
378 serge 428
           jmp .out_buff
429
.static:
430
           mov ecx, [size]
431
           add ecx, 128          ;resampler required
432
           mov [eax+STREAM.in_size], ecx
433
           stdcall KernelAlloc, ecx
434
 
435
           mov edi, [str]
436
           mov [edi+STREAM.in_base], eax
437
           add eax, 128
438
           mov [edi+STREAM.in_wp], eax
439
           mov [edi+STREAM.in_rp], eax
440
           mov ebx, [size]
441
           mov [edi+STREAM.in_count], ebx
442
           mov [edi+STREAM.in_free], ebx
443
           add eax, ebx
444
           mov [edi+STREAM.in_top], eax
445
 
446
.out_buff:
328 serge 447
           stdcall AllocKernelSpace, dword 128*1024
448
 
449
           mov edi, [str]
378 serge 450
           mov [edi+STREAM.out_base], eax
451
           mov [edi+STREAM.out_wp], eax
452
           mov [edi+STREAM.out_rp], eax
453
           mov [edi+STREAM.out_count], 0
328 serge 454
           add eax, 64*1024
378 serge 455
           mov [edi+STREAM.out_top], eax
168 serge 456
 
328 serge 457
           stdcall AllocPages, dword 64/4
458
           mov edi, [str]
378 serge 459
           mov ebx, [edi+STREAM.out_base]
328 serge 460
           mov ecx, 16
461
           or eax, PG_SW
462
           push eax
463
           push ebx
464
           call CommitPages ;eax, ebx, ecx
465
           mov ecx, 16
466
           pop ebx
467
           pop eax
468
           add ebx, 64*1024
469
           call CommitPages    ;double mapped
470
 
471
           mov edi, [str]
378 serge 472
           mov ecx, [edi+STREAM.in_top]
473
           mov edi, [edi+STREAM.in_base]
474
           sub ecx, edi
227 serge 475
           xor eax, eax
378 serge 476
           shr ecx, 2
328 serge 477
           cld
227 serge 478
           rep stosd
168 serge 479
 
328 serge 480
           mov edi, [str]
378 serge 481
           mov edi, [edi+STREAM.out_base]
328 serge 482
           mov ecx, (64*1024)/4
483
           rep stosd
484
 
378 serge 485
           xor edx, edx
486
           mov ebx, MANUAL_DESTROY
487
           call CreateEvent
488
 
489
           mov ebx, [str]
490
           mov [ebx+STREAM.notify_event], eax
491
           mov [ebx+STREAM.notify_id], edx
492
 
493
           mov [ebx+STREAM.magic], 'WAVE'
494
           mov [ebx+STREAM.destroy], DestroyBuffer.destroy
495
           mov [ebx+STREAM.size], STREAM_SIZE
496
           mov [ebx+STREAM.flags], SND_STOP
497
 
498
           pushf
499
           cli
500
           mov eax, str.fd-FD_OFFSET
501
           mov edx, [eax+STREAM.str_fd]
502
           mov [ebx+STREAM.str_fd], edx
503
           mov [ebx+STREAM.str_bk], eax
504
           mov [eax+STREAM.str_fd], ebx
505
           mov [edx+STREAM.str_bk], ebx
506
           popf
507
 
508
           xor eax, eax
227 serge 509
           ret
168 serge 510
.fail:
378 serge 511
           xor ebx, ebx
512
           or eax, -1
227 serge 513
           ret
168 serge 514
endp
515
 
291 serge 516
;param
517
; eax= buffer handle
518
 
168 serge 519
align 4
291 serge 520
DestroyBuffer:
328 serge 521
           .handle  equ esp       ;local
168 serge 522
 
378 serge 523
           mov [eax+STREAM.flags], SND_STOP
291 serge 524
.destroy:
328 serge 525
           push eax
526
 
378 serge 527
           pushfd
291 serge 528
           cli
529
           mov ebx, [eax+STREAM.str_fd]
530
           mov ecx, [eax+STREAM.str_bk]
531
           mov [ebx+STREAM.str_bk], ecx
532
           mov [ecx+STREAM.str_fd], ebx
533
           popf
168 serge 534
 
378 serge 535
           stdcall KernelFree, [eax+STREAM.in_base]
328 serge 536
           mov eax, [.handle]
378 serge 537
           stdcall KernelFree, [eax+STREAM.out_base]
328 serge 538
 
539
           pop eax               ;restore stack
378 serge 540
           call DestroyObject    ;eax= stream
541
           xor eax, eax
542
           ret
168 serge 543
.fail:
378 serge 544
           or eax, -1
227 serge 545
           ret
378 serge 546
restore .handle
168 serge 547
 
548
align 4
378 serge 549
proc SetFormat stdcall, str:dword, format:dword
168 serge 550
 
378 serge 551
           cmp word [format], PCM_1_8_8
552
           ja .fail
168 serge 553
 
378 serge 554
           mov edx, [str]
555
           mov [edx+STREAM.flags], SND_STOP
168 serge 556
 
378 serge 557
           test [edx+STREAM.format], PCM_RING
558
           jnz .fail
168 serge 559
 
378 serge 560
;           mov eax,[edx+STREAM.out_base]
561
;           mov [edx+STREAM.out_wp], eax
562
;           mov [edx+STREAM.out_rp], eax
563
;           mov [edx+STREAM.out_count], 0
168 serge 564
 
378 serge 565
           movzx eax, word [format]
566
           mov word [edx+STREAM.format], ax
567
 
568
           xor ebx, ebx
569
           cmp eax, 19
570
           jb @f
571
           mov ebx, 0x80808080
168 serge 572
@@:
378 serge 573
           mov [edx+STREAM.r_silence], ebx
168 serge 574
 
378 serge 575
           shl eax, 2
576
           lea eax, [eax+eax*2]     ;eax*=12
168 serge 577
 
378 serge 578
           mov edi, [resampler_params+eax]
579
           mov ecx, [resampler_params+eax+4]
580
           mov ebx, [resampler_params+eax+8]
168 serge 581
 
378 serge 582
           mov [edx+STREAM.r_size],edi
583
           mov [edx+STREAM.r_dt],  ecx
584
           mov [edx+STREAM.resample], ebx
168 serge 585
 
378 serge 586
           mov edi, [edx+STREAM.in_base]
587
           mov ecx, 128/4
588
           mov eax, [edx+STREAM.r_silence]
285 serge 589
           cld
590
           rep stosd
227 serge 591
           xor eax, eax
592
           ret
168 serge 593
.fail:
378 serge 594
           or eax, -1
227 serge 595
           ret
168 serge 596
endp
597
 
378 serge 598
; for static buffers only
599
; use waveout for streams
600
 
168 serge 601
align 4
378 serge 602
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
168 serge 603
 
378 serge 604
           mov edx, [str]
605
           test [edx+STREAM.format], PCM_OUT
606
           jnz .fail
168 serge 607
 
378 serge 608
           mov esi, [src]
609
           mov edi, [offs]
610
           add edi, [edx+STREAM.in_base]
611
           add edi, 128
168 serge 612
 
378 serge 613
           cmp edi, [edx+STREAM.in_top]
614
           jae .fail
168 serge 615
 
378 serge 616
           mov ecx, [size]
617
           lea ebx, [ecx+edi]
618
           sub ebx, [edx+STREAM.in_top]
619
           jb @F
620
           sub ecx, ebx
621
@@:
622
           shr ecx, 2
623
           cld
624
           rep movsd
625
           xor eax,eax
227 serge 626
           ret
168 serge 627
.fail:
378 serge 628
           or eax, -1
227 serge 629
           ret
168 serge 630
endp
631
 
378 serge 632
; for stream buffers only
633
 
168 serge 634
align 4
378 serge 635
proc wave_out stdcall, str:dword,src:dword,size:dword
636
           locals
637
             state_saved  dd ?
638
             fpu_state    rb 528
639
           endl
168 serge 640
 
227 serge 641
           mov edx, [str]
378 serge 642
           mov eax, [edx+STREAM.format]
643
           test eax, PCM_STATIC+PCM_RING
644
           jnz .fail
168 serge 645
 
378 serge 646
           cmp ax, PCM_ALL
647
           je .fail
168 serge 648
 
227 serge 649
           mov esi,[src]
650
           test esi, esi
651
           jz .fail
168 serge 652
 
465 serge 653
           cmp esi, OS_BASE
654
           ja .fail
168 serge 655
 
378 serge 656
           mov [state_saved], 0
168 serge 657
 
378 serge 658
.main_loop:
659
           mov edx, [str]
168 serge 660
 
378 serge 661
           mov ebx, [size]
662
           test ebx, ebx
663
           jz .done
664
 
665
           cmp [edx+STREAM.flags], SND_STOP
666
           jne .fill
667
 
668
           mov edi, [edx+STREAM.in_base]
669
           mov ecx, 128/4
670
           mov eax, [edx+STREAM.r_silence]
671
           cld
672
           rep stosd
673
 
674
           mov ecx, [edx+STREAM.in_size]
675
           sub ecx, 128
676
           mov [edx+STREAM.in_wp], edi
677
           mov [edx+STREAM.in_rp], edi
678
           mov [edx+STREAM.in_count], 0
679
           mov [edx+STREAM.in_free], ecx
680
 
681
           mov eax,[edx+STREAM.out_base]
682
           mov [edx+STREAM.out_wp], eax
683
           mov [edx+STREAM.out_rp], eax
684
           mov [edx+STREAM.out_count], 0
685
.fill:
686
           mov ecx, [edx+STREAM.in_free]
687
           test ecx, ecx
688
           jz .wait
689
 
690
           cmp ecx, ebx
691
           jbe @F
692
 
693
           mov ecx, ebx
694
@@:
285 serge 695
           sub [size], ecx
378 serge 696
           add [edx+STREAM.in_count], ecx
697
           sub [edx+STREAM.in_free], ecx
168 serge 698
 
285 serge 699
           shr ecx, 2
378 serge 700
           mov edi, [edx+STREAM.in_wp]
701
           mov esi, [src]
285 serge 702
           cld
703
           rep movsd
378 serge 704
 
705
           mov [src], esi
706
           cmp edi, [edx+STREAM.in_top]
707
           jb @F
708
           sub edi, [edx+STREAM.in_size]
285 serge 709
@@:
378 serge 710
           mov [edx+STREAM.in_wp], edi
168 serge 711
 
378 serge 712
           cmp [edx+STREAM.out_count], 32768
713
           jae .skip
714
 
715
           cmp [state_saved], 0
716
           jne @F
717
           lea eax, [fpu_state+15]
718
           and eax, -16
719
           call FpuSave
720
           mov [state_saved], 1
721
@@:
722
           stdcall refill, edx
723
.skip:
724
           mov ebx, [str]
725
           mov [ebx+STREAM.flags], SND_PLAY
726
           cmp [eng_state], SND_PLAY
727
           je .main_loop
728
 
729
           stdcall dev_play, [hSound]
730
           mov [eng_state], SND_PLAY
731
           jmp .main_loop
732
.wait:
733
           mov edx, [str]
734
           mov eax, [edx+STREAM.notify_event]
735
           mov ebx, [edx+STREAM.notify_id]
736
           call WaitEvent   ;eax ebx
737
           jmp .main_loop
285 serge 738
.done:
378 serge 739
           cmp [state_saved], 1
740
           jne @F
741
 
742
           lea eax, [fpu_state+15]
743
           and eax, -16
744
           call FpuRestore
745
@@:
227 serge 746
           xor eax, eax
378 serge 747
           ret
748
.fail:
749
           or eax, -1
750
           ret
751
endp
752
 
753
; both static and stream
754
; reset all but not clear buffers
755
 
756
 
757
; flags reserved
758
;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
759
;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
760
;  RESET_ALL    equ 3
761
 
762
 
763
align 4
764
proc ResetBuffer stdcall, str:dword, flags:dword
765
 
766
           mov edx, [str]
767
           mov [edx+STREAM.flags], SND_STOP
768
 
769
           mov edi, [edx+STREAM.in_base]
770
           mov ecx, 128/4
771
           mov eax, [edx+STREAM.r_silence]
772
           cld
773
           rep stosd
774
 
775
           mov [edx+STREAM.in_wp], edi
776
           mov [edx+STREAM.in_rp], edi
777
 
778
           mov [edx+STREAM.in_count], 0
779
           mov eax, [edx+STREAM.in_size]
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]
800
           test [edx+STREAM.format], PCM_OUT+PCM_RING
801
           jnz .fail
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]
827
           test [edx+STREAM.format], PCM_OUT+PCM_RING
828
           jnz .fail
829
 
830
           mov ebx, [edx+STREAM.in_rp]
831
           xor eax, eax
832
           ret
833
.fail:
834
           xor ebx,ebx
835
           or eax, -1
836
           ret
837
endp
838
 
839
; both
840
 
841
align 4
842
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
843
 
844
           mov edx, [str]
845
           stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
846
           ret
847
endp
848
 
849
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
850
           locals
851
             _600    dd ?
852
             _32767  dd ?
853
             state   rb 108
854
           endl
855
 
856
           mov [_600], 0x44160000   ;600.0
857
           mov [_32767], 32767
858
 
859
           lea ebx, [state]
860
           fnsave [ebx]
861
 
862
           movq mm0, qword [l_vol]
863
           pminsw mm0, qword [vol_max]
864
           pmaxsw mm0, qword [vol_min]
865
           movq qword [l_vol], mm0
866
           movq qword [edx+STREAM.l_vol], mm0
867
 
868
           movd mm1,[pan]
869
           pminsw mm1, qword [pan_max]
870
           pmaxsw mm1, qword [vol_min]
871
           movd [edx+STREAM.pan], mm1
872
 
873
           cmp word [edx+STREAM.pan], 0
874
           jl @F
875
 
876
           psubsw mm0,mm1
877
           pminsw mm0, qword [vol_max]
878
           pmaxsw mm0, qword [vol_min]
879
           movd [l_vol],mm0
880
           jmp .calc_amp
881
@@:
882
           punpckhdq mm0,mm0
883
           paddsw mm0,mm1
884
           pminsw mm0, qword [vol_max]
885
           pmaxsw mm0, qword [vol_min]
886
           movd [r_vol], mm0
887
.calc_amp:
888
           emms
889
           fild word [l_vol]
890
 
891
           call .calc
892
 
893
           fistp word [edx+STREAM.l_amp]
894
           fstp st0
895
 
896
           fild word [r_vol]
897
 
898
           call .calc
899
 
900
           fistp word [edx+STREAM.r_amp]
901
           fstp st0
902
 
903
           fnclex
904
           lea ebx, [state]
905
           frstor [ebx]
906
 
907
           xor eax, eax
227 serge 908
           inc eax
909
           ret
378 serge 910
.calc:
911
           fdiv dword [_600]
912
           fld st0
913
           frndint
914
           fxch st1
915
           fsub st, st1
916
           f2xm1
917
           fld1
918
           faddp st1, st0
919
           fscale
920
           fimul dword [_32767]
921
           ret 0
922
endp
923
 
924
align 4
925
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
926
 
927
           mov edx, [str]
928
           mov eax, [p_lvol]
929
           movsx ecx, word [edx+STREAM.l_vol]
930
           mov [eax], ecx
931
 
932
           mov eax, [p_rvol]
933
           movsx ecx, word [edx+STREAM.r_vol]
934
           mov [eax], ecx
935
           xor eax, eax
936
           ret
937
endp
938
 
939
align 4
940
proc SetBufferPan stdcall, str:dword,pan:dword
941
 
942
           mov edx, [str]
943
           stdcall set_vol_param,[edx+STREAM.l_vol],\
944
                                 [edx+STREAM.r_vol],[pan]
945
           ret
946
endp
947
 
948
; for static and ring buffers only
949
 
950
align 4
951
proc play_buffer stdcall, str:dword, flags:dword
952
           locals
953
             fpu_state   rb 528
954
           endl
955
 
956
           mov ebx, [str]
957
           mov eax, [ebx+STREAM.format]
958
           test eax, PCM_OUT
959
           jnz .fail
960
 
961
           cmp ax, PCM_ALL
962
           je .fail
963
 
964
           mov [ebx+STREAM.flags], SND_PLAY
965
           cmp [eng_state], SND_PLAY
966
           je .done
967
 
968
           stdcall  dev_play, [hSound]
969
           mov [eng_state], SND_PLAY
970
.done:
971
           test [flags], PLAY_SYNC
972
           jz @F
973
 
974
           mov edx, [str]
975
.wait:
976
           mov eax, [edx+STREAM.notify_event]
977
           mov ebx, [edx+STREAM.notify_id]
978
           call WaitEvent   ;eax ebx
979
 
980
           mov edx, [str]
981
           cmp [edx+STREAM.flags], SND_STOP
982
           jne .wait
983
@@:
984
           xor eax, eax
985
           ret
168 serge 986
.fail:
378 serge 987
           or eax, -1
988
           ret
989
endp
990
 
991
; for static buffers only
992
 
993
align 4
994
proc stop_buffer stdcall, str:dword
995
 
996
           mov edx, [str]
997
           test [edx+STREAM.format], PCM_STATIC+PCM_RING
998
           jz .fail
999
 
1000
           mov [edx+STREAM.flags], SND_STOP
1001
 
1002
;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
1003
 
1004
           mov eax, [edx+STREAM.notify_event]
1005
           mov ebx, [edx+STREAM.notify_id]
1006
           call ClearEvent   ;eax ebx
1007
 
227 serge 1008
           xor eax, eax
1009
           ret
378 serge 1010
.fail:
1011
           or eax, -1
1012
           ret
168 serge 1013
endp
1014
 
378 serge 1015
; parm
1016
;  eax= mix_list
1017
 
168 serge 1018
align 4
378 serge 1019
do_mix_list:
1020
 
1021
           xor edx, edx
1022
           mov esi, str.fd-FD_OFFSET
1023
           mov ebx, [esi+STREAM.str_fd]
1024
@@:
1025
           cmp ebx, esi
1026
           je .done
1027
 
1028
           cmp [ebx+STREAM.magic], 'WAVE'
1029
           jne .next
1030
 
1031
           cmp [ebx+STREAM.size], STREAM_SIZE
1032
           jne .next
1033
 
1034
           cmp [ebx+STREAM.flags], SND_PLAY;
1035
           jne .next
1036
 
1037
           mov ecx, [ebx+STREAM.out_count]
1038
           test ecx, ecx
1039
           jnz .l1
1040
 
1041
           test [ebx+STREAM.format], PCM_RING
1042
           jnz .next
1043
           mov [ebx+STREAM.flags], SND_STOP
1044
           jmp .next
1045
.l1:
1046
           cmp ecx, 512
1047
           jae .add_buff
1048
 
1049
           mov edi, [ebx+STREAM.out_rp]
1050
           add edi, ecx
1051
           sub ecx, 512
1052
           neg ecx
1053
           push eax
1054
           xor eax, eax
1055
           cld
1056
           rep stosb
1057
           pop eax
1058
 
1059
           mov [ebx+STREAM.out_count], 512
1060
 
1061
.add_buff:
1062
           mov ecx, [ebx+STREAM.out_rp]
1063
           mov [eax],ecx
1064
           mov edi, dword [ebx+STREAM.l_amp]
1065
           mov [eax+4], edi
1066
           add [ebx+STREAM.out_rp], 512
1067
           sub [ebx+STREAM.out_count], 512
1068
 
1069
           add eax, 8
1070
           inc edx
1071
.next:
1072
           mov ebx, [ebx+STREAM.str_fd]
1073
           jmp @B
1074
.done:
1075
           mov eax, edx
1076
           ret
1077
 
1078
align 4
291 serge 1079
prepare_playlist:
168 serge 1080
 
227 serge 1081
           xor edx, edx
291 serge 1082
           mov [play_count], edx
1083
           mov esi, str.fd-FD_OFFSET
1084
           mov edi, [esi+STREAM.str_fd]
1085
@@:
1086
           cmp edi, esi
1087
           je .done
168 serge 1088
 
291 serge 1089
           cmp [edi+STREAM.magic], 'WAVE'
168 serge 1090
           jne .next
1091
 
291 serge 1092
           cmp [edi+STREAM.size], STREAM_SIZE
168 serge 1093
           jne .next
1094
 
291 serge 1095
           cmp [edi+STREAM.flags], SND_PLAY;
227 serge 1096
           jne .next
168 serge 1097
 
291 serge 1098
           mov [play_list+edx], edi
227 serge 1099
           inc [play_count]
1100
           add edx, 4
168 serge 1101
.next:
291 serge 1102
           mov edi, [edi+STREAM.str_fd]
1103
           jmp @B
1104
.done:
227 serge 1105
           ret
168 serge 1106
 
1107
align 4
1108
proc set_handler stdcall, hsrv:dword, handler_proc:dword
1109
           locals
1110
             handler    dd ?
1111
             io_code    dd ?
1112
             input      dd ?
1113
             inp_size   dd ?
1114
             output     dd ?
1115
             out_size   dd ?
1116
             val        dd ?
1117
           endl
1118
 
1119
           mov eax, [hsrv]
1120
           lea ecx, [handler_proc]
1121
           xor ebx, ebx
1122
 
1123
           mov [handler], eax
1124
           mov [io_code], DEV_CALLBACK
1125
           mov [input], ecx
1126
           mov [inp_size], 4
1127
           mov [output], ebx
1128
           mov [out_size], 0
1129
 
1130
           lea eax, [handler]
188 serge 1131
           stdcall ServiceHandler, eax
168 serge 1132
           ret
1133
endp
1134
 
1135
align 4
1136
proc dev_play stdcall, hsrv:dword
1137
           locals
1138
             handle     dd ?
1139
             io_code    dd ?
1140
             input      dd ?
1141
             inp_size   dd ?
1142
             output     dd ?
1143
             out_size   dd ?
1144
             val        dd ?
1145
           endl
1146
 
1147
           mov eax, [hsrv]
1148
           xor ebx, ebx
1149
 
1150
           mov [handle], eax
1151
           mov [io_code], DEV_PLAY
1152
           mov [input], ebx
1153
           mov [inp_size], ebx
1154
           mov [output], ebx
1155
           mov [out_size], ebx
1156
 
1157
           lea eax, [handle]
188 serge 1158
           stdcall ServiceHandler, eax
168 serge 1159
           ret
1160
endp
1161
 
378 serge 1162
if 0
1163
align 4
1164
dword2str:
1165
      mov  esi, hex_buff
1166
      mov ecx, -8
1167
@@:
1168
      rol eax, 4
1169
      mov ebx, eax
1170
      and ebx, 0x0F
1171
      mov bl, [ebx+hexletters]
1172
      mov [8+esi+ecx], bl
1173
      inc ecx
1174
      jnz @B
1175
      ret
1176
 
1177
hexletters   db '0123456789ABCDEF'
1178
hex_buff     db 8 dup(0),13,10,0
1179
 
1180
end if
1181
 
168 serge 1182
include 'mixer.asm'
293 serge 1183
include 'mix_mmx.inc'
1184
include 'mix_sse2.inc'
168 serge 1185
 
291 serge 1186
;if USE_SSE
1187
; include 'mix_sse.inc'
1188
;end if
1189
 
168 serge 1190
align 16
1191
resampler_params:
378 serge 1192
     ;r_size    r_dt   resampler_func
1193
     dd 0,0,0                                  ; 0  PCM_ALL
1194
     dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
1195
     dd 16384,      0, m16_stereo     ; 2  PCM_1_16_48
168 serge 1196
 
378 serge 1197
     dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
1198
     dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
168 serge 1199
 
378 serge 1200
     dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
1201
     dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
168 serge 1202
 
378 serge 1203
     dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
1204
     dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
168 serge 1205
 
378 serge 1206
     dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
1207
     dd  4096,  15052, resample_1     ;10  PCM_1_16_22
168 serge 1208
 
378 serge 1209
     dd  8192,  10923, resample_2     ;11  PCM_2_16_16
1210
     dd  4096,  10923, resample_1     ;12  PCM_1_16_16
168 serge 1211
 
378 serge 1212
     dd  8192,   8192, resample_2     ;13  PCM_2_16_12
1213
     dd  4096,   8192, resample_1     ;14  PCM_1_16_12
168 serge 1214
 
378 serge 1215
     dd  4096,   7527, resample_2     ;15  PCM_2_16_11
1216
     dd  2048,   7527, resample_1     ;16  PCM_1_16_11
168 serge 1217
 
378 serge 1218
     dd  4096,   5462, resample_2     ;17  PCM_2_16_8
1219
     dd  2048,   5462, resample_1     ;18  PCM_1_16_8
168 serge 1220
 
378 serge 1221
     dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
1222
     dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
168 serge 1223
 
378 serge 1224
     dd  8192,  30109, resample_28    ;21  PCM_2_8_44
1225
     dd  4096,  30109, resample_18    ;22  PCM_1_8_44
168 serge 1226
 
378 serge 1227
     dd  8192,  21846, resample_28    ;23  PCM_2_8_32
1228
     dd  4096,  21846, resample_18    ;24  PCM_1_8_32
168 serge 1229
 
378 serge 1230
     dd  8192,  16384, resample_28    ;25  PCM_2_8_24
1231
     dd  4096,  16384, resample_18    ;26  PCM_1_8_24
168 serge 1232
 
378 serge 1233
     dd  4096,  15052, resample_28    ;27  PCM_2_8_22
1234
     dd  2048,  15052, resample_18    ;28  PCM_1_8_22
168 serge 1235
 
378 serge 1236
     dd  4096,  10923, resample_28    ;29  PCM_2_8_16
1237
     dd  2048,  10923, resample_18    ;30  PCM_1_8_16
168 serge 1238
 
378 serge 1239
     dd  4096,   8192, resample_28    ;31  PCM_2_8_12
1240
     dd  2048,   8192, resample_18    ;32  PCM_1_8_12
168 serge 1241
 
378 serge 1242
     dd  2048,   7527, resample_28    ;33  PCM_2_8_11
1243
     dd  1024,   7527, resample_18    ;34  PCM_1_8_11
168 serge 1244
 
378 serge 1245
     dd  2048,   5462, resample_28    ;35  PCM_2_8_8
1246
     dd  1024,   5462, resample_18    ;36  PCM_1_8_8
168 serge 1247
 
281 serge 1248
m7            dw 0x8000,0x8000,0x8000,0x8000
1249
mm80          dq 0x8080808080808080
1250
mm_mask       dq 0xFF00FF00FF00FF00
168 serge 1251
 
378 serge 1252
vol_max       dd 0x00000000,0x00000000
1253
vol_min       dd 0x0000D8F0,0x0000D8F0
1254
pan_max       dd 0x00002710,0x00002710
1255
 
291 serge 1256
;stream_map    dd 0xFFFF       ; 16
465 serge 1257
version       dd (5 shl 16) or (SOUND_VERSION and 0xFFFF)
168 serge 1258
 
281 serge 1259
szInfinity    db 'INFINITY',0
1260
szSound       db 'SOUND',0
168 serge 1261
 
1262
if DEBUG
281 serge 1263
msgFail       db 'Sound service not loaded',13,10,0
1264
msgPlay       db 'Play buffer',13,10,0
1265
msgStop       db 'Stop',13,10,0
1266
msgUser       db 'User callback',13,10,0
1267
msgMem        db 'Not enough memory',13,10,0
291 serge 1268
msgDestroy    db 'Destroy sound buffer', 13,10,0
378 serge 1269
msgWaveout    db 'Play waveout', 13,10,0
1270
msgSetVolume  db 'Set volume',13,10,0
168 serge 1271
end if
188 serge 1272
 
1273
section '.data' data readable writable align 16
1274
 
281 serge 1275
play_list     rd 16
1276
mix_input     rd 16
1277
play_count    rd 1
1278
hSound        rd 1
378 serge 1279
eng_state     rd 1
281 serge 1280
mix_buff      rd 1
1281
mix_buff_map  rd 1
291 serge 1282
str.fd        rd 1
1283
str.bk        rd 1
188 serge 1284
 
293 serge 1285
mix_2_core    rd 1
1286
mix_3_core    rd 1
1287
mix_4_core    rd 1
291 serge 1288