;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; ;; 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 0xE0000000 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 mov ecx, 16*512 mov edx, PG_SW call MemAlloc 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 proc service_proc stdcall, ioctl:dword mov edi, [ioctl] mov eax, [edi+io_code] cmp eax, SRV_GETVERSION jne @F mov eax, [edi+output] cmp [edi+out_size], 4 jne .fail mov eax, [eax] mov [eax], dword API_VERSION xor eax, eax ret @@: cmp eax, SND_CREATE_BUFF jne @F mov ebx, [edi+input] stdcall CreateBuffer,[ebx],[ebx+4] mov edi, [ioctl] mov ecx, [edi+output] mov ecx, [ecx] mov [ecx], ebx ret @@: 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 eax, edx call DestroyBuffer ;edx= stream ret @@: cmp eax, SND_SETFORMAT jne @F stdcall SetFormat,edx,[ebx+4] ret @@: cmp eax, SND_GETFORMAT jne @F movzx eax, word [edx+STREAM.format] mov ecx, [edi+output] mov ecx, [ecx] mov [ecx], eax xor eax, eax ret @@: cmp eax, SND_RESET jne @F stdcall ResetBuffer,edx,[ebx+4] ret @@: cmp eax, SND_SETPOS jne @F stdcall SetBufferPos,edx,[ebx+4] ret @@: cmp eax, SND_GETPOS jne @F stdcall GetBufferPos, edx mov edi, [ioctl] mov ecx, [edi+output] mov ecx, [ecx] mov [ecx], ebx ret @@: cmp eax, SND_SETBUFF jne @F mov eax, [ebx+4] stdcall set_buffer, edx,eax,[ebx+8],[ebx+12] ret @@: cmp eax, SND_SETVOLUME jne @F stdcall SetBufferVol,edx,[ebx+4],[ebx+8] ret @@: cmp eax, SND_GETVOLUME jne @F mov eax, [edi+output] mov ecx, [eax] mov eax, [eax+4] stdcall GetBufferVol,edx,ecx,eax ret @@: cmp eax, SND_SETPAN jne @F stdcall SetBufferPan,edx,[ebx+4] ret @@: cmp eax, SND_GETPAN jne @F mov eax, [edx+STREAM.pan] mov ebx, [edi+output] mov ebx, [ebx] mov [ebx], eax xor eax, eax ret @@: cmp eax, SND_OUT jne @F mov eax, [ebx+4] stdcall wave_out, edx,eax,[ebx+8] ret @@: cmp eax, SND_PLAY jne @F stdcall play_buffer, edx,[ebx+4] ret @@: cmp eax, SND_STOP jne @F stdcall stop_buffer, edx ret @@: cmp eax, SND_GETBUFFSIZE jne @F mov eax, [edx+STREAM.in_size] mov ecx, [edi+output] mov ecx, [ecx] mov [ecx], eax xor eax, eax ret @@: cmp eax, SND_GETFREESPACE jne @F 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 @@: .fail: or eax, -1 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 ? 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_SIZE 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 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 ; sub ecx, 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 mov edx, PG_SW call MemAlloc 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 CreateRingBuffer, 64*1024, PG_SW mov edi, [str] 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.out_top], eax 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 edx, edx mov ebx, 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_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 .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 mov ecx, [eax+STREAM.in_base] call MemFree mov eax, [.handle] mov ecx, [eax+STREAM.out_base] call MemFree 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: 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: 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: 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_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 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_SIZE 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