Subversion Repositories Kolibri OS

Rev

Rev 1024 | Blame | Last modification | View Log | Download | RSS feed

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