Subversion Repositories Kolibri OS

Rev

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