Subversion Repositories Kolibri OS

Rev

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