Subversion Repositories Kolibri OS

Rev

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