kolibrios-gitea/kernel/trunk/drivers/infinity.asm
Sergey Semyonov (Serge) 82eba545cd Infinity: get streams time stamp. Low precision version.
git-svn-id: svn://kolibrios.org@1679 a494cfbc-eb01-0410-851d-a64ba20cac60
2010-10-26 15:41:23 +00:00

1371 lines
33 KiB
NASM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; Copyright (C) KolibriOS team 2006-2008. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Serge 2006-2008
; email: infinity_sound@mail.ru
format MS COFF
DEBUG equ 1
include 'proc32.inc'
include 'main.inc'
include 'imports.inc'
CURRENT_API equ 0x0101 ;1.01
COMPATIBLE_API equ 0x0100 ;1.00
API_VERSION equ (COMPATIBLE_API shl 16) or CURRENT_API
SOUND_VERSION equ CURRENT_API
FORCE_MMX equ 0 ;set to 1 to force use mmx or
FORCE_MMX_128 equ 0 ;integer sse2 extensions
;and reduce driver size
;USE_SSE equ 0
USE_SSE2_MIXER equ 0 ;floating point mixer. Disabled by default
OS_BASE equ 0x80000000
CAPS_SSE2 equ 26
PG_SW equ 0x003
public START
public service_proc
public version
RT_INP_EMPTY equ 0xFF000001
RT_OUT_EMPTY equ 0xFF000002
RT_INP_FULL equ 0xFF000003
RT_OUT_FULL equ 0xFF000004
EVENT_WATCHED equ 0x10000000
EVENT_SIGNALED equ 0x20000000
MANUAL_RESET equ 0x40000000
MANUAL_DESTROY equ 0x80000000
DEV_PLAY equ 1
DEV_STOP equ 2
DEV_CALLBACK equ 3
struc IOCTL
{ .handle dd ?
.io_code dd ?
.input dd ?
.inp_size dd ?
.output dd ?
.out_size dd ?
}
virtual at 0
IOCTL IOCTL
end virtual
section '.flat' code readable align 16
proc START stdcall, state:dword
cmp [state], 1
jne .exit
stdcall GetService, szSound
test eax, eax
jz .fail
mov [hSound], eax
stdcall KernelAlloc, 16*512
test eax, eax
jz .out_of_mem
mov [mix_buff], eax
mov eax, str.fd-FD_OFFSET
mov [str.fd], eax
mov [str.bk], eax
if FORCE_MMX
if FORCE_MMX_128
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10
stop
end if
mov [mix_2_core], mmx_mix_2
mov [mix_3_core], mmx_mix_3
mov [mix_4_core], mmx_mix_4
end if
if FORCE_MMX_128
if FORCE_MMX
display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10
stop
end if
mov [mix_2_core], mmx128_mix_2
mov [mix_3_core], mmx128_mix_3
mov [mix_4_core], mmx128_mix_4
end if
if 0
if ~(FORCE_MMX or FORCE_MMX_128) ;autodetect
mov eax, 1
cpuid
bt edx, CAPS_SSE2
jc .mmx128
;old 64-bit mmx
mov [mix_2_core], mmx_mix_2
mov [mix_3_core], mmx_mix_3
mov [mix_4_core], mmx_mix_4
jmp @F
.mmx128: ;128-bit integer sse2 extensions
mov [mix_2_core], mmx128_mix_2
mov [mix_3_core], mmx128_mix_3
mov [mix_4_core], mmx128_mix_4
@@:
end if
end if
stdcall set_handler, [hSound], new_mix
mov [eng_state], SND_STOP
stdcall RegService, szInfinity, service_proc
ret
.fail:
if DEBUG
mov esi, msgFail
call SysMsgBoardStr
end if
.exit:
xor eax, eax
ret
.out_of_mem:
if DEBUG
mov esi, msgMem
call SysMsgBoardStr
end if
xor eax, eax
ret
endp
handle equ IOCTL.handle
io_code equ IOCTL.io_code
input equ IOCTL.input
inp_size equ IOCTL.inp_size
output equ IOCTL.output
out_size equ IOCTL.out_size
align 4
srv_calls dd service_proc.srv_getversion ; 0
dd service_proc.snd_create_buff ; 1
dd service_proc.snd_destroy_buff ; 2
dd service_proc.snd_setformat ; 3
dd service_proc.snd_getformat ; 4
dd service_proc.snd_reset ; 5
dd service_proc.snd_setpos ; 6
dd service_proc.snd_getpos ; 7
dd service_proc.snd_setbuff ; 8
dd service_proc.snd_out ; 9
dd service_proc.snd_play ; 10
dd service_proc.snd_stop ; 11
dd service_proc.snd_setvolume ; 12
dd service_proc.snd_getvolume ; 13
dd service_proc.snd_setpan ; 14
dd service_proc.snd_getpan ; 15
dd service_proc.snd_getbuffsize ; 16
dd service_proc.snd_getfreespace ; 17
dd service_proc.snd_settimebase ; 18
dd service_proc.snd_gettimestamp ; 19
srv_calls_end:
proc service_proc stdcall, ioctl:dword
mov edi, [ioctl]
mov eax, [edi+io_code]
cmp eax, (srv_calls_end-srv_calls)/4
ja .fail
cmp eax, SND_CREATE_BUFF
ja @F
jmp [srv_calls+eax*4]
@@:
mov ebx, [edi+input]
mov edx, [ebx]
cmp [edx+STREAM.magic], 'WAVE'
jne .fail
cmp [edx+STREAM.size], STREAM.sizeof
jne .fail
jmp [srv_calls+eax*4]
.fail:
mov eax, -1
ret
align 4
.srv_getversion:
mov eax, [edi+output]
cmp [edi+out_size], 4
jne .fail
mov eax, [eax]
mov [eax], dword API_VERSION
xor eax, eax
ret
align 4
.snd_create_buff:
mov ebx, [edi+input]
stdcall CreateBuffer,[ebx],[ebx+4]
mov edi, [ioctl]
mov ecx, [edi+output]
mov ecx, [ecx]
mov [ecx], ebx
ret
align 4
.snd_destroy_buff:
mov eax, edx
call DestroyBuffer
ret
align 4
.snd_setformat:
stdcall SetFormat, edx,[ebx+4]
ret
align 4
.snd_getformat:
movzx eax, word [edx+STREAM.format]
mov ecx, [edi+output]
mov ecx, [ecx]
mov [ecx], eax
xor eax, eax
ret
align 4
.snd_reset:
stdcall ResetBuffer,edx,[ebx+4]
ret
align 4
.snd_setpos:
stdcall SetBufferPos,edx,[ebx+4]
ret
align 4
.snd_getpos:
stdcall GetBufferPos, edx
mov edi, [ioctl]
mov ecx, [edi+output]
mov ecx, [ecx]
mov [ecx], ebx
ret
align 4
.snd_setbuff:
mov eax, [ebx+4]
stdcall set_buffer, edx,eax,[ebx+8],[ebx+12]
ret
align 4
.snd_out:
mov eax, [ebx+4]
stdcall wave_out, edx,eax,[ebx+8]
ret
align 4
.snd_play:
stdcall play_buffer, edx,[ebx+4]
ret
align 4
.snd_stop:
stdcall stop_buffer, edx
ret
align 4
.snd_setvolume:
stdcall SetBufferVol,edx,[ebx+4],[ebx+8]
ret
align 4
.snd_getvolume:
mov eax, [edi+output]
mov ecx, [eax]
mov eax, [eax+4]
stdcall GetBufferVol,edx,ecx,eax
ret
align 4
.snd_setpan:
stdcall SetBufferPan,edx,[ebx+4]
ret
align 4
.snd_getpan:
mov eax, [edx+STREAM.pan]
mov ebx, [edi+output]
mov ebx, [ebx]
mov [ebx], eax
xor eax, eax
ret
align 4
.snd_getbuffsize:
mov eax, [edx+STREAM.in_size]
mov ecx, [edi+output]
mov ecx, [ecx]
mov [ecx], eax
xor eax, eax
ret
align 4
.snd_getfreespace:
test [edx+STREAM.format], PCM_OUT
jz .fail
mov ebx, [edx+STREAM.in_free]
mov ecx, [edi+output]
mov [ecx], ebx
xor eax, eax
ret
align 4
.snd_settimebase:
cmp [edi+inp_size], 8
jne .fail
mov edi, [edi+input]
mov eax, [edi]
mov ebx, [edi+4]
mov dword [edx+STREAM.time_base], eax
mov dword [edx+STREAM.time_base+4], ebx
xor eax, eax
ret
.snd_gettimestamp:
cmp [edi+out_size], 8
jne .fail
mov edi, [edi+output]
push 48
emms
fild qword [edx+STREAM.time_stamp]
fidiv dword [esp]
fadd qword [edx+STREAM.time_base]
fstp qword [edi]
add esp, 4
xor eax, eax
ret
endp
restore handle
restore io_code
restore input
restore inp_size
restore output
restore out_size
align 4
proc CreateBuffer stdcall, format:dword, size:dword
locals
str dd ?
ring_size dd ?
ring_pages dd ?
endl
mov eax, [format]
cmp ax, PCM_1_8_8
ja .fail
test eax, PCM_OUT
jnz .test_out
test eax, PCM_RING
jnz .test_ring
;staic
test eax, PCM_STATIC
jz .test_out ;use PCM_OUT as default format
jmp .test_ok
.test_out:
test eax, PCM_RING+PCM_STATIC
jnz .fail
or [format], PCM_OUT ;force set
jmp .test_ok
.test_ring:
test eax, PCM_OUT+PCM_STATIC
jnz .fail
.test_ok:
call GetPid
mov ebx, eax
mov eax, STREAM.sizeof
call CreateObject
test eax, eax
jz .fail
mov [str], eax
mov ebx, [format]
mov [eax+STREAM.format], ebx
xor ecx, ecx
movzx ebx, bx
cmp ebx, 19
jb @f
mov ecx, 0x80808080
@@:
mov [eax+STREAM.r_silence], ecx
shl ebx, 2
lea ebx, [ebx+ebx*2] ;ebx*=12
mov ecx, [resampler_params+ebx]
mov edx, [resampler_params+ebx+4]
mov esi, [resampler_params+ebx+8]
mov [eax+STREAM.r_size],ecx
mov [eax+STREAM.r_dt], edx
mov [eax+STREAM.resample], esi
xor ecx, ecx
mov [eax+STREAM.l_vol], ecx
mov [eax+STREAM.r_vol], ecx
mov dword [eax+STREAM.l_amp], 0x7FFF7FFF
mov [eax+STREAM.pan], ecx
test [format], PCM_STATIC
jnz .static
; ring and waveout
mov ebx, 0x10000
test [format], PCM_RING
jz .waveout
mov ebx, [eax+STREAM.r_size]
add ebx, 4095
and ebx, -4096
add ebx, ebx
.waveout:
mov [ring_size], ebx
mov eax, ebx
shr ebx, 12
mov [ring_pages], ebx
stdcall CreateRingBuffer, eax, PG_SW
mov edi, [str]
mov ecx, [ring_size]
mov [edi+STREAM.in_base], eax
mov [edi+STREAM.in_size], ecx
add eax, 128
mov [edi+STREAM.in_wp], eax
mov [edi+STREAM.in_rp], eax
mov [edi+STREAM.in_count], 0
mov [edi+STREAM.in_free], ecx
add eax, ecx
mov [edi+STREAM.in_top], eax
jmp .out_buff
.static:
mov ecx, [size]
add ecx, 128 ;resampler required
mov [eax+STREAM.in_size], ecx
stdcall KernelAlloc, ecx
mov edi, [str]
mov [edi+STREAM.in_base], eax
add eax, 128
mov [edi+STREAM.in_wp], eax
mov [edi+STREAM.in_rp], eax
mov ebx, [size]
mov [edi+STREAM.in_count], ebx
mov [edi+STREAM.in_free], ebx
add eax, ebx
mov [edi+STREAM.in_top], eax
.out_buff:
stdcall AllocKernelSpace, dword 128*1024
mov edi, [str]
xor ebx, ebx
mov [edi+STREAM.out_base], eax
mov [edi+STREAM.out_wp], eax
mov [edi+STREAM.out_rp], eax
mov [edi+STREAM.out_count], ebx
add eax, 64*1024
mov [edi+STREAM.out_top], eax
mov dword [edi+STREAM.time_base], ebx
mov dword [edi+STREAM.time_base+4], ebx
mov dword [edi+STREAM.time_stamp], ebx
mov dword [edi+STREAM.time_stamp+4], ebx
stdcall AllocPages, dword 64/4
mov edi, [str]
mov ebx, [edi+STREAM.out_base]
mov ecx, 16
or eax, PG_SW
push eax
push ebx
call CommitPages ;eax, ebx, ecx
mov ecx, 16
pop ebx
pop eax
add ebx, 64*1024
call CommitPages ;double mapped
mov edi, [str]
mov ecx, [edi+STREAM.in_top]
mov edi, [edi+STREAM.in_base]
sub ecx, edi
xor eax, eax
shr ecx, 2
cld
rep stosd
mov edi, [str]
mov edi, [edi+STREAM.out_base]
mov ecx, (64*1024)/4
rep stosd
xor esi, esi
mov ecx, MANUAL_DESTROY
call CreateEvent
mov ebx, [str]
mov [ebx+STREAM.notify_event], eax
mov [ebx+STREAM.notify_id], edx
mov [ebx+STREAM.magic], 'WAVE'
mov [ebx+STREAM.destroy], DestroyBuffer.destroy
mov [ebx+STREAM.size], STREAM.sizeof
mov [ebx+STREAM.flags], SND_STOP
pushf
cli
mov eax, str.fd-FD_OFFSET
mov edx, [eax+STREAM.str_fd]
mov [ebx+STREAM.str_fd], edx
mov [ebx+STREAM.str_bk], eax
mov [eax+STREAM.str_fd], ebx
mov [edx+STREAM.str_bk], ebx
popf
xor eax, eax
ret
.fail:
xor ebx, ebx
or eax, -1
ret
endp
;param
; eax= buffer handle
align 4
DestroyBuffer:
.handle equ esp ;local
mov [eax+STREAM.flags], SND_STOP
.destroy:
push eax
pushfd
cli
mov ebx, [eax+STREAM.str_fd]
mov ecx, [eax+STREAM.str_bk]
mov [ebx+STREAM.str_bk], ecx
mov [ecx+STREAM.str_fd], ebx
popf
stdcall KernelFree, [eax+STREAM.in_base]
mov eax, [.handle]
stdcall KernelFree, [eax+STREAM.out_base]
pop eax ;restore stack
call DestroyObject ;eax= stream
xor eax, eax
ret
.fail:
or eax, -1
ret
restore .handle
align 4
proc SetFormat stdcall, str:dword, format:dword
cmp word [format], PCM_1_8_8
ja .fail
mov edx, [str]
mov [edx+STREAM.flags], SND_STOP
test [edx+STREAM.format], PCM_RING
jnz .fail
; mov eax,[edx+STREAM.out_base]
; mov [edx+STREAM.out_wp], eax
; mov [edx+STREAM.out_rp], eax
; mov [edx+STREAM.out_count], 0
movzx eax, word [format]
mov word [edx+STREAM.format], ax
xor ebx, ebx
cmp eax, 19
jb @f
mov ebx, 0x80808080
@@:
mov [edx+STREAM.r_silence], ebx
shl eax, 2
lea eax, [eax+eax*2] ;eax*=12
mov edi, [resampler_params+eax]
mov ecx, [resampler_params+eax+4]
mov ebx, [resampler_params+eax+8]
mov [edx+STREAM.r_size],edi
mov [edx+STREAM.r_dt], ecx
mov [edx+STREAM.resample], ebx
mov edi, [edx+STREAM.in_base]
mov ecx, 128/4
mov eax, [edx+STREAM.r_silence]
cld
rep stosd
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
; for static buffers only
; use waveout for streams
align 4
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
mov edx, [str]
test [edx+STREAM.format], PCM_OUT
jnz .fail
mov esi, [src]
mov edi, [offs]
add edi, [edx+STREAM.in_base]
add edi, 128
cmp edi, [edx+STREAM.in_top]
jae .fail
mov ecx, [size]
lea ebx, [ecx+edi]
sub ebx, [edx+STREAM.in_top]
jb @F
sub ecx, ebx
@@:
shr ecx, 2
cld
rep movsd
xor eax,eax
ret
.fail:
or eax, -1
ret
endp
; for stream buffers only
align 4
proc wave_out stdcall, str:dword,src:dword,size:dword
locals
state_saved dd ?
fpu_state rb 528
endl
mov edx, [str]
mov eax, [edx+STREAM.format]
test eax, PCM_OUT
jz .fail
cmp ax, PCM_ALL
je .fail
mov esi,[src]
test esi, esi
jz .fail
cmp esi, OS_BASE
jae .fail
mov [state_saved], 0
.main_loop:
mov edx, [str]
mov ebx, [size]
test ebx, ebx
jz .done
cmp [edx+STREAM.flags], SND_STOP
jne .fill
mov edi, [edx+STREAM.in_base]
mov ecx, 128/4
mov eax, [edx+STREAM.r_silence]
cld
rep stosd
mov ecx, [edx+STREAM.in_size]
sub ecx, 128
mov [edx+STREAM.in_wp], edi
mov [edx+STREAM.in_rp], edi
mov [edx+STREAM.in_count], 0
mov [edx+STREAM.in_free], ecx
mov eax,[edx+STREAM.out_base]
mov [edx+STREAM.out_wp], eax
mov [edx+STREAM.out_rp], eax
mov [edx+STREAM.out_count], 0
.fill:
cli
mov ecx, [edx+STREAM.in_free]
test ecx, ecx
jz .wait
cmp ecx, ebx
jbe @F
mov ecx, ebx
@@:
sub [size], ecx
add [edx+STREAM.in_count], ecx
sub [edx+STREAM.in_free], ecx
shr ecx, 2
mov edi, [edx+STREAM.in_wp]
mov esi, [src]
cld
rep movsd
mov [src], esi
cmp edi, [edx+STREAM.in_top]
jb @F
sub edi, [edx+STREAM.in_size]
@@:
mov [edx+STREAM.in_wp], edi
cmp [edx+STREAM.out_count], 32768
jae .skip
cmp [state_saved], 0
jne @F
lea eax, [fpu_state+15]
and eax, -16
call FpuSave
mov [state_saved], 1
@@:
stdcall refill, edx
.skip:
sti
mov edx, [str]
mov [edx+STREAM.flags], SND_PLAY
cmp [eng_state], SND_PLAY
je .main_loop
stdcall dev_play, [hSound]
mov [eng_state], SND_PLAY
jmp .main_loop
.wait:
sti
mov edx, [str]
mov eax, [edx+STREAM.notify_event]
mov ebx, [edx+STREAM.notify_id]
call WaitEvent ;eax ebx
jmp .main_loop
.done:
cmp [state_saved], 1
jne @F
lea eax, [fpu_state+15]
and eax, -16
call FpuRestore
@@:
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
; both static and stream
; reset all but not clear buffers
; flags reserved
; RESET_INPUT equ 1 ;reserved reset and clear input buffer
; RESET_OUTPUT equ 2 ;reserved reset and clear output buffer
; RESET_ALL equ 3
align 4
proc ResetBuffer stdcall, str:dword, flags:dword
mov edx, [str]
mov [edx+STREAM.flags], SND_STOP
mov edi, [edx+STREAM.in_base]
mov ecx, 128/4
mov eax, [edx+STREAM.r_silence]
cld
rep stosd
mov [edx+STREAM.in_wp], edi
mov [edx+STREAM.in_rp], edi
test [edx+STREAM.flags], PCM_STATIC
jnz .static
mov [edx+STREAM.in_count], 0
jmp @F
.static:
mov eax, [edx+STREAM.in_size]
mov [edx+STREAM.in_count], eax
@@:
mov eax, [edx+STREAM.in_size]
sub eax, 128
mov [edx+STREAM.in_free], eax
xor eax, eax
mov ebx,[edx+STREAM.out_base]
mov [edx+STREAM.out_wp], ebx
mov [edx+STREAM.out_rp], ebx
mov [edx+STREAM.out_count], eax
ret
.fail:
or eax, -1
ret
endp
; for static buffers only
align 4
proc SetBufferPos stdcall, str:dword, pos:dword
mov edx, [str]
test [edx+STREAM.format], PCM_STATIC
jz .fail
mov [edx+STREAM.flags], SND_STOP
mov eax, [pos]
add eax, [edx+STREAM.in_base]
mov ebx, [edx+STREAM.in_top]
add eax, 128
cmp eax, ebx
jae .fail
mov [edx+STREAM.in_rp], eax
sub ebx, eax
mov [edx+STREAM.in_count], ebx
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
align 4
proc GetBufferPos stdcall, str:dword
mov edx, [str]
test [edx+STREAM.format], PCM_STATIC
jz .fail
mov ebx, [edx+STREAM.in_rp]
sub ebx, [edx+STREAM.in_base]
sub ebx, 128
xor eax, eax
ret
.fail:
xor ebx,ebx
or eax, -1
ret
endp
; both
align 4
proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
mov edx, [str]
stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
ret
endp
proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
locals
_600 dd ?
_32767 dd ?
state rb 108
endl
mov [_600], 0x44160000 ;600.0
mov [_32767], 32767
lea ebx, [state]
fnsave [ebx]
movq mm0, qword [l_vol]
pminsw mm0, qword [vol_max]
pmaxsw mm0, qword [vol_min]
movq qword [l_vol], mm0
movq qword [edx+STREAM.l_vol], mm0
movd mm1,[pan]
pminsw mm1, qword [pan_max]
pmaxsw mm1, qword [vol_min]
movd [edx+STREAM.pan], mm1
cmp word [edx+STREAM.pan], 0
jl @F
psubsw mm0,mm1
pminsw mm0, qword [vol_max]
pmaxsw mm0, qword [vol_min]
movd [l_vol],mm0
jmp .calc_amp
@@:
punpckhdq mm0,mm0
paddsw mm0,mm1
pminsw mm0, qword [vol_max]
pmaxsw mm0, qword [vol_min]
movd [r_vol], mm0
.calc_amp:
emms
fild word [l_vol]
call .calc
fistp word [edx+STREAM.l_amp]
fstp dword [edx+STREAM.l_amp_f]
fstp st0
fild word [r_vol]
call .calc
fistp word [edx+STREAM.r_amp]
fstp dword [edx+STREAM.r_amp_f]
fstp st0
fnclex
lea ebx, [state]
frstor [ebx]
xor eax, eax
inc eax
ret
.calc:
fdiv dword [_600]
fld st0
frndint
fxch st1
fsub st, st1
f2xm1
fld1
faddp st1, st0
fscale
fld st0
fimul dword [_32767]
ret 0
endp
align 4
proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
mov edx, [str]
mov eax, [p_lvol]
movsx ecx, word [edx+STREAM.l_vol]
mov [eax], ecx
mov eax, [p_rvol]
movsx ecx, word [edx+STREAM.r_vol]
mov [eax], ecx
xor eax, eax
ret
endp
align 4
proc SetBufferPan stdcall, str:dword,pan:dword
mov edx, [str]
stdcall set_vol_param,[edx+STREAM.l_vol],\
[edx+STREAM.r_vol],[pan]
ret
endp
; for static and ring buffers only
align 4
proc play_buffer stdcall, str:dword, flags:dword
mov ebx, [str]
mov eax, [ebx+STREAM.format]
test eax, PCM_OUT
jnz .fail
cmp ax, PCM_ALL
je .fail
mov [ebx+STREAM.flags], SND_PLAY
cmp [eng_state], SND_PLAY
je .done
stdcall dev_play, [hSound]
mov [eng_state], SND_PLAY
.done:
test [flags], PLAY_SYNC
jz @F
mov edx, [str]
.wait:
mov eax, [edx+STREAM.notify_event]
mov ebx, [edx+STREAM.notify_id]
call WaitEvent ;eax ebx
mov edx, [str]
cmp [edx+STREAM.flags], SND_STOP
jne .wait
@@:
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
; for static and ring buffers only
align 4
proc stop_buffer stdcall, str:dword
mov edx, [str]
test [edx+STREAM.format], PCM_STATIC+PCM_RING
jz .fail
mov [edx+STREAM.flags], SND_STOP
; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
mov eax, [edx+STREAM.notify_event]
mov ebx, [edx+STREAM.notify_id]
call ClearEvent ;eax ebx
xor eax, eax
ret
.fail:
or eax, -1
ret
endp
; param
; eax= mix_list
align 4
do_mix_list:
xor edx, edx
mov esi, str.fd-FD_OFFSET
mov ebx, [esi+STREAM.str_fd]
@@:
cmp ebx, esi
je .done
cmp [ebx+STREAM.magic], 'WAVE'
jne .next
cmp [ebx+STREAM.size], STREAM.sizeof
jne .next
cmp [ebx+STREAM.flags], SND_PLAY;
jne .next
mov ecx, [ebx+STREAM.out_count]
test ecx, ecx
jnz .l1
test [ebx+STREAM.format], PCM_RING
jnz .next
mov [ebx+STREAM.flags], SND_STOP
jmp .next
.l1:
cmp ecx, 512
jae .add_buff
mov edi, [ebx+STREAM.out_rp]
add edi, ecx
sub ecx, 512
neg ecx
push eax
xor eax, eax
cld
rep stosb
pop eax
mov [ebx+STREAM.out_count], 512
.add_buff:
mov ecx, [ebx+STREAM.out_rp]
mov [eax],ecx
if USE_SSE2_MIXER
mov edi, dword [ebx+STREAM.l_amp_f]
mov [eax+4], edi
mov edi, dword [ebx+STREAM.r_amp_f]
mov [eax+8], edi
else
mov edi, dword [ebx+STREAM.l_amp]
mov [eax+4], edi
end if
add [ebx+STREAM.out_rp], 512
sub [ebx+STREAM.out_count], 512
add eax, 12
inc edx
.next:
mov ebx, [ebx+STREAM.str_fd]
jmp @B
.done:
mov eax, edx
ret
align 4
prepare_playlist:
xor edx, edx
mov [play_count], edx
mov esi, str.fd-FD_OFFSET
mov edi, [esi+STREAM.str_fd]
@@:
cmp edi, esi
je .done
cmp [edi+STREAM.magic], 'WAVE'
jne .next
cmp [edi+STREAM.size], STREAM.sizeof
jne .next
cmp [edi+STREAM.flags], SND_PLAY;
jne .next
mov [play_list+edx], edi
inc [play_count]
add edx, 4
.next:
mov edi, [edi+STREAM.str_fd]
jmp @B
.done:
ret
align 4
proc set_handler stdcall, hsrv:dword, handler_proc:dword
locals
handler dd ?
io_code dd ?
input dd ?
inp_size dd ?
output dd ?
out_size dd ?
val dd ?
endl
mov eax, [hsrv]
lea ecx, [handler_proc]
xor ebx, ebx
mov [handler], eax
mov [io_code], DEV_CALLBACK
mov [input], ecx
mov [inp_size], 4
mov [output], ebx
mov [out_size], 0
lea eax, [handler]
stdcall ServiceHandler, eax
ret
endp
align 4
proc dev_play stdcall, hsrv:dword
locals
handle dd ?
io_code dd ?
input dd ?
inp_size dd ?
output dd ?
out_size dd ?
val dd ?
endl
mov eax, [hsrv]
xor ebx, ebx
mov [handle], eax
mov [io_code], DEV_PLAY
mov [input], ebx
mov [inp_size], ebx
mov [output], ebx
mov [out_size], ebx
lea eax, [handle]
stdcall ServiceHandler, eax
ret
endp
if 0
align 4
dword2str:
mov esi, hex_buff
mov ecx, -8
@@:
rol eax, 4
mov ebx, eax
and ebx, 0x0F
mov bl, [ebx+hexletters]
mov [8+esi+ecx], bl
inc ecx
jnz @B
ret
hexletters db '0123456789ABCDEF'
hex_buff db 8 dup(0),13,10,0
end if
include 'mixer.asm'
include 'mix_mmx.inc'
include 'mix_sse2.inc'
;if USE_SSE
; include 'mix_sse.inc'
;end if
align 16
resampler_params:
;r_size r_dt resampler_func
dd 0,0,0 ; 0 PCM_ALL
dd 16384, 0, copy_stream ; 1 PCM_2_16_48
dd 8192, 0, m16_stereo ; 2 PCM_1_16_48
dd 16384, 30109, resample_2 ; 3 PCM_2_16_44
dd 8192, 30109, resample_1 ; 4 PCM_1_16_44
dd 16384, 21846, resample_2 ; 5 PCM_2_16_32
dd 8192, 21846, resample_1 ; 6 PCM_1_16_32
dd 16384, 16384, resample_2 ; 7 PCM_2_16_24
dd 8192, 16384, resample_1 ; 8 PCM_1_16_24
dd 8192, 15052, resample_2 ; 9 PCM_2_16_22
dd 4096, 15052, resample_1 ;10 PCM_1_16_22
dd 8192, 10923, resample_2 ;11 PCM_2_16_16
dd 4096, 10923, resample_1 ;12 PCM_1_16_16
dd 8192, 8192, resample_2 ;13 PCM_2_16_12
dd 4096, 8192, resample_1 ;14 PCM_1_16_12
dd 4096, 7527, resample_2 ;15 PCM_2_16_11
dd 2048, 7527, resample_1 ;16 PCM_1_16_11
dd 4096, 5462, resample_2 ;17 PCM_2_16_8
dd 2048, 5462, resample_1 ;18 PCM_1_16_8
dd 16384, 0, s8_stereo ;19 PCM_2_8_48
dd 8192, 0, m8_stereo ;20 PCM_1_8_48
dd 8192, 30109, resample_28 ;21 PCM_2_8_44
dd 4096, 30109, resample_18 ;22 PCM_1_8_44
dd 8192, 21846, resample_28 ;23 PCM_2_8_32
dd 4096, 21846, resample_18 ;24 PCM_1_8_32
dd 8192, 16384, resample_28 ;25 PCM_2_8_24
dd 4096, 16384, resample_18 ;26 PCM_1_8_24
dd 4096, 15052, resample_28 ;27 PCM_2_8_22
dd 2048, 15052, resample_18 ;28 PCM_1_8_22
dd 4096, 10923, resample_28 ;29 PCM_2_8_16
dd 2048, 10923, resample_18 ;30 PCM_1_8_16
dd 4096, 8192, resample_28 ;31 PCM_2_8_12
dd 2048, 8192, resample_18 ;32 PCM_1_8_12
dd 2048, 7527, resample_28 ;33 PCM_2_8_11
dd 1024, 7527, resample_18 ;34 PCM_1_8_11
dd 2048, 5462, resample_28 ;35 PCM_2_8_8
dd 1024, 5462, resample_18 ;36 PCM_1_8_8
m7 dw 0x8000,0x8000,0x8000,0x8000
mm80 dq 0x8080808080808080
mm_mask dq 0xFF00FF00FF00FF00
vol_max dd 0x00000000,0x00000000
vol_min dd 0x0000D8F0,0x0000D8F0
pan_max dd 0x00002710,0x00002710
;stream_map dd 0xFFFF ; 16
version dd (5 shl 16) or SOUND_VERSION
szInfinity db 'INFINITY',0
szSound db 'SOUND',0
if DEBUG
msgFail db 'Sound service not loaded',13,10,0
msgPlay db 'Play buffer',13,10,0
msgStop db 'Stop',13,10,0
msgUser db 'User callback',13,10,0
msgMem db 'Not enough memory',13,10,0
msgDestroy db 'Destroy sound buffer', 13,10,0
msgWaveout db 'Play waveout', 13,10,0
msgSetVolume db 'Set volume',13,10,0
end if
section '.data' data readable writable align 16
play_list rd 16
mix_input rd 16
play_count rd 1
hSound rd 1
eng_state rd 1
mix_buff rd 1
mix_buff_map rd 1
str.fd rd 1
str.bk rd 1
mix_2_core rd 1
mix_3_core rd 1
mix_4_core rd 1