Subversion Repositories Kolibri OS

Rev

Rev 379 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;
  2. ;   This file is part of the Infinity sound library.
  3. ;   (C) copyright Serge 2006
  4. ;   email: infinity_sound@mail.ru
  5. ;
  6. ;   This program is free software; you can redistribute it and/or modify
  7. ;   it under the terms of the GNU General Public License as published by
  8. ;   the Free Software Foundation; either version 2 of the License, or
  9. ;   (at your option) any later version.
  10. ;
  11. ;   This program is distributed in the hope that it will be useful,
  12. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;   GNU General Public License for more details.
  15.  
  16. format MS COFF
  17.  
  18. include 'proc32.inc'
  19. include 'main.inc'
  20. include 'imports.inc'
  21.  
  22. FORCE_MMX         equ 0  ;set to 1 to force use mmx or
  23. FORCE_MMX_128     equ 0  ;integer sse2 extensions
  24.                         ;and reduce driver size
  25. ;USE_SSE          equ 0
  26.  
  27. DEBUG             equ 1
  28.  
  29.  
  30. OS_BASE           equ 0
  31. new_app_base     equ 0x80000000
  32. SLOT_BASE         equ OS_BASE+0x0080000
  33.  
  34. CAPS_SSE2         equ 26
  35. PG_SW             equ 0x003
  36.  
  37. public START
  38. public service_proc
  39. public version
  40.  
  41. RT_INP_EMPTY     equ 0xFF000001
  42. RT_OUT_EMPTY     equ 0xFF000002
  43. RT_INP_FULL       equ 0xFF000003
  44. RT_OUT_FULL       equ 0xFF000004
  45.  
  46. EVENT_WATCHED     equ 0x10000000
  47. EVENT_SIGNALED   equ 0x20000000
  48. MANUAL_RESET     equ 0x40000000
  49. MANUAL_DESTROY   equ 0x80000000
  50.  
  51. DEV_PLAY         equ 1
  52. DEV_STOP         equ 2
  53. DEV_CALLBACK     equ 3
  54.  
  55. struc IOCTL
  56. {  .handle        dd ?
  57.    .io_code       dd ?
  58.    .input         dd ?
  59.    .inp_size      dd ?
  60.    .output        dd ?
  61.    .out_size      dd ?
  62. }
  63.  
  64. virtual at 0
  65.   IOCTL IOCTL
  66. end virtual
  67.  
  68. section '.flat' code readable align 16
  69.  
  70. proc START stdcall, state:dword
  71.  
  72.            cmp [state], 1
  73.            jne .exit
  74.  
  75.            stdcall GetService, szSound
  76.            test eax, eax
  77.            jz .fail
  78.            mov [hSound], eax
  79.  
  80.            stdcall KernelAlloc, 16*512
  81.            test eax, eax
  82.            jz .out_of_mem
  83.            mov [mix_buff], eax
  84.  
  85.            mov eax, str.fd-FD_OFFSET
  86.            mov [str.fd], eax
  87.            mov [str.bk], eax
  88.  
  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.  
  109. if 0
  110.  
  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
  121. .mmx128:                                   ;128-bit integer sse2 extensions
  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
  127.  
  128. end if
  129.            stdcall set_handler, [hSound], new_mix
  130.            mov [eng_state], SND_STOP
  131.            stdcall RegService, szInfinity, service_proc
  132.            ret
  133. .fail:
  134.      if DEBUG
  135.            mov esi, msgFail
  136.            call SysMsgBoardStr
  137.      end if
  138. .exit:
  139.            xor eax, eax
  140.            ret
  141.  
  142. .out_of_mem:
  143.      if DEBUG
  144.            mov esi, msgMem
  145.            call SysMsgBoardStr
  146.      end if
  147.            xor eax, eax
  148.            ret
  149. endp
  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.  
  164.            cmp eax, SRV_GETVERSION
  165.            jne @F
  166.            mov eax, [edi+output]
  167.            mov eax, [eax]
  168.            mov [eax+new_app_base], dword SOUND_VERSION
  169.            xor eax, eax
  170.            ret
  171. @@:
  172.            cmp eax, SND_CREATE_BUFF
  173.            jne @F
  174.            mov ebx, [edi+input]
  175.            push edi
  176.            stdcall CreateBuffer,[ebx],[ebx+4]
  177.            pop edi
  178.            mov ecx, [edi+output]
  179.            mov ecx, [ecx]
  180.            mov [ecx+new_app_base], ebx
  181.            ret
  182. @@:
  183.            mov ebx, [edi+input]
  184.            mov edx, [ebx]
  185.  
  186.            cmp [edx+STREAM.magic], 'WAVE'
  187.            jne .fail
  188.  
  189.            cmp [edx+STREAM.size], STREAM_SIZE
  190.            jne .fail
  191.  
  192.            cmp eax, SND_DESTROY_BUFF
  193.            jne @F
  194.            mov eax, edx
  195.            call DestroyBuffer    ;edx= stream
  196.            ret
  197. @@:
  198.            cmp eax, SND_SETFORMAT
  199.            jne @F
  200.            stdcall SetFormat,[ebx],[ebx+4]
  201.            ret
  202. @@:
  203.            cmp eax, SND_GETFORMAT
  204.            jne @F
  205.  
  206.            movzx eax, word [edx+STREAM.format]
  207.            mov ecx, [edi+output]
  208.            mov ecx, [ecx]
  209.            mov [ecx+new_app_base], eax
  210.            xor eax, eax
  211.            ret
  212. @@:
  213.            cmp eax, SND_RESET
  214.            jne @F
  215.            stdcall ResetBuffer,[ebx],[ebx+4]
  216.            ret
  217. @@:
  218.            cmp eax, SND_SETPOS
  219.            jne @F
  220.            stdcall SetBufferPos,[ebx],[ebx+4]
  221.            ret
  222. @@:
  223.            cmp eax, SND_GETPOS
  224.            jne @F
  225.            push edi
  226.            stdcall GetBufferPos, [ebx]
  227.            pop edi
  228.            mov ecx, [edi+output]
  229.            mov ecx, [ecx]
  230.            mov [ecx+new_app_base], ebx
  231.            ret
  232. @@:
  233.            cmp eax, SND_SETBUFF
  234.            jne @F
  235.            mov eax, [ebx+4]
  236.            add eax, new_app_base
  237.            stdcall set_buffer, [ebx],eax,[ebx+8],[ebx+12]
  238.            ret
  239. @@:
  240.            cmp eax, SND_SETVOLUME
  241.            jne @F
  242.            stdcall SetBufferVol,[ebx],[ebx+4],[ebx+8]
  243.            ret
  244. @@:
  245.            cmp eax, SND_GETVOLUME
  246.            jne @F
  247.  
  248.            mov eax, [edi+output]
  249.            mov ecx, [eax]
  250.            mov eax, [eax+4]
  251.            add ecx, new_app_base
  252.            add eax, new_app_base
  253.            stdcall GetBufferVol,[ebx],ecx,eax
  254.            ret
  255. @@:
  256.            cmp eax, SND_SETPAN
  257.            jne @F
  258.            stdcall SetBufferPan,[ebx],[ebx+4]
  259.            ret
  260. @@:
  261.            cmp eax, SND_GETPAN
  262.            jne @F
  263.            mov eax, [edx+STREAM.pan]
  264.            mov ebx, [edi+output]
  265.            mov ebx, [ebx]
  266.            mov [ebx+new_app_base], eax
  267.            xor eax, eax
  268.            ret
  269. @@:
  270.            cmp eax, SND_OUT
  271.            jne @F
  272.  
  273.            mov eax, [ebx+4]
  274.            add eax, new_app_base
  275.            stdcall wave_out, [ebx],eax,[ebx+8]
  276.            ret
  277. @@:
  278.            cmp eax, SND_PLAY
  279.            jne @F
  280.  
  281.            stdcall play_buffer, [ebx],[ebx+4]
  282.            ret
  283. @@:
  284.            cmp eax, SND_STOP
  285.            jne @F
  286.  
  287.            stdcall stop_buffer, [ebx]
  288.            ret
  289. @@:
  290.            cmp eax, SND_GETBUFFSIZE
  291.            jne @F
  292.            mov eax, [edx+STREAM.in_size]
  293.            mov ecx, [edi+output]
  294.            mov ecx, [ecx]
  295.            mov [ecx+new_app_base], eax
  296.            xor eax, eax
  297.            ret
  298. @@:
  299. .fail:
  300.            or eax, -1
  301.            ret
  302. endp
  303.  
  304. restore   handle
  305. restore   io_code
  306. restore   input
  307. restore   inp_size
  308. restore   output
  309. restore   out_size
  310.  
  311. TASK_COUNT   equ 0x0003004
  312. CURRENT_TASK equ 0x0003000
  313.  
  314.  
  315. align 4
  316. proc CreateBuffer stdcall, format:dword, size:dword
  317.            locals
  318.              str         dd ?
  319.              ring_size   dd ?
  320.              ring_pages  dd ?
  321.            endl
  322.  
  323.            mov eax, [format]
  324.            cmp ax, PCM_1_8_8
  325.            ja .fail
  326.  
  327.            test eax, PCM_OUT
  328.            jnz .test_out
  329.            test eax, PCM_RING
  330.            jnz .test_ring
  331. ;staic
  332.            test eax, PCM_OUT+PCM_RING
  333.            jnz .fail
  334.            jmp .test_ok
  335. .test_out:
  336.            test eax, PCM_RING+PCM_STATIC
  337.            jnz .fail
  338.            jmp .test_ok
  339. .test_ring:
  340.            test eax, PCM_OUT+PCM_STATIC
  341.            jnz .fail
  342. .test_ok:
  343.            mov ebx, [CURRENT_TASK]      ;hack: direct accsess
  344.            shl ebx, 5                   ;to kernel data
  345.            mov ebx, [CURRENT_TASK+ebx+4]
  346.            mov eax, STREAM_SIZE
  347.  
  348.            call CreateObject
  349.            test eax, eax
  350.            jz .fail
  351.            mov [str], eax
  352.  
  353.            mov ebx, [format]
  354.            mov [eax+STREAM.format], ebx
  355.  
  356.            xor ecx, ecx
  357.            movzx ebx, bx
  358.            cmp ebx, 19
  359.            jb @f
  360.            mov ecx, 0x80808080
  361. @@:
  362.            mov [eax+STREAM.r_silence], ecx
  363.  
  364.            shl ebx, 2
  365.            lea ebx, [ebx+ebx*2]     ;ebx*=12
  366.  
  367.            mov ecx, [resampler_params+ebx]
  368.            mov edx, [resampler_params+ebx+4]
  369.            mov esi, [resampler_params+ebx+8]
  370.  
  371.            mov [eax+STREAM.r_size],ecx
  372.            mov [eax+STREAM.r_dt],  edx
  373.            mov [eax+STREAM.resample], esi
  374.            xor ecx, ecx
  375.            mov [eax+STREAM.l_vol], ecx
  376.            mov [eax+STREAM.r_vol], ecx
  377.            mov dword [eax+STREAM.l_amp], 0x7FFF7FFF
  378.            mov [eax+STREAM.pan], ecx
  379.  
  380.            test [format], PCM_STATIC
  381.            jnz .static
  382.  
  383. ; ring and waveout
  384.  
  385.            mov eax, 0x10000
  386.            test [format], PCM_RING
  387.            jz .waveout
  388.  
  389.            mov eax, [eax+STREAM.r_size]
  390.            add eax, 4095
  391.            and eax, -4096
  392.            add eax, eax
  393. .waveout:
  394.            mov [ring_size], eax
  395.            mov ebx, eax
  396.            shr ebx, 12
  397.            mov [ring_pages], ebx
  398.  
  399.            add eax, eax              ;double ring size
  400.            stdcall AllocKernelSpace, eax
  401.  
  402.            mov edi, [str]
  403.            mov ecx, [ring_size]
  404.            mov [edi+STREAM.in_base], eax
  405.            mov [edi+STREAM.in_size], ecx
  406.            add eax, 128
  407.            sub ecx, 128
  408.            mov [edi+STREAM.in_wp], eax
  409.            mov [edi+STREAM.in_rp], eax
  410.            mov [edi+STREAM.in_count], 0
  411.  
  412.            mov [edi+STREAM.in_free], ecx
  413.            add eax, ecx
  414.            mov [edi+STREAM.in_top], eax
  415.  
  416.            mov ebx, [ring_pages]
  417.            stdcall AllocPages, ebx
  418.            mov edi, [str]
  419.            mov ebx, [edi+STREAM.in_base]
  420.            mov ecx, [ring_pages]
  421.            or eax, PG_SW
  422.            push eax
  423.            push ebx
  424.            call CommitPages ;eax, ebx, ecx
  425.            mov ecx, [ring_pages]
  426.            pop ebx
  427.            pop eax
  428.            add ebx, [ring_size]
  429.            call CommitPages    ;double mapped
  430.  
  431.            jmp .out_buff
  432. .static:
  433.            mov ecx, [size]
  434.            add ecx, 128          ;resampler required
  435.            mov [eax+STREAM.in_size], ecx
  436.            stdcall KernelAlloc, ecx
  437.  
  438.            mov edi, [str]
  439.            mov [edi+STREAM.in_base], eax
  440.            add eax, 128
  441.            mov [edi+STREAM.in_wp], eax
  442.            mov [edi+STREAM.in_rp], eax
  443.            mov ebx, [size]
  444.            mov [edi+STREAM.in_count], ebx
  445.            mov [edi+STREAM.in_free], ebx
  446.            add eax, ebx
  447.            mov [edi+STREAM.in_top], eax
  448.  
  449. .out_buff:
  450.            stdcall AllocKernelSpace, dword 128*1024
  451.  
  452.            mov edi, [str]
  453.            mov [edi+STREAM.out_base], eax
  454.            mov [edi+STREAM.out_wp], eax
  455.            mov [edi+STREAM.out_rp], eax
  456.            mov [edi+STREAM.out_count], 0
  457.            add eax, 64*1024
  458.            mov [edi+STREAM.out_top], eax
  459.  
  460.            stdcall AllocPages, dword 64/4
  461.            mov edi, [str]
  462.            mov ebx, [edi+STREAM.out_base]
  463.            mov ecx, 16
  464.            or eax, PG_SW
  465.            push eax
  466.            push ebx
  467.            call CommitPages ;eax, ebx, ecx
  468.            mov ecx, 16
  469.            pop ebx
  470.            pop eax
  471.            add ebx, 64*1024
  472.            call CommitPages    ;double mapped
  473.  
  474.            mov edi, [str]
  475.            mov ecx, [edi+STREAM.in_top]
  476.            mov edi, [edi+STREAM.in_base]
  477.            sub ecx, edi
  478.            xor eax, eax
  479.            shr ecx, 2
  480.            cld
  481.            rep stosd
  482.  
  483.            mov edi, [str]
  484.            mov edi, [edi+STREAM.out_base]
  485.            mov ecx, (64*1024)/4
  486.            rep stosd
  487.  
  488.            xor edx, edx
  489.            mov ebx, MANUAL_DESTROY
  490.            call CreateEvent
  491.  
  492.            mov ebx, [str]
  493.            mov [ebx+STREAM.notify_event], eax
  494.            mov [ebx+STREAM.notify_id], edx
  495.  
  496.            mov [ebx+STREAM.magic], 'WAVE'
  497.            mov [ebx+STREAM.destroy], DestroyBuffer.destroy
  498.            mov [ebx+STREAM.size], STREAM_SIZE
  499.            mov [ebx+STREAM.flags], SND_STOP
  500.  
  501.            pushf
  502.            cli
  503.            mov eax, str.fd-FD_OFFSET
  504.            mov edx, [eax+STREAM.str_fd]
  505.            mov [ebx+STREAM.str_fd], edx
  506.            mov [ebx+STREAM.str_bk], eax
  507.            mov [eax+STREAM.str_fd], ebx
  508.            mov [edx+STREAM.str_bk], ebx
  509.            popf
  510.  
  511.            xor eax, eax
  512.            ret
  513. .fail:
  514.            xor ebx, ebx
  515.            or eax, -1
  516.            ret
  517. endp
  518.  
  519. ;param
  520. ; eax= buffer handle
  521.  
  522. align 4
  523. DestroyBuffer:
  524.            .handle equ esp       ;local
  525.  
  526.            mov [eax+STREAM.flags], SND_STOP
  527. .destroy:
  528.            push eax
  529.  
  530.            pushfd
  531.            cli
  532.            mov ebx, [eax+STREAM.str_fd]
  533.            mov ecx, [eax+STREAM.str_bk]
  534.            mov [ebx+STREAM.str_bk], ecx
  535.            mov [ecx+STREAM.str_fd], ebx
  536.            popf
  537.  
  538.            stdcall KernelFree, [eax+STREAM.in_base]
  539.            mov eax, [.handle]
  540.            stdcall KernelFree, [eax+STREAM.out_base]
  541.  
  542.            pop eax               ;restore stack
  543.            call DestroyObject    ;eax= stream
  544.            xor eax, eax
  545.            ret
  546. .fail:
  547.            or eax, -1
  548.            ret
  549. restore .handle
  550.  
  551. align 4
  552. proc SetFormat stdcall, str:dword, format:dword
  553.  
  554.            cmp word [format], PCM_1_8_8
  555.            ja .fail
  556.  
  557.            mov edx, [str]
  558.            mov [edx+STREAM.flags], SND_STOP
  559.  
  560.            test [edx+STREAM.format], PCM_RING
  561.            jnz .fail
  562.  
  563. ;           mov eax,[edx+STREAM.out_base]
  564. ;           mov [edx+STREAM.out_wp], eax
  565. ;           mov [edx+STREAM.out_rp], eax
  566. ;           mov [edx+STREAM.out_count], 0
  567.  
  568.            movzx eax, word [format]
  569.            mov word [edx+STREAM.format], ax
  570.  
  571.            xor ebx, ebx
  572.            cmp eax, 19
  573.            jb @f
  574.            mov ebx, 0x80808080
  575. @@:
  576.            mov [edx+STREAM.r_silence], ebx
  577.  
  578.            shl eax, 2
  579.            lea eax, [eax+eax*2]     ;eax*=12
  580.  
  581.            mov edi, [resampler_params+eax]
  582.            mov ecx, [resampler_params+eax+4]
  583.            mov ebx, [resampler_params+eax+8]
  584.  
  585.            mov [edx+STREAM.r_size],edi
  586.            mov [edx+STREAM.r_dt],  ecx
  587.            mov [edx+STREAM.resample], ebx
  588.  
  589.            mov edi, [edx+STREAM.in_base]
  590.            mov ecx, 128/4
  591.            mov eax, [edx+STREAM.r_silence]
  592.            cld
  593.            rep stosd
  594.            xor eax, eax
  595.            ret
  596. .fail:
  597.            or eax, -1
  598.            ret
  599. endp
  600.  
  601. ; for static buffers only
  602. ; use waveout for streams
  603.  
  604. align 4
  605. proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
  606.  
  607.            mov edx, [str]
  608.            test [edx+STREAM.format], PCM_OUT
  609.            jnz .fail
  610.  
  611.            mov esi, [src]
  612.            mov edi, [offs]
  613.            add edi, [edx+STREAM.in_base]
  614.            add edi, 128
  615.  
  616.            cmp edi, [edx+STREAM.in_top]
  617.            jae .fail
  618.  
  619.            mov ecx, [size]
  620.            lea ebx, [ecx+edi]
  621.            sub ebx, [edx+STREAM.in_top]
  622.            jb @F
  623.            sub ecx, ebx
  624. @@:
  625.            shr ecx, 2
  626.            cld
  627.            rep movsd
  628.            xor eax,eax
  629.            ret
  630. .fail:
  631.            or eax, -1
  632.            ret
  633. endp
  634.  
  635. ; for stream buffers only
  636.  
  637. align 4
  638. proc wave_out stdcall, str:dword,src:dword,size:dword
  639.            locals
  640.              state_saved  dd ?
  641.              fpu_state    rb 528
  642.            endl
  643.  
  644.            mov edx, [str]
  645.            mov eax, [edx+STREAM.format]
  646.            test eax, PCM_STATIC+PCM_RING
  647.            jnz .fail
  648.  
  649.            cmp ax, PCM_ALL
  650.            je .fail
  651.  
  652.            mov esi,[src]
  653.            test esi, esi
  654.            jz .fail
  655.  
  656.            cmp esi, new_app_base
  657.            jb .fail
  658.  
  659.            mov [state_saved], 0
  660.  
  661. .main_loop:
  662.            mov edx, [str]
  663.  
  664.            mov ebx, [size]
  665.            test ebx, ebx
  666.            jz .done
  667.  
  668.            cmp [edx+STREAM.flags], SND_STOP
  669.            jne .fill
  670.  
  671.            mov edi, [edx+STREAM.in_base]
  672.            mov ecx, 128/4
  673.            mov eax, [edx+STREAM.r_silence]
  674.            cld
  675.            rep stosd
  676.  
  677.            mov ecx, [edx+STREAM.in_size]
  678.            sub ecx, 128
  679.            mov [edx+STREAM.in_wp], edi
  680.            mov [edx+STREAM.in_rp], edi
  681.            mov [edx+STREAM.in_count], 0
  682.            mov [edx+STREAM.in_free], ecx
  683.  
  684.            mov eax,[edx+STREAM.out_base]
  685.            mov [edx+STREAM.out_wp], eax
  686.            mov [edx+STREAM.out_rp], eax
  687.            mov [edx+STREAM.out_count], 0
  688. .fill:
  689.            mov ecx, [edx+STREAM.in_free]
  690.            test ecx, ecx
  691.            jz .wait
  692.  
  693.            cmp ecx, ebx
  694.            jbe @F
  695.  
  696.            mov ecx, ebx
  697. @@:
  698.            sub [size], ecx
  699.            add [edx+STREAM.in_count], ecx
  700.            sub [edx+STREAM.in_free], ecx
  701.  
  702.            shr ecx, 2
  703.            mov edi, [edx+STREAM.in_wp]
  704.            mov esi, [src]
  705.            cld
  706.            rep movsd
  707.  
  708.            mov [src], esi
  709.            cmp edi, [edx+STREAM.in_top]
  710.            jb @F
  711.            sub edi, [edx+STREAM.in_size]
  712. @@:
  713.            mov [edx+STREAM.in_wp], edi
  714.  
  715.            cmp [edx+STREAM.out_count], 32768
  716.            jae .skip
  717.  
  718.            cmp [state_saved], 0
  719.            jne @F
  720.            lea eax, [fpu_state+15]
  721.            and eax, -16
  722.            call FpuSave
  723.            mov [state_saved], 1
  724. @@:
  725.            stdcall refill, edx
  726. .skip:
  727.            mov ebx, [str]
  728.            mov [ebx+STREAM.flags], SND_PLAY
  729.            cmp [eng_state], SND_PLAY
  730.            je .main_loop
  731.  
  732.            stdcall dev_play, [hSound]
  733.            mov [eng_state], SND_PLAY
  734.            jmp .main_loop
  735. .wait:
  736.            mov edx, [str]
  737.            mov eax, [edx+STREAM.notify_event]
  738.            mov ebx, [edx+STREAM.notify_id]
  739.            call WaitEvent   ;eax ebx
  740.            jmp .main_loop
  741. .done:
  742.            cmp [state_saved], 1
  743.            jne @F
  744.  
  745.            lea eax, [fpu_state+15]
  746.            and eax, -16
  747.            call FpuRestore
  748. @@:
  749.            xor eax, eax
  750.            ret
  751. .fail:
  752.            or eax, -1
  753.            ret
  754. endp
  755.  
  756. ; both static and stream
  757. ; reset all but not clear buffers
  758.  
  759.  
  760. ; flags reserved
  761. ;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
  762. ;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
  763. ;  RESET_ALL    equ 3
  764.  
  765.  
  766. align 4
  767. proc ResetBuffer stdcall, str:dword, flags:dword
  768.  
  769.            mov edx, [str]
  770.            mov [edx+STREAM.flags], SND_STOP
  771.  
  772.            mov edi, [edx+STREAM.in_base]
  773.            mov ecx, 128/4
  774.            mov eax, [edx+STREAM.r_silence]
  775.            cld
  776.            rep stosd
  777.  
  778.            mov [edx+STREAM.in_wp], edi
  779.            mov [edx+STREAM.in_rp], edi
  780.  
  781.            mov [edx+STREAM.in_count], 0
  782.            mov eax, [edx+STREAM.in_size]
  783.            sub eax, 128
  784.            mov [edx+STREAM.in_free], eax
  785.  
  786.            xor eax, eax
  787.            mov ebx,[edx+STREAM.out_base]
  788.            mov [edx+STREAM.out_wp], ebx
  789.            mov [edx+STREAM.out_rp], ebx
  790.            mov [edx+STREAM.out_count], eax
  791.            ret
  792. .fail:
  793.            or eax, -1
  794.            ret
  795. endp
  796.  
  797. ; for static buffers only
  798.  
  799. align 4
  800. proc SetBufferPos stdcall, str:dword, pos:dword
  801.  
  802.            mov edx, [str]
  803.            test [edx+STREAM.format], PCM_OUT+PCM_RING
  804.            jnz .fail
  805.  
  806.            mov [edx+STREAM.flags], SND_STOP
  807.  
  808.            mov eax, [pos]
  809.            add eax, [edx+STREAM.in_base]
  810.            mov ebx, [edx+STREAM.in_top]
  811.            add eax, 128
  812.  
  813.            cmp eax, ebx
  814.            jae .fail
  815.  
  816.            mov [edx+STREAM.in_rp], eax
  817.            sub ebx, eax
  818.            mov [edx+STREAM.in_count], ebx
  819.            xor eax, eax
  820.            ret
  821. .fail:
  822.            or eax, -1
  823.            ret
  824. endp
  825.  
  826. align 4
  827. proc GetBufferPos stdcall, str:dword
  828.  
  829.            mov edx, [str]
  830.            test [edx+STREAM.format], PCM_OUT+PCM_RING
  831.            jnz .fail
  832.  
  833.            mov ebx, [edx+STREAM.in_rp]
  834.            xor eax, eax
  835.            ret
  836. .fail:
  837.            xor ebx,ebx
  838.            or eax, -1
  839.            ret
  840. endp
  841.  
  842. ; both
  843.  
  844. align 4
  845. proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
  846.  
  847.            mov edx, [str]
  848.            stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
  849.            ret
  850. endp
  851.  
  852. proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
  853.            locals
  854.              _600    dd ?
  855.              _32767  dd ?
  856.              state   rb 108
  857.            endl
  858.  
  859.            mov [_600], 0x44160000   ;600.0
  860.            mov [_32767], 32767
  861.  
  862.            lea ebx, [state]
  863.            fnsave [ebx]
  864.  
  865.            movq mm0, qword [l_vol]
  866.            pminsw mm0, qword [vol_max]
  867.            pmaxsw mm0, qword [vol_min]
  868.            movq qword [l_vol], mm0
  869.            movq qword [edx+STREAM.l_vol], mm0
  870.  
  871.            movd mm1,[pan]
  872.            pminsw mm1, qword [pan_max]
  873.            pmaxsw mm1, qword [vol_min]
  874.            movd [edx+STREAM.pan], mm1
  875.  
  876.            cmp word [edx+STREAM.pan], 0
  877.            jl @F
  878.  
  879.            psubsw mm0,mm1
  880.            pminsw mm0, qword [vol_max]
  881.            pmaxsw mm0, qword [vol_min]
  882.            movd [l_vol],mm0
  883.            jmp .calc_amp
  884. @@:
  885.            punpckhdq mm0,mm0
  886.            paddsw mm0,mm1
  887.            pminsw mm0, qword [vol_max]
  888.            pmaxsw mm0, qword [vol_min]
  889.            movd [r_vol], mm0
  890. .calc_amp:
  891.            emms
  892.            fild word [l_vol]
  893.  
  894.            call .calc
  895.  
  896.            fistp word [edx+STREAM.l_amp]
  897.            fstp st0
  898.  
  899.            fild word [r_vol]
  900.  
  901.            call .calc
  902.  
  903.            fistp word [edx+STREAM.r_amp]
  904.            fstp st0
  905.  
  906.            fnclex
  907.            lea ebx, [state]
  908.            frstor [ebx]
  909.  
  910.            xor eax, eax
  911.            inc eax
  912.            ret
  913. .calc:
  914.            fdiv dword [_600]
  915.            fld st0
  916.            frndint
  917.            fxch st1
  918.            fsub st, st1
  919.            f2xm1
  920.            fld1
  921.            faddp st1, st0
  922.            fscale
  923.            fimul dword [_32767]
  924.            ret 0
  925. endp
  926.  
  927. align 4
  928. proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
  929.  
  930.            mov edx, [str]
  931.            mov eax, [p_lvol]
  932.            movsx ecx, word [edx+STREAM.l_vol]
  933.            mov [eax], ecx
  934.  
  935.            mov eax, [p_rvol]
  936.            movsx ecx, word [edx+STREAM.r_vol]
  937.            mov [eax], ecx
  938.            xor eax, eax
  939.            ret
  940. endp
  941.  
  942. align 4
  943. proc SetBufferPan stdcall, str:dword,pan:dword
  944.  
  945.            mov edx, [str]
  946.            stdcall set_vol_param,[edx+STREAM.l_vol],\
  947.                                  [edx+STREAM.r_vol],[pan]
  948.            ret
  949. endp
  950.  
  951. ; for static and ring buffers only
  952.  
  953. align 4
  954. proc play_buffer stdcall, str:dword, flags:dword
  955.            locals
  956.              fpu_state   rb 528
  957.            endl
  958.  
  959.            mov ebx, [str]
  960.            mov eax, [ebx+STREAM.format]
  961.            test eax, PCM_OUT
  962.            jnz .fail
  963.  
  964.            cmp ax, PCM_ALL
  965.            je .fail
  966.  
  967.            mov [ebx+STREAM.flags], SND_PLAY
  968.            cmp [eng_state], SND_PLAY
  969.            je .done
  970.  
  971.            stdcall  dev_play, [hSound]
  972.            mov [eng_state], SND_PLAY
  973. .done:
  974.            test [flags], PLAY_SYNC
  975.            jz @F
  976.  
  977.            mov edx, [str]
  978. .wait:
  979.            mov eax, [edx+STREAM.notify_event]
  980.            mov ebx, [edx+STREAM.notify_id]
  981.            call WaitEvent   ;eax ebx
  982.  
  983.            mov edx, [str]
  984.            cmp [edx+STREAM.flags], SND_STOP
  985.            jne .wait
  986. @@:
  987.            xor eax, eax
  988.            ret
  989. .fail:
  990.            or eax, -1
  991.            ret
  992. endp
  993.  
  994. ; for static buffers only
  995.  
  996. align 4
  997. proc stop_buffer stdcall, str:dword
  998.  
  999.            mov edx, [str]
  1000.            test [edx+STREAM.format], PCM_STATIC+PCM_RING
  1001.            jz .fail
  1002.  
  1003.            mov [edx+STREAM.flags], SND_STOP
  1004.  
  1005. ;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
  1006.  
  1007.            mov eax, [edx+STREAM.notify_event]
  1008.            mov ebx, [edx+STREAM.notify_id]
  1009.            call ClearEvent   ;eax ebx
  1010.  
  1011.            xor eax, eax
  1012.            ret
  1013. .fail:
  1014.            or eax, -1
  1015.            ret
  1016. endp
  1017.  
  1018. ; parm
  1019. ;  eax= mix_list
  1020.  
  1021. align 4
  1022. do_mix_list:
  1023.  
  1024.            xor edx, edx
  1025.            mov esi, str.fd-FD_OFFSET
  1026.            mov ebx, [esi+STREAM.str_fd]
  1027. @@:
  1028.            cmp ebx, esi
  1029.            je .done
  1030.  
  1031.            cmp [ebx+STREAM.magic], 'WAVE'
  1032.            jne .next
  1033.  
  1034.            cmp [ebx+STREAM.size], STREAM_SIZE
  1035.            jne .next
  1036.  
  1037.            cmp [ebx+STREAM.flags], SND_PLAY;
  1038.            jne .next
  1039.  
  1040.            mov ecx, [ebx+STREAM.out_count]
  1041.            test ecx, ecx
  1042.            jnz .l1
  1043.  
  1044.            test [ebx+STREAM.format], PCM_RING
  1045.            jnz .next
  1046.            mov [ebx+STREAM.flags], SND_STOP
  1047.            jmp .next
  1048. .l1:
  1049.            cmp ecx, 512
  1050.            jae .add_buff
  1051.  
  1052.            mov edi, [ebx+STREAM.out_rp]
  1053.            add edi, ecx
  1054.            sub ecx, 512
  1055.            neg ecx
  1056.            push eax
  1057.            xor eax, eax
  1058.            cld
  1059.            rep stosb
  1060.            pop eax
  1061.  
  1062.            mov [ebx+STREAM.out_count], 512
  1063.  
  1064. .add_buff:
  1065.            mov ecx, [ebx+STREAM.out_rp]
  1066.            mov [eax],ecx
  1067.            mov edi, dword [ebx+STREAM.l_amp]
  1068.            mov [eax+4], edi
  1069.            add [ebx+STREAM.out_rp], 512
  1070.            sub [ebx+STREAM.out_count], 512
  1071.  
  1072.            add eax, 8
  1073.            inc edx
  1074. .next:
  1075.            mov ebx, [ebx+STREAM.str_fd]
  1076.            jmp @B
  1077. .done:
  1078.            mov eax, edx
  1079.            ret
  1080.  
  1081. align 4
  1082. prepare_playlist:
  1083.  
  1084.            xor edx, edx
  1085.            mov [play_count], edx
  1086.            mov esi, str.fd-FD_OFFSET
  1087.            mov edi, [esi+STREAM.str_fd]
  1088. @@:
  1089.            cmp edi, esi
  1090.            je .done
  1091.  
  1092.            cmp [edi+STREAM.magic], 'WAVE'
  1093.            jne .next
  1094.  
  1095.            cmp [edi+STREAM.size], STREAM_SIZE
  1096.            jne .next
  1097.  
  1098.            cmp [edi+STREAM.flags], SND_PLAY;
  1099.            jne .next
  1100.  
  1101.            mov [play_list+edx], edi
  1102.            inc [play_count]
  1103.            add edx, 4
  1104. .next:
  1105.            mov edi, [edi+STREAM.str_fd]
  1106.            jmp @B
  1107. .done:
  1108.            ret
  1109.  
  1110. align 4
  1111. proc set_handler stdcall, hsrv:dword, handler_proc:dword
  1112.            locals
  1113.              handler    dd ?
  1114.              io_code    dd ?
  1115.              input      dd ?
  1116.              inp_size   dd ?
  1117.              output     dd ?
  1118.              out_size   dd ?
  1119.              val        dd ?
  1120.            endl
  1121.  
  1122.            mov eax, [hsrv]
  1123.            lea ecx, [handler_proc]
  1124.            xor ebx, ebx
  1125.  
  1126.            mov [handler], eax
  1127.            mov [io_code], DEV_CALLBACK
  1128.            mov [input], ecx
  1129.            mov [inp_size], 4
  1130.            mov [output], ebx
  1131.            mov [out_size], 0
  1132.  
  1133.            lea eax, [handler]
  1134.            stdcall ServiceHandler, eax
  1135.            ret
  1136. endp
  1137.  
  1138. align 4
  1139. proc dev_play stdcall, hsrv:dword
  1140.            locals
  1141.              handle     dd ?
  1142.              io_code    dd ?
  1143.              input      dd ?
  1144.              inp_size   dd ?
  1145.              output     dd ?
  1146.              out_size   dd ?
  1147.              val        dd ?
  1148.            endl
  1149.  
  1150.            mov eax, [hsrv]
  1151.            xor ebx, ebx
  1152.  
  1153.            mov [handle], eax
  1154.            mov [io_code], DEV_PLAY
  1155.            mov [input], ebx
  1156.            mov [inp_size], ebx
  1157.            mov [output], ebx
  1158.            mov [out_size], ebx
  1159.  
  1160.            lea eax, [handle]
  1161.            stdcall ServiceHandler, eax
  1162.            ret
  1163. endp
  1164.  
  1165. if 0
  1166. align 4
  1167. dword2str:
  1168.       mov  esi, hex_buff
  1169.       mov ecx, -8
  1170. @@:
  1171.       rol eax, 4
  1172.       mov ebx, eax
  1173.       and ebx, 0x0F
  1174.       mov bl, [ebx+hexletters]
  1175.       mov [8+esi+ecx], bl
  1176.       inc ecx
  1177.       jnz @B
  1178.       ret
  1179.  
  1180. hexletters   db '0123456789ABCDEF'
  1181. hex_buff     db 8 dup(0),13,10,0
  1182.  
  1183. end if
  1184.  
  1185. include 'mixer.asm'
  1186. include 'mix_mmx.inc'
  1187. include 'mix_sse2.inc'
  1188.  
  1189. ;if USE_SSE
  1190. ; include 'mix_sse.inc'
  1191. ;end if
  1192.  
  1193. align 16
  1194. resampler_params:
  1195.      ;r_size    r_dt   resampler_func
  1196.      dd 0,0,0                                  ; 0  PCM_ALL
  1197.      dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
  1198.      dd 16384,      0, m16_stereo     ; 2  PCM_1_16_48
  1199.  
  1200.      dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
  1201.      dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
  1202.  
  1203.      dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
  1204.      dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
  1205.  
  1206.      dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
  1207.      dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
  1208.  
  1209.      dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
  1210.      dd  4096,  15052, resample_1     ;10  PCM_1_16_22
  1211.  
  1212.      dd  8192,  10923, resample_2     ;11  PCM_2_16_16
  1213.      dd  4096,  10923, resample_1     ;12  PCM_1_16_16
  1214.  
  1215.      dd  8192,   8192, resample_2     ;13  PCM_2_16_12
  1216.      dd  4096,   8192, resample_1     ;14  PCM_1_16_12
  1217.  
  1218.      dd  4096,   7527, resample_2     ;15  PCM_2_16_11
  1219.      dd  2048,   7527, resample_1     ;16  PCM_1_16_11
  1220.  
  1221.      dd  4096,   5462, resample_2     ;17  PCM_2_16_8
  1222.      dd  2048,   5462, resample_1     ;18  PCM_1_16_8
  1223.  
  1224.      dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
  1225.      dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
  1226.  
  1227.      dd  8192,  30109, resample_28    ;21  PCM_2_8_44
  1228.      dd  4096,  30109, resample_18    ;22  PCM_1_8_44
  1229.  
  1230.      dd  8192,  21846, resample_28    ;23  PCM_2_8_32
  1231.      dd  4096,  21846, resample_18    ;24  PCM_1_8_32
  1232.  
  1233.      dd  8192,  16384, resample_28    ;25  PCM_2_8_24
  1234.      dd  4096,  16384, resample_18    ;26  PCM_1_8_24
  1235.  
  1236.      dd  4096,  15052, resample_28    ;27  PCM_2_8_22
  1237.      dd  2048,  15052, resample_18    ;28  PCM_1_8_22
  1238.  
  1239.      dd  4096,  10923, resample_28    ;29  PCM_2_8_16
  1240.      dd  2048,  10923, resample_18    ;30  PCM_1_8_16
  1241.  
  1242.      dd  4096,   8192, resample_28    ;31  PCM_2_8_12
  1243.      dd  2048,   8192, resample_18    ;32  PCM_1_8_12
  1244.  
  1245.      dd  2048,   7527, resample_28    ;33  PCM_2_8_11
  1246.      dd  1024,   7527, resample_18    ;34  PCM_1_8_11
  1247.  
  1248.      dd  2048,   5462, resample_28    ;35  PCM_2_8_8
  1249.      dd  1024,   5462, resample_18    ;36  PCM_1_8_8
  1250.  
  1251. m7            dw 0x8000,0x8000,0x8000,0x8000
  1252. mm80          dq 0x8080808080808080
  1253. mm_mask       dq 0xFF00FF00FF00FF00
  1254.  
  1255. vol_max       dd 0x00000000,0x00000000
  1256. vol_min       dd 0x0000D8F0,0x0000D8F0
  1257. pan_max       dd 0x00002710,0x00002710
  1258.  
  1259. ;stream_map    dd 0xFFFF       ; 16
  1260. version       dd (4 shl 16) or (SOUND_VERSION and 0xFFFF)
  1261.  
  1262. szInfinity    db 'INFINITY',0
  1263. szSound       db 'SOUND',0
  1264.  
  1265. if DEBUG
  1266. msgFail       db 'Sound service not loaded',13,10,0
  1267. msgPlay       db 'Play buffer',13,10,0
  1268. msgStop       db 'Stop',13,10,0
  1269. msgUser       db 'User callback',13,10,0
  1270. msgMem        db 'Not enough memory',13,10,0
  1271. msgDestroy    db 'Destroy sound buffer', 13,10,0
  1272. msgWaveout    db 'Play waveout', 13,10,0
  1273. msgSetVolume  db 'Set volume',13,10,0
  1274. end if
  1275.  
  1276. section '.data' data readable writable align 16
  1277.  
  1278. play_list     rd 16
  1279. mix_input     rd 16
  1280. play_count    rd 1
  1281. hSound        rd 1
  1282. eng_state     rd 1
  1283. mix_buff      rd 1
  1284. mix_buff_map  rd 1
  1285. str.fd        rd 1
  1286. str.bk        rd 1
  1287.  
  1288. mix_2_core    rd 1
  1289. mix_3_core    rd 1
  1290. mix_4_core    rd 1
  1291.  
  1292.