Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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