Subversion Repositories Kolibri OS

Rev

Rev 855 | Go to most recent revision | 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 HeapAlloc
  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 HeapAlloc
  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.            stdcall KernelFree, [eax+STREAM.in_base]
  517.            mov eax, [.handle]
  518.            stdcall KernelFree, [eax+STREAM.out_base]
  519.  
  520.            pop eax               ;restore stack
  521.            call DestroyObject    ;eax= stream
  522.            xor eax, eax
  523.            ret
  524. .fail:
  525.            or eax, -1
  526.            ret
  527. restore .handle
  528.  
  529. align 4
  530. proc SetFormat stdcall, str:dword, format:dword
  531.  
  532.            cmp word [format], PCM_1_8_8
  533.            ja .fail
  534.  
  535.            mov edx, [str]
  536.            mov [edx+STREAM.flags], SND_STOP
  537.  
  538.            test [edx+STREAM.format], PCM_RING
  539.            jnz .fail
  540.  
  541. ;           mov eax,[edx+STREAM.out_base]
  542. ;           mov [edx+STREAM.out_wp], eax
  543. ;           mov [edx+STREAM.out_rp], eax
  544. ;           mov [edx+STREAM.out_count], 0
  545.  
  546.            movzx eax, word [format]
  547.            mov word [edx+STREAM.format], ax
  548.  
  549.            xor ebx, ebx
  550.            cmp eax, 19
  551.            jb @f
  552.            mov ebx, 0x80808080
  553. @@:
  554.            mov [edx+STREAM.r_silence], ebx
  555.  
  556.            shl eax, 2
  557.            lea eax, [eax+eax*2]     ;eax*=12
  558.  
  559.            mov edi, [resampler_params+eax]
  560.            mov ecx, [resampler_params+eax+4]
  561.            mov ebx, [resampler_params+eax+8]
  562.  
  563.            mov [edx+STREAM.r_size],edi
  564.            mov [edx+STREAM.r_dt],  ecx
  565.            mov [edx+STREAM.resample], ebx
  566.  
  567.            mov edi, [edx+STREAM.in_base]
  568.            mov ecx, 128/4
  569.            mov eax, [edx+STREAM.r_silence]
  570.            cld
  571.            rep stosd
  572.            xor eax, eax
  573.            ret
  574. .fail:
  575.            or eax, -1
  576.            ret
  577. endp
  578.  
  579. ; for static buffers only
  580. ; use waveout for streams
  581.  
  582. align 4
  583. proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
  584.  
  585.            mov edx, [str]
  586.            test [edx+STREAM.format], PCM_OUT
  587.            jnz .fail
  588.  
  589.            mov esi, [src]
  590.            mov edi, [offs]
  591.            add edi, [edx+STREAM.in_base]
  592.            add edi, 128
  593.  
  594.            cmp edi, [edx+STREAM.in_top]
  595.            jae .fail
  596.  
  597.            mov ecx, [size]
  598.            lea ebx, [ecx+edi]
  599.            sub ebx, [edx+STREAM.in_top]
  600.            jb @F
  601.            sub ecx, ebx
  602. @@:
  603.            shr ecx, 2
  604.            cld
  605.            rep movsd
  606.            xor eax,eax
  607.            ret
  608. .fail:
  609.            or eax, -1
  610.            ret
  611. endp
  612.  
  613. ; for stream buffers only
  614.  
  615. align 4
  616. proc wave_out stdcall, str:dword,src:dword,size:dword
  617.            locals
  618.              state_saved  dd ?
  619.              fpu_state    rb 528
  620.            endl
  621.  
  622.            mov edx, [str]
  623.            mov eax, [edx+STREAM.format]
  624.            test eax, PCM_OUT
  625.            jz .fail
  626.  
  627.            cmp ax, PCM_ALL
  628.            je .fail
  629.  
  630.            mov esi,[src]
  631.            test esi, esi
  632.            jz .fail
  633.  
  634.            cmp esi, OS_BASE
  635.            jae .fail
  636.  
  637.            mov [state_saved], 0
  638.  
  639. .main_loop:
  640.            mov edx, [str]
  641.  
  642.            mov ebx, [size]
  643.            test ebx, ebx
  644.            jz .done
  645.  
  646.            cmp [edx+STREAM.flags], SND_STOP
  647.            jne .fill
  648.  
  649.            mov edi, [edx+STREAM.in_base]
  650.            mov ecx, 128/4
  651.            mov eax, [edx+STREAM.r_silence]
  652.            cld
  653.            rep stosd
  654.  
  655.            mov ecx, [edx+STREAM.in_size]
  656.            sub ecx, 128
  657.            mov [edx+STREAM.in_wp], edi
  658.            mov [edx+STREAM.in_rp], edi
  659.            mov [edx+STREAM.in_count], 0
  660.            mov [edx+STREAM.in_free], ecx
  661.  
  662.            mov eax,[edx+STREAM.out_base]
  663.            mov [edx+STREAM.out_wp], eax
  664.            mov [edx+STREAM.out_rp], eax
  665.            mov [edx+STREAM.out_count], 0
  666. .fill:
  667.            mov ecx, [edx+STREAM.in_free]
  668.            test ecx, ecx
  669.            jz .wait
  670.  
  671.            cmp ecx, ebx
  672.            jbe @F
  673.  
  674.            mov ecx, ebx
  675. @@:
  676.            sub [size], ecx
  677.            add [edx+STREAM.in_count], ecx
  678.            sub [edx+STREAM.in_free], ecx
  679.  
  680.            shr ecx, 2
  681.            mov edi, [edx+STREAM.in_wp]
  682.            mov esi, [src]
  683.            cld
  684.            rep movsd
  685.  
  686.            mov [src], esi
  687.            cmp edi, [edx+STREAM.in_top]
  688.            jb @F
  689.            sub edi, [edx+STREAM.in_size]
  690. @@:
  691.            mov [edx+STREAM.in_wp], edi
  692.  
  693.            cmp [edx+STREAM.out_count], 32768
  694.            jae .skip
  695.  
  696.            cmp [state_saved], 0
  697.            jne @F
  698.            lea eax, [fpu_state+15]
  699.            and eax, -16
  700.            call FpuSave
  701.            mov [state_saved], 1
  702. @@:
  703.            stdcall refill, edx
  704. .skip:
  705.            mov edx, [str]
  706.            mov [edx+STREAM.flags], SND_PLAY
  707.            cmp [eng_state], SND_PLAY
  708.            je .main_loop
  709.  
  710.            stdcall dev_play, [hSound]
  711.            mov [eng_state], SND_PLAY
  712.            jmp .main_loop
  713. .wait:
  714.            mov edx, [str]
  715.            mov eax, [edx+STREAM.notify_event]
  716.            mov ebx, [edx+STREAM.notify_id]
  717.            call WaitEvent   ;eax ebx
  718.            jmp .main_loop
  719. .done:
  720.            cmp [state_saved], 1
  721.            jne @F
  722.  
  723.            lea eax, [fpu_state+15]
  724.            and eax, -16
  725.            call FpuRestore
  726. @@:
  727.            xor eax, eax
  728.            ret
  729. .fail:
  730.            or eax, -1
  731.            ret
  732. endp
  733.  
  734. ; both static and stream
  735. ; reset all but not clear buffers
  736.  
  737.  
  738. ; flags reserved
  739. ;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
  740. ;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
  741. ;  RESET_ALL    equ 3
  742.  
  743.  
  744. align 4
  745. proc ResetBuffer stdcall, str:dword, flags:dword
  746.  
  747.            mov edx, [str]
  748.            mov [edx+STREAM.flags], SND_STOP
  749.  
  750.            mov edi, [edx+STREAM.in_base]
  751.            mov ecx, 128/4
  752.            mov eax, [edx+STREAM.r_silence]
  753.            cld
  754.            rep stosd
  755.  
  756.            mov [edx+STREAM.in_wp], edi
  757.            mov [edx+STREAM.in_rp], edi
  758.  
  759.            test [edx+STREAM.flags], PCM_STATIC
  760.            jnz .static
  761.            mov [edx+STREAM.in_count], 0
  762.            jmp @F
  763. .static:
  764.            mov eax, [edx+STREAM.in_size]
  765.            mov [edx+STREAM.in_count], eax
  766. @@:
  767.  
  768.            mov eax, [edx+STREAM.in_size]
  769.            sub eax, 128
  770.            mov [edx+STREAM.in_free], eax
  771.  
  772.            xor eax, eax
  773.            mov ebx,[edx+STREAM.out_base]
  774.            mov [edx+STREAM.out_wp], ebx
  775.            mov [edx+STREAM.out_rp], ebx
  776.            mov [edx+STREAM.out_count], eax
  777.            ret
  778. .fail:
  779.            or eax, -1
  780.            ret
  781. endp
  782.  
  783. ; for static buffers only
  784.  
  785. align 4
  786. proc SetBufferPos stdcall, str:dword, pos:dword
  787.  
  788.            mov edx, [str]
  789.            test [edx+STREAM.format], PCM_STATIC
  790.            jz .fail
  791.  
  792.            mov [edx+STREAM.flags], SND_STOP
  793.  
  794.            mov eax, [pos]
  795.            add eax, [edx+STREAM.in_base]
  796.            mov ebx, [edx+STREAM.in_top]
  797.            add eax, 128
  798.  
  799.            cmp eax, ebx
  800.            jae .fail
  801.  
  802.            mov [edx+STREAM.in_rp], eax
  803.            sub ebx, eax
  804.            mov [edx+STREAM.in_count], ebx
  805.            xor eax, eax
  806.            ret
  807. .fail:
  808.            or eax, -1
  809.            ret
  810. endp
  811.  
  812. align 4
  813. proc GetBufferPos stdcall, str:dword
  814.  
  815.            mov edx, [str]
  816.            test [edx+STREAM.format], PCM_STATIC
  817.            jz .fail
  818.  
  819.            mov ebx, [edx+STREAM.in_rp]
  820.            sub ebx, [edx+STREAM.in_base]
  821.            sub ebx, 128
  822.            xor eax, eax
  823.            ret
  824. .fail:
  825.            xor ebx,ebx
  826.            or eax, -1
  827.            ret
  828. endp
  829.  
  830. ; both
  831.  
  832. align 4
  833. proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
  834.  
  835.            mov edx, [str]
  836.            stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
  837.            ret
  838. endp
  839.  
  840. proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
  841.            locals
  842.              _600    dd ?
  843.              _32767  dd ?
  844.              state   rb 108
  845.            endl
  846.  
  847.            mov [_600], 0x44160000   ;600.0
  848.            mov [_32767], 32767
  849.  
  850.            lea ebx, [state]
  851.            fnsave [ebx]
  852.  
  853.            movq mm0, qword [l_vol]
  854.            pminsw mm0, qword [vol_max]
  855.            pmaxsw mm0, qword [vol_min]
  856.            movq qword [l_vol], mm0
  857.            movq qword [edx+STREAM.l_vol], mm0
  858.  
  859.            movd mm1,[pan]
  860.            pminsw mm1, qword [pan_max]
  861.            pmaxsw mm1, qword [vol_min]
  862.            movd [edx+STREAM.pan], mm1
  863.  
  864.            cmp word [edx+STREAM.pan], 0
  865.            jl @F
  866.  
  867.            psubsw mm0,mm1
  868.            pminsw mm0, qword [vol_max]
  869.            pmaxsw mm0, qword [vol_min]
  870.            movd [l_vol],mm0
  871.            jmp .calc_amp
  872. @@:
  873.            punpckhdq mm0,mm0
  874.            paddsw mm0,mm1
  875.            pminsw mm0, qword [vol_max]
  876.            pmaxsw mm0, qword [vol_min]
  877.            movd [r_vol], mm0
  878. .calc_amp:
  879.            emms
  880.            fild word [l_vol]
  881.  
  882.            call .calc
  883.  
  884.            fistp word [edx+STREAM.l_amp]
  885.            fstp dword [edx+STREAM.l_amp_f]
  886.            fstp st0
  887.  
  888.            fild word [r_vol]
  889.  
  890.            call .calc
  891.  
  892.            fistp word [edx+STREAM.r_amp]
  893.            fstp dword [edx+STREAM.r_amp_f]
  894.            fstp st0
  895.  
  896.            fnclex
  897.            lea ebx, [state]
  898.            frstor [ebx]
  899.  
  900.            xor eax, eax
  901.            inc eax
  902.            ret
  903. .calc:
  904.            fdiv dword [_600]
  905.            fld st0
  906.            frndint
  907.            fxch st1
  908.            fsub st, st1
  909.            f2xm1
  910.            fld1
  911.            faddp st1, st0
  912.            fscale
  913.            fld st0
  914.            fimul dword [_32767]
  915.            ret 0
  916. endp
  917.  
  918. align 4
  919. proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
  920.  
  921.            mov edx, [str]
  922.            mov eax, [p_lvol]
  923.            movsx ecx, word [edx+STREAM.l_vol]
  924.            mov [eax], ecx
  925.  
  926.            mov eax, [p_rvol]
  927.            movsx ecx, word [edx+STREAM.r_vol]
  928.            mov [eax], ecx
  929.            xor eax, eax
  930.            ret
  931. endp
  932.  
  933. align 4
  934. proc SetBufferPan stdcall, str:dword,pan:dword
  935.  
  936.            mov edx, [str]
  937.            stdcall set_vol_param,[edx+STREAM.l_vol],\
  938.                                  [edx+STREAM.r_vol],[pan]
  939.            ret
  940. endp
  941.  
  942. ; for static and ring buffers only
  943.  
  944. align 4
  945. proc play_buffer stdcall, str:dword, flags:dword
  946.  
  947.            mov ebx, [str]
  948.            mov eax, [ebx+STREAM.format]
  949.            test eax, PCM_OUT
  950.            jnz .fail
  951.  
  952.            cmp ax, PCM_ALL
  953.            je .fail
  954.  
  955.            mov [ebx+STREAM.flags], SND_PLAY
  956.            cmp [eng_state], SND_PLAY
  957.            je .done
  958.  
  959.            stdcall  dev_play, [hSound]
  960.            mov [eng_state], SND_PLAY
  961. .done:
  962.            test [flags], PLAY_SYNC
  963.            jz @F
  964.  
  965.            mov edx, [str]
  966. .wait:
  967.            mov eax, [edx+STREAM.notify_event]
  968.            mov ebx, [edx+STREAM.notify_id]
  969.            call WaitEvent   ;eax ebx
  970.  
  971.            mov edx, [str]
  972.            cmp [edx+STREAM.flags], SND_STOP
  973.            jne .wait
  974. @@:
  975.            xor eax, eax
  976.            ret
  977. .fail:
  978.            or eax, -1
  979.            ret
  980. endp
  981.  
  982. ; for static and ring buffers only
  983.  
  984. align 4
  985. proc stop_buffer stdcall, str:dword
  986.  
  987.            mov edx, [str]
  988.            test [edx+STREAM.format], PCM_STATIC+PCM_RING
  989.            jz .fail
  990.  
  991.            mov [edx+STREAM.flags], SND_STOP
  992.  
  993. ;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
  994.  
  995.            mov eax, [edx+STREAM.notify_event]
  996.            mov ebx, [edx+STREAM.notify_id]
  997.            call ClearEvent   ;eax ebx
  998.  
  999.            xor eax, eax
  1000.            ret
  1001. .fail:
  1002.            or eax, -1
  1003.            ret
  1004. endp
  1005.  
  1006. ; param
  1007. ;  eax= mix_list
  1008.  
  1009. align 4
  1010. do_mix_list:
  1011.  
  1012.            xor edx, edx
  1013.            mov esi, str.fd-FD_OFFSET
  1014.            mov ebx, [esi+STREAM.str_fd]
  1015. @@:
  1016.            cmp ebx, esi
  1017.            je .done
  1018.  
  1019.            cmp [ebx+STREAM.magic], 'WAVE'
  1020.            jne .next
  1021.  
  1022.            cmp [ebx+STREAM.size], STREAM_SIZE
  1023.            jne .next
  1024.  
  1025.            cmp [ebx+STREAM.flags], SND_PLAY;
  1026.            jne .next
  1027.  
  1028.            mov ecx, [ebx+STREAM.out_count]
  1029.            test ecx, ecx
  1030.            jnz .l1
  1031.  
  1032.            test [ebx+STREAM.format], PCM_RING
  1033.            jnz .next
  1034.            mov [ebx+STREAM.flags], SND_STOP
  1035.            jmp .next
  1036. .l1:
  1037.            cmp ecx, 512
  1038.            jae .add_buff
  1039.  
  1040.            mov edi, [ebx+STREAM.out_rp]
  1041.            add edi, ecx
  1042.            sub ecx, 512
  1043.            neg ecx
  1044.            push eax
  1045.            xor eax, eax
  1046.            cld
  1047.            rep stosb
  1048.            pop eax
  1049.  
  1050.            mov [ebx+STREAM.out_count], 512
  1051.  
  1052. .add_buff:
  1053.            mov ecx, [ebx+STREAM.out_rp]
  1054.            mov [eax],ecx
  1055.  
  1056. if USE_SSE2_MIXER
  1057.            mov edi, dword [ebx+STREAM.l_amp_f]
  1058.            mov [eax+4], edi
  1059.            mov edi, dword [ebx+STREAM.r_amp_f]
  1060.            mov [eax+8], edi
  1061. else
  1062.            mov edi, dword [ebx+STREAM.l_amp]
  1063.            mov [eax+4], edi
  1064. end if
  1065.            add [ebx+STREAM.out_rp], 512
  1066.            sub [ebx+STREAM.out_count], 512
  1067.  
  1068.            add eax, 12
  1069.            inc edx
  1070. .next:
  1071.            mov ebx, [ebx+STREAM.str_fd]
  1072.            jmp @B
  1073. .done:
  1074.            mov eax, edx
  1075.            ret
  1076.  
  1077. align 4
  1078. prepare_playlist:
  1079.  
  1080.            xor edx, edx
  1081.            mov [play_count], edx
  1082.            mov esi, str.fd-FD_OFFSET
  1083.            mov edi, [esi+STREAM.str_fd]
  1084. @@:
  1085.            cmp edi, esi
  1086.            je .done
  1087.  
  1088.            cmp [edi+STREAM.magic], 'WAVE'
  1089.            jne .next
  1090.  
  1091.            cmp [edi+STREAM.size], STREAM_SIZE
  1092.            jne .next
  1093.  
  1094.            cmp [edi+STREAM.flags], SND_PLAY;
  1095.            jne .next
  1096.  
  1097.            mov [play_list+edx], edi
  1098.            inc [play_count]
  1099.            add edx, 4
  1100. .next:
  1101.            mov edi, [edi+STREAM.str_fd]
  1102.            jmp @B
  1103. .done:
  1104.            ret
  1105.  
  1106. align 4
  1107. proc set_handler stdcall, hsrv:dword, handler_proc:dword
  1108.            locals
  1109.              handler    dd ?
  1110.              io_code    dd ?
  1111.              input      dd ?
  1112.              inp_size   dd ?
  1113.              output     dd ?
  1114.              out_size   dd ?
  1115.              val        dd ?
  1116.            endl
  1117.  
  1118.            mov eax, [hsrv]
  1119.            lea ecx, [handler_proc]
  1120.            xor ebx, ebx
  1121.  
  1122.            mov [handler], eax
  1123.            mov [io_code], DEV_CALLBACK
  1124.            mov [input], ecx
  1125.            mov [inp_size], 4
  1126.            mov [output], ebx
  1127.            mov [out_size], 0
  1128.  
  1129.            lea eax, [handler]
  1130.            stdcall ServiceHandler, eax
  1131.            ret
  1132. endp
  1133.  
  1134. align 4
  1135. proc dev_play stdcall, hsrv:dword
  1136.            locals
  1137.              handle     dd ?
  1138.              io_code    dd ?
  1139.              input      dd ?
  1140.              inp_size   dd ?
  1141.              output     dd ?
  1142.              out_size   dd ?
  1143.              val        dd ?
  1144.            endl
  1145.  
  1146.            mov eax, [hsrv]
  1147.            xor ebx, ebx
  1148.  
  1149.            mov [handle], eax
  1150.            mov [io_code], DEV_PLAY
  1151.            mov [input], ebx
  1152.            mov [inp_size], ebx
  1153.            mov [output], ebx
  1154.            mov [out_size], ebx
  1155.  
  1156.            lea eax, [handle]
  1157.            stdcall ServiceHandler, eax
  1158.            ret
  1159. endp
  1160.  
  1161. if 0
  1162. align 4
  1163. dword2str:
  1164.       mov  esi, hex_buff
  1165.       mov ecx, -8
  1166. @@:
  1167.       rol eax, 4
  1168.       mov ebx, eax
  1169.       and ebx, 0x0F
  1170.       mov bl, [ebx+hexletters]
  1171.       mov [8+esi+ecx], bl
  1172.       inc ecx
  1173.       jnz @B
  1174.       ret
  1175.  
  1176. hexletters   db '0123456789ABCDEF'
  1177. hex_buff     db 8 dup(0),13,10,0
  1178.  
  1179. end if
  1180.  
  1181. include 'mixer.asm'
  1182. include 'mix_mmx.inc'
  1183. include 'mix_sse2.inc'
  1184.  
  1185. ;if USE_SSE
  1186. ; include 'mix_sse.inc'
  1187. ;end if
  1188.  
  1189. align 16
  1190. resampler_params:
  1191.      ;r_size    r_dt   resampler_func
  1192.      dd 0,0,0                                  ; 0  PCM_ALL
  1193.      dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
  1194.      dd  8192,      0, m16_stereo     ; 2  PCM_1_16_48
  1195.  
  1196.      dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
  1197.      dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
  1198.  
  1199.      dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
  1200.      dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
  1201.  
  1202.      dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
  1203.      dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
  1204.  
  1205.      dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
  1206.      dd  4096,  15052, resample_1     ;10  PCM_1_16_22
  1207.  
  1208.      dd  8192,  10923, resample_2     ;11  PCM_2_16_16
  1209.      dd  4096,  10923, resample_1     ;12  PCM_1_16_16
  1210.  
  1211.      dd  8192,   8192, resample_2     ;13  PCM_2_16_12
  1212.      dd  4096,   8192, resample_1     ;14  PCM_1_16_12
  1213.  
  1214.      dd  4096,   7527, resample_2     ;15  PCM_2_16_11
  1215.      dd  2048,   7527, resample_1     ;16  PCM_1_16_11
  1216.  
  1217.      dd  4096,   5462, resample_2     ;17  PCM_2_16_8
  1218.      dd  2048,   5462, resample_1     ;18  PCM_1_16_8
  1219.  
  1220.      dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
  1221.      dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
  1222.  
  1223.      dd  8192,  30109, resample_28    ;21  PCM_2_8_44
  1224.      dd  4096,  30109, resample_18    ;22  PCM_1_8_44
  1225.  
  1226.      dd  8192,  21846, resample_28    ;23  PCM_2_8_32
  1227.      dd  4096,  21846, resample_18    ;24  PCM_1_8_32
  1228.  
  1229.      dd  8192,  16384, resample_28    ;25  PCM_2_8_24
  1230.      dd  4096,  16384, resample_18    ;26  PCM_1_8_24
  1231.  
  1232.      dd  4096,  15052, resample_28    ;27  PCM_2_8_22
  1233.      dd  2048,  15052, resample_18    ;28  PCM_1_8_22
  1234.  
  1235.      dd  4096,  10923, resample_28    ;29  PCM_2_8_16
  1236.      dd  2048,  10923, resample_18    ;30  PCM_1_8_16
  1237.  
  1238.      dd  4096,   8192, resample_28    ;31  PCM_2_8_12
  1239.      dd  2048,   8192, resample_18    ;32  PCM_1_8_12
  1240.  
  1241.      dd  2048,   7527, resample_28    ;33  PCM_2_8_11
  1242.      dd  1024,   7527, resample_18    ;34  PCM_1_8_11
  1243.  
  1244.      dd  2048,   5462, resample_28    ;35  PCM_2_8_8
  1245.      dd  1024,   5462, resample_18    ;36  PCM_1_8_8
  1246.  
  1247. m7            dw 0x8000,0x8000,0x8000,0x8000
  1248. mm80          dq 0x8080808080808080
  1249. mm_mask       dq 0xFF00FF00FF00FF00
  1250.  
  1251. vol_max       dd 0x00000000,0x00000000
  1252. vol_min       dd 0x0000D8F0,0x0000D8F0
  1253. pan_max       dd 0x00002710,0x00002710
  1254.  
  1255. ;stream_map    dd 0xFFFF       ; 16
  1256. version       dd (5 shl 16) or SOUND_VERSION
  1257.  
  1258. szInfinity    db 'INFINITY',0
  1259. szSound       db 'SOUND',0
  1260.  
  1261. if DEBUG
  1262. msgFail       db 'Sound service not loaded',13,10,0
  1263. msgPlay       db 'Play buffer',13,10,0
  1264. msgStop       db 'Stop',13,10,0
  1265. msgUser       db 'User callback',13,10,0
  1266. msgMem        db 'Not enough memory',13,10,0
  1267. msgDestroy    db 'Destroy sound buffer', 13,10,0
  1268. msgWaveout    db 'Play waveout', 13,10,0
  1269. msgSetVolume  db 'Set volume',13,10,0
  1270. end if
  1271.  
  1272. section '.data' data readable writable align 16
  1273.  
  1274. play_list     rd 16
  1275. mix_input     rd 16
  1276. play_count    rd 1
  1277. hSound        rd 1
  1278. eng_state     rd 1
  1279. mix_buff      rd 1
  1280. mix_buff_map  rd 1
  1281. str.fd        rd 1
  1282. str.bk        rd 1
  1283.  
  1284. mix_2_core    rd 1
  1285. mix_3_core    rd 1
  1286. mix_4_core    rd 1
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292.  
  1293.