Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 377 → Rev 378

/kernel/trunk/drivers/infinity.asm
26,26 → 26,28
 
DEBUG equ 1
 
EVENT_NOTIFY equ 0x00000200
 
OS_BASE equ 0
new_app_base equ 0x60400000
new_app_base equ 0x80000000
PROC_BASE equ OS_BASE+0x0080000
 
CAPS_SSE2 equ 26
PG_SW equ 0x003
 
 
public START
public service_proc
public version
 
SND_CREATE_BUFF equ 2
SND_PLAY equ 3
SND_STOP equ 4
SND_SETBUFF equ 5
SND_DESTROY_BUFF equ 6
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
104,6 → 106,8
mov [mix_4_core], mmx128_mix_4
end if
 
if 0
 
if ~(FORCE_MMX or FORCE_MMX_128) ;autodetect
mov eax, 1
cpuid
120,7 → 124,10
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:
154,50 → 161,144
mov edi, [ioctl]
mov eax, [edi+io_code]
 
cmp eax, SRV_GETVERSION
jne @F
mov eax, [edi+output]
mov eax, [eax]
mov [eax+new_app_base], dword SOUND_VERSION
xor eax, eax
ret
@@:
cmp eax, SND_CREATE_BUFF
jne @F
mov ebx, [edi+input]
stdcall CreateBuffer,[ebx]
push edi
stdcall CreateBuffer,[ebx],[ebx+4]
pop edi
mov ecx, [edi+output]
mov ecx, [ecx]
mov [ecx+new_app_base], ebx
ret
@@:
cmp eax, SND_PLAY
mov ebx, [edi+input]
mov edx, [ebx]
 
cmp [edx+STREAM.magic], 'WAVE'
jne .fail
 
cmp [edx+STREAM.size], STREAM_SIZE
jne .fail
 
cmp eax, SND_DESTROY_BUFF
jne @F
 
mov ebx, [edi+input]
stdcall play_buffer, [ebx]
mov eax, edx
call DestroyBuffer ;edx= stream
ret
@@:
cmp eax, SND_STOP
cmp eax, SND_SETFORMAT
jne @F
stdcall SetFormat,[ebx],[ebx+4]
ret
@@:
cmp eax, SND_GETFORMAT
jne @F
 
; if DEBUG
; mov esi, msgStop
; call [SysMsgBoardStr]
; end if
 
mov ebx, [edi+input]
stdcall stop_buffer, [ebx]
movzx eax, word [edx+STREAM.format]
mov ecx, [edi+output]
mov ecx, [ecx]
mov [ecx+new_app_base], eax
xor eax, eax
ret
@@:
cmp eax, SND_RESET
jne @F
stdcall ResetBuffer,[ebx],[ebx+4]
ret
@@:
cmp eax, SND_SETPOS
jne @F
stdcall SetBufferPos,[ebx],[ebx+4]
ret
@@:
cmp eax, SND_GETPOS
jne @F
push edi
stdcall GetBufferPos, [ebx]
pop edi
mov ecx, [edi+output]
mov ecx, [ecx]
mov [ecx+new_app_base], ebx
ret
@@:
cmp eax, SND_SETBUFF
jne @F
 
mov ebx, [edi+input]
mov eax, [ebx+4]
add eax, new_app_base
stdcall set_buffer, [ebx],eax,[ebx+8],[ebx+12]
ret
@@:
cmp eax, SND_DESTROY_BUFF
cmp eax, SND_SETVOLUME
jne @F
stdcall SetBufferVol,[ebx],[ebx+4],[ebx+8]
ret
@@:
cmp eax, SND_GETVOLUME
jne @F
 
mov eax, [edi+input]
mov eax, [eax]
call DestroyBuffer ;eax
mov eax, [edi+output]
mov ecx, [eax]
mov eax, [eax+4]
add ecx, new_app_base
add eax, new_app_base
stdcall GetBufferVol,[ebx],ecx,eax
ret
@@:
cmp eax, SND_SETPAN
jne @F
stdcall SetBufferPan,[ebx],[ebx+4]
ret
@@:
cmp eax, SND_GETPAN
jne @F
mov eax, [edx+STREAM.pan]
mov ebx, [edi+output]
mov ebx, [ebx]
mov [ebx+new_app_base], eax
xor eax, eax
ret
@@:
cmp eax, SND_OUT
jne @F
 
mov eax, [ebx+4]
add eax, new_app_base
stdcall wave_out, [ebx],eax,[ebx+8]
ret
@@:
cmp eax, SND_PLAY
jne @F
 
stdcall play_buffer, [ebx],[ebx+4]
ret
@@:
cmp eax, SND_STOP
jne @F
 
stdcall stop_buffer, [ebx]
ret
@@:
cmp eax, SND_GETBUFFSIZE
jne @F
mov eax, [edx+STREAM.in_size]
mov ecx, [edi+output]
mov ecx, [ecx]
mov [ecx+new_app_base], eax
xor eax, eax
ret
@@:
.fail:
or eax, -1
ret
endp
 
restore handle
210,12 → 311,35
TASK_COUNT equ 0x0003004
CURRENT_TASK equ 0x0003000
 
 
align 4
proc CreateBuffer stdcall, format:dword
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_OUT+PCM_RING
jnz .fail
jmp .test_ok
.test_out:
test eax, PCM_RING+PCM_STATIC
jnz .fail
jmp .test_ok
.test_ring:
test eax, PCM_OUT+PCM_STATIC
jnz .fail
.test_ok:
mov ebx, [CURRENT_TASK] ;hack: direct accsess
shl ebx, 5 ;to kernel data
mov ebx, [0x3000+ebx+4]
226,52 → 350,116
jz .fail
mov [str], eax
 
mov [eax+STREAM.magic], 'WAVE'
mov [eax+STREAM.destroy], DestroyBuffer.destroy
mov [eax+STREAM.size], STREAM_SIZE
mov ebx, [format]
mov [eax+STREAM.format], ebx
 
pushf
cli
mov ebx, str.fd-FD_OFFSET
mov edx, [ebx+STREAM.str_fd]
mov [eax+STREAM.str_fd], edx
mov [eax+STREAM.str_bk], ebx
mov [ebx+STREAM.str_fd], eax
mov [edx+STREAM.str_bk], eax
popf
xor ecx, ecx
movzx ebx, bx
cmp ebx, 19
jb @f
mov ecx, 0x80808080
@@:
mov [eax+STREAM.r_silence], ecx
 
stdcall KernelAlloc, dword 72*1024
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 eax, 0x10000
test [format], PCM_RING
jz .waveout
 
mov eax, [eax+STREAM.r_size]
add eax, 4095
and eax, -4096
add eax, eax
.waveout:
mov [ring_size], eax
mov ebx, eax
shr ebx, 12
mov [ring_pages], ebx
 
add eax, eax ;double ring size
stdcall AllocKernelSpace, eax
 
mov edi, [str]
mov [edi+STREAM.base], eax
add eax, 0x1000
mov [edi+STREAM.seg_0], eax
mov [edi+STREAM.curr_seg], eax
mov [edi+STREAM.notify_off1], eax
add eax, 0x8000
mov [edi+STREAM.lim_0], eax
add eax, 0x1000
mov [edi+STREAM.seg_1], eax
mov [edi+STREAM.notify_off2], eax
add eax, 0x8000
mov [edi+STREAM.limit], eax
mov [edi+STREAM.lim_1], eax
mov ecx, [ring_size]
mov [edi+STREAM.in_base], eax
mov [edi+STREAM.in_size], ecx
add eax, 128
sub ecx, 128
mov [edi+STREAM.in_wp], eax
mov [edi+STREAM.in_rp], eax
mov [edi+STREAM.in_count], 0
 
; create ring buffer
mov [edi+STREAM.in_free], ecx
add eax, ecx
mov [edi+STREAM.in_top], eax
 
mov ebx, [ring_pages]
stdcall AllocPages, ebx
mov edi, [str]
mov ebx, [edi+STREAM.in_base]
mov ecx, [ring_pages]
or eax, PG_SW
push eax
push ebx
call CommitPages ;eax, ebx, ecx
mov ecx, [ring_pages]
pop ebx
pop eax
add ebx, [ring_size]
call CommitPages ;double mapped
 
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]
mov [edi+STREAM.work_buff], eax
mov [edi+STREAM.work_read], eax
mov [edi+STREAM.work_write], eax
mov [edi+STREAM.work_count], 0
mov [edi+STREAM.out_base], eax
mov [edi+STREAM.out_wp], eax
mov [edi+STREAM.out_rp], eax
mov [edi+STREAM.out_count], 0
add eax, 64*1024
mov [edi+STREAM.work_top], eax
mov [edi+STREAM.out_top], eax
 
stdcall AllocPages, dword 64/4
mov edi, [str]
mov ebx, [edi+STREAM.work_buff]
mov ebx, [edi+STREAM.out_base]
mov ecx, 16
or eax, PG_SW
push eax
284,89 → 472,50
call CommitPages ;double mapped
 
mov edi, [str]
mov eax, [format]
mov [edi+STREAM.format], eax
mov [edi+STREAM.flags], SND_STOP
 
xor ebx, ebx
cmp eax, 19
jb @f
mov ebx, 0x80808080
@@:
mov [edi+STREAM.r_silence], ebx
 
shl eax, 4
mov ebx, [resampler_params+eax]
mov ecx, [resampler_params+eax+4]
mov edx, [resampler_params+eax+8]
 
mov [edi+STREAM.r_size],ebx
mov [edi+STREAM.r_end], ecx
mov [edi+STREAM.r_dt], edx
 
mov ebx, [resampler_params+eax+12]
mov [edi+STREAM.resample], ebx
 
mov edx, [edi+STREAM.base]
lea eax, [edx+0x9000]
call GetPgAddr ;eax
call FreePage ;eax
 
mov eax, edx
lea ebx, [edx+0x9000]
call GetPgAddr ;eax
stdcall MapPage, ebx, eax, dword 3
 
mov edi, [edi+STREAM.base]
mov ecx, (72*1024)/4
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.work_buff]
mov edi, [edi+STREAM.out_base]
mov ecx, (64*1024)/4
rep stosd
 
mov eax, [str]
ret
.fail:
xor eax, eax
ret
endp
xor edx, edx
mov ebx, MANUAL_DESTROY
call CreateEvent
 
if 0
align 4
pid_to_slot:
mov ebx, [str]
mov [ebx+STREAM.notify_event], eax
mov [ebx+STREAM.notify_id], edx
 
push ebx
push ecx
mov ebx,[TASK_COUNT]
shl ebx,5
mov ecx,2*32
.loop:
cmp byte [CURRENT_TASK+ecx+0xa],9
jz .endloop ;skip empty slots
cmp [CURRENT_TASK+ecx+0x4],eax ;check PID
jz .pid_found
.endloop:
add ecx,32
cmp ecx,ebx
jle .loop
pop ecx
pop ebx
mov [ebx+STREAM.magic], 'WAVE'
mov [ebx+STREAM.destroy], DestroyBuffer.destroy
mov [ebx+STREAM.size], STREAM_SIZE
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
 
.pid_found:
shr ecx,5
mov eax,ecx
pop ecx
pop ebx
.fail:
xor ebx, ebx
or eax, -1
ret
endp
 
end if
 
;param
; eax= buffer handle
 
374,15 → 523,11
DestroyBuffer:
.handle equ esp ;local
 
cmp [eax+STREAM.magic], 'WAVE'
jne .fail
 
cmp [eax+STREAM.size], STREAM_SIZE
jne .fail
mov [eax+STREAM.flags], SND_STOP
.destroy:
push eax
 
pushf
pushfd
cli
mov ebx, [eax+STREAM.str_fd]
mov ecx, [eax+STREAM.str_bk]
390,115 → 535,120
mov [ecx+STREAM.str_fd], ebx
popf
 
stdcall KernelFree, [eax+STREAM.base]
stdcall KernelFree, [eax+STREAM.in_base]
mov eax, [.handle]
stdcall KernelFree, [eax+STREAM.work_buff]
stdcall KernelFree, [eax+STREAM.out_base]
 
pop eax ;restore stack
call DestroyObject ;eax
call DestroyObject ;eax= stream
xor eax, eax
ret
.fail:
or eax, -1
ret
restore .handle
 
align 4
proc play_buffer stdcall, str:dword
proc SetFormat stdcall, str:dword, format:dword
 
mov ebx, [str]
cmp [ebx+STREAM.magic], 'WAVE'
jne .fail
cmp word [format], PCM_1_8_8
ja .fail
 
cmp [ebx+STREAM.size], STREAM_SIZE
jne .fail
mov edx, [str]
mov [edx+STREAM.flags], SND_STOP
 
mov edi,[ebx+STREAM.work_buff]
mov [ebx+STREAM.work_read], edi
mov [ebx+STREAM.work_write], edi
mov [ebx+STREAM.work_count], 0
test [edx+STREAM.format], PCM_RING
jnz .fail
 
mov edx, [ebx+STREAM.base]
add edx, 0x1000
mov [ebx+STREAM.seg_0], edx
mov [ebx+STREAM.curr_seg], edx
add edx, 0x8000
mov [ebx+STREAM.lim_0], edx
add edx, 0x1000
mov [ebx+STREAM.seg_1], edx
add edx, 0x8000
mov [ebx+STREAM.lim_1], edx
; mov eax,[edx+STREAM.out_base]
; mov [edx+STREAM.out_wp], eax
; mov [edx+STREAM.out_rp], eax
; mov [edx+STREAM.out_count], 0
 
mov edx, [ebx+STREAM.seg_0]
mov ecx, -128
mov eax, [ebx+STREAM.r_silence]
movzx eax, word [format]
mov word [edx+STREAM.format], ax
 
xor ebx, ebx
cmp eax, 19
jb @f
mov ebx, 0x80808080
@@:
mov [edx+ecx], eax
add ecx, 4
jnz @B
mov [edx+STREAM.r_silence], ebx
 
stdcall [ebx+STREAM.resample], edi, edx,\
[ebx+STREAM.r_dt],[ebx+STREAM.r_size],[ebx+STREAM.r_end]
shl eax, 2
lea eax, [eax+eax*2] ;eax*=12
 
mov ebx, [str]
mov edi, [resampler_params+eax]
mov ecx, [resampler_params+eax+4]
mov ebx, [resampler_params+eax+8]
 
add [ebx+STREAM.work_count], eax
add [ebx+STREAM.work_write], eax
mov [edx+STREAM.r_size],edi
mov [edx+STREAM.r_dt], ecx
mov [edx+STREAM.resample], ebx
 
mov edx, [ebx+STREAM.r_size]
add [ebx+STREAM.curr_seg], edx
 
mov [ebx+STREAM.flags], SND_PLAY
 
mov eax, [ebx+STREAM.r_silence]
mov edi, [ebx+STREAM.work_write]
mov ecx, [ebx+STREAM.work_top]
sub ecx, edi
shr ecx, 2
mov edi, [edx+STREAM.in_base]
mov ecx, 128/4
mov eax, [edx+STREAM.r_silence]
cld
rep stosd
 
stdcall dev_play, [hSound]
xor eax, eax
inc eax
ret
.fail:
xor eax, eax
or eax, -1
ret
endp
 
; for static buffers only
; use waveout for streams
 
align 4
proc stop_buffer stdcall, str:dword
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
 
mov edi, [str]
mov edx, [str]
test [edx+STREAM.format], PCM_OUT
jnz .fail
 
cmp [edi+STREAM.magic], 'WAVE'
jne .fail
mov esi, [src]
mov edi, [offs]
add edi, [edx+STREAM.in_base]
add edi, 128
 
cmp [edi+STREAM.size], STREAM_SIZE
jne .fail
cmp edi, [edx+STREAM.in_top]
jae .fail
 
mov [edi+STREAM.flags], SND_STOP
 
; stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
 
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
inc eax
ret
.fail:
xor eax, eax
or eax, -1
ret
endp
 
; for stream buffers only
 
align 4
proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
proc wave_out stdcall, str:dword,src:dword,size:dword
locals
state_saved dd ?
fpu_state rb 528
endl
 
mov edx, [str]
test edx, edx
jz .fail
mov eax, [edx+STREAM.format]
test eax, PCM_STATIC+PCM_RING
jnz .fail
 
cmp [edx+STREAM.magic], 'WAVE'
jne .fail
cmp ax, PCM_ALL
je .fail
 
cmp [edx+STREAM.size], STREAM_SIZE
jne .fail
 
mov esi,[src]
test esi, esi
jz .fail
506,44 → 656,429
cmp esi, new_app_base
jb .fail
 
mov edi, [offs]
mov ecx, 0x8000
mov [state_saved], 0
 
sub ecx, edi
jbe .seg_1
.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:
mov ecx, [edx+STREAM.in_free]
test ecx, ecx
jz .wait
 
cmp ecx, ebx
jbe @F
 
mov ecx, ebx
@@:
sub [size], ecx
jb .fail
add [edx+STREAM.in_count], ecx
sub [edx+STREAM.in_free], ecx
 
add edi, [edx+STREAM.base]
add edi, 0x1000
shr ecx, 2
mov edi, [edx+STREAM.in_wp]
mov esi, [src]
cld
rep movsd
jmp @F
.seg_1:
add edi, [edx+STREAM.base]
add edi, 0x1000
 
mov [src], esi
cmp edi, [edx+STREAM.in_top]
jb @F
sub edi, [edx+STREAM.in_size]
@@:
add edi, 0x1000
mov ecx, [size]
test ecx, ecx
jz .done
cmp ecx, 0x8000
ja .fail
mov [edx+STREAM.in_wp], edi
 
shr ecx, 2
rep movsd
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:
mov ebx, [str]
mov [ebx+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:
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
 
mov [edx+STREAM.in_count], 0
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_OUT+PCM_RING
jnz .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_OUT+PCM_RING
jnz .fail
 
mov ebx, [edx+STREAM.in_rp]
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 st0
 
fild word [r_vol]
 
call .calc
 
fistp word [edx+STREAM.r_amp]
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
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
locals
fpu_state rb 528
endl
 
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 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
 
; parm
; 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_SIZE
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
mov edi, dword [ebx+STREAM.l_amp]
mov [eax+4], edi
add [ebx+STREAM.out_rp], 512
sub [ebx+STREAM.out_count], 512
 
add eax, 8
inc edx
.next:
mov ebx, [ebx+STREAM.str_fd]
jmp @B
.done:
mov eax, edx
ret
 
align 4
prepare_playlist:
 
xor edx, edx
562,8 → 1097,6
 
cmp [edi+STREAM.flags], SND_PLAY;
jne .next
cmp [edi+STREAM.work_count], 16384
jb .next
 
mov [play_list+edx], edi
inc [play_count]
629,6 → 1162,26
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'
639,68 → 1192,72
 
align 16
resampler_params:
;r_size r_end r_dt resampler_func
dd 0,0,0,0 ; 0 PCM_ALL
dd 16384, 0, 0, copy_stream ; 1 PCM_2_16_48
dd 16384, 0, 0, m16_stereo ; 2 PCM_1_16_48
;r_size r_dt resampler_func
dd 0,0,0 ; 0 PCM_ALL
dd 16384, 0, copy_stream ; 1 PCM_2_16_48
dd 16384, 0, m16_stereo ; 2 PCM_1_16_48
 
dd 16384, 0x08000000, 30109, resample_2 ; 3 PCM_2_16_44
dd 8192, 0x08000000, 30109, resample_1 ; 4 PCM_1_16_44
dd 16384, 30109, resample_2 ; 3 PCM_2_16_44
dd 8192, 30109, resample_1 ; 4 PCM_1_16_44
 
dd 16384, 0x08000000, 21846, resample_2 ; 5 PCM_2_16_32
dd 8192, 0x08000000, 21846, resample_1 ; 6 PCM_1_16_32
dd 16384, 21846, resample_2 ; 5 PCM_2_16_32
dd 8192, 21846, resample_1 ; 6 PCM_1_16_32
 
dd 16384, 0x08000000, 16384, resample_2 ; 7 PCM_2_16_24
dd 8192, 0x08000000, 16384, resample_1 ; 8 PCM_1_16_24
dd 16384, 16384, resample_2 ; 7 PCM_2_16_24
dd 8192, 16384, resample_1 ; 8 PCM_1_16_24
 
dd 8192, 0x04000000, 15052, resample_2 ; 9 PCM_2_16_22
dd 4096, 0x04000000, 15052, resample_1 ;10 PCM_1_16_22
dd 8192, 15052, resample_2 ; 9 PCM_2_16_22
dd 4096, 15052, resample_1 ;10 PCM_1_16_22
 
dd 8192, 0x04000000, 10923, resample_2 ;11 PCM_2_16_16
dd 4096, 0x04000000, 10923, resample_1 ;12 PCM_1_16_16
dd 8192, 10923, resample_2 ;11 PCM_2_16_16
dd 4096, 10923, resample_1 ;12 PCM_1_16_16
 
dd 8192, 0x04000000, 8192, resample_2 ;13 PCM_2_16_12
dd 4096, 0x04000000, 8192, resample_1 ;14 PCM_1_16_12
dd 8192, 8192, resample_2 ;13 PCM_2_16_12
dd 4096, 8192, resample_1 ;14 PCM_1_16_12
 
dd 4096, 0x02000000, 7527, resample_2 ;15 PCM_2_16_11
dd 2048, 0x02000000, 7527, resample_1 ;16 PCM_1_16_11
dd 4096, 7527, resample_2 ;15 PCM_2_16_11
dd 2048, 7527, resample_1 ;16 PCM_1_16_11
 
dd 4096, 0x02000000, 5462, resample_2 ;17 PCM_2_16_8
dd 2048, 0x02000000, 5462, resample_1 ;18 PCM_1_16_8
dd 4096, 5462, resample_2 ;17 PCM_2_16_8
dd 2048, 5462, resample_1 ;18 PCM_1_16_8
 
dd 16384, 0, 0, s8_stereo ;19 PCM_2_8_48
dd 8192, 0, 0, m8_stereo ;20 PCM_1_8_48
dd 16384, 0, s8_stereo ;19 PCM_2_8_48
dd 8192, 0, m8_stereo ;20 PCM_1_8_48
 
dd 8192, 0x08000000, 30109, resample_28 ;21 PCM_2_8_44
dd 4096, 0x08000000, 30109, resample_18 ;22 PCM_1_8_44
dd 8192, 30109, resample_28 ;21 PCM_2_8_44
dd 4096, 30109, resample_18 ;22 PCM_1_8_44
 
dd 8192, 0x08000000, 21846, resample_28 ;23 PCM_2_8_32
dd 4096, 0x08000000, 21846, resample_18 ;24 PCM_1_8_32
dd 8192, 21846, resample_28 ;23 PCM_2_8_32
dd 4096, 21846, resample_18 ;24 PCM_1_8_32
 
dd 8192, 0x08000000, 16384, resample_28 ;25 PCM_2_8_24
dd 4096, 0x08000000, 16384, resample_18 ;26 PCM_1_8_24
dd 8192, 16384, resample_28 ;25 PCM_2_8_24
dd 4096, 16384, resample_18 ;26 PCM_1_8_24
 
dd 4096, 0x04000000, 15052, resample_28 ;27 PCM_2_8_22
dd 2048, 0x04000000, 15052, resample_18 ;28 PCM_1_8_22
dd 4096, 15052, resample_28 ;27 PCM_2_8_22
dd 2048, 15052, resample_18 ;28 PCM_1_8_22
 
dd 4096, 0x04000000, 10923, resample_28 ;29 PCM_2_8_16
dd 2048, 0x04000000, 10923, resample_18 ;30 PCM_1_8_16
dd 4096, 10923, resample_28 ;29 PCM_2_8_16
dd 2048, 10923, resample_18 ;30 PCM_1_8_16
 
dd 4096, 0x04000000, 8192, resample_28 ;31 PCM_2_8_12
dd 2048, 0x04000000, 8192, resample_18 ;32 PCM_1_8_12
dd 4096, 8192, resample_28 ;31 PCM_2_8_12
dd 2048, 8192, resample_18 ;32 PCM_1_8_12
 
dd 2048, 0x02000000, 7527, resample_28 ;33 PCM_2_8_11
dd 1024, 0x02000000, 7527, resample_18 ;34 PCM_1_8_11
dd 2048, 7527, resample_28 ;33 PCM_2_8_11
dd 1024, 7527, resample_18 ;34 PCM_1_8_11
 
dd 2048, 0x02000000, 5462, resample_28 ;35 PCM_2_8_8
dd 1024, 0x02000000, 5462, resample_18 ;36 PCM_1_8_8
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 0x00030003
version dd (4 shl 16) or (SOUND_VERSION and 0xFFFF)
 
szInfinity db 'INFINITY',0
szSound db 'SOUND',0
712,6 → 1269,8
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
720,6 → 1279,7
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