Subversion Repositories Kolibri OS

Rev

Rev 568 | 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,edx,[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,edx,[ebx+4]
  217.            ret
  218. @@:
  219.            cmp eax, SND_SETPOS
  220.            jne @F
  221.            stdcall SetBufferPos,edx,[ebx+4]
  222.            ret
  223. @@:
  224.            cmp eax, SND_GETPOS
  225.            jne @F
  226.            stdcall GetBufferPos, edx
  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, edx,eax,[ebx+8],[ebx+12]
  237.            ret
  238. @@:
  239.            cmp eax, SND_SETVOLUME
  240.            jne @F
  241.            stdcall SetBufferVol,edx,[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,edx,ecx,eax
  251.            ret
  252. @@:
  253.            cmp eax, SND_SETPAN
  254.            jne @F
  255.            stdcall SetBufferPan,edx,[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, edx,eax,[ebx+8]
  272.            ret
  273. @@:
  274.            cmp eax, SND_PLAY
  275.            jne @F
  276.  
  277.            stdcall play_buffer, edx,[ebx+4]
  278.            ret
  279. @@:
  280.            cmp eax, SND_STOP
  281.            jne @F
  282.  
  283.            stdcall stop_buffer, edx
  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.            cmp eax, SND_GETFREESPACE
  296.            jne @F
  297.  
  298.            test [edx+STREAM.format], PCM_OUT
  299.            jz .fail
  300.  
  301.            mov ebx, [edx+STREAM.in_free]
  302.            mov ecx, [edi+output]
  303.            mov [ecx], ebx
  304.            xor eax, eax
  305.            ret
  306. @@:
  307. .fail:
  308.            or eax, -1
  309.            ret
  310. endp
  311.  
  312. restore   handle
  313. restore   io_code
  314. restore   input
  315. restore   inp_size
  316. restore   output
  317. restore   out_size
  318.  
  319. align 4
  320. proc CreateBuffer stdcall, format:dword, size:dword
  321.            locals
  322.              str         dd ?
  323.              ring_size   dd ?
  324.              ring_pages  dd ?
  325.            endl
  326.  
  327.            mov eax, [format]
  328.            cmp ax, PCM_1_8_8
  329.            ja .fail
  330.  
  331.            test eax, PCM_OUT
  332.            jnz .test_out
  333.            test eax, PCM_RING
  334.            jnz .test_ring
  335. ;staic
  336.            test eax, PCM_STATIC
  337.            jz .test_out                   ;use PCM_OUT as default format
  338.            jmp .test_ok
  339. .test_out:
  340.            test eax, PCM_RING+PCM_STATIC
  341.            jnz .fail
  342.            or [format], PCM_OUT           ;force set
  343.            jmp .test_ok
  344. .test_ring:
  345.            test eax, PCM_OUT+PCM_STATIC
  346.            jnz .fail
  347. .test_ok:
  348.  
  349.            call GetPid
  350.            mov ebx, eax
  351.            mov eax, STREAM_SIZE
  352.  
  353.            call CreateObject
  354.            test eax, eax
  355.            jz .fail
  356.            mov [str], eax
  357.  
  358.            mov ebx, [format]
  359.            mov [eax+STREAM.format], ebx
  360.  
  361.            xor ecx, ecx
  362.            movzx ebx, bx
  363.            cmp ebx, 19
  364.            jb @f
  365.            mov ecx, 0x80808080
  366. @@:
  367.            mov [eax+STREAM.r_silence], ecx
  368.  
  369.            shl ebx, 2
  370.            lea ebx, [ebx+ebx*2]     ;ebx*=12
  371.  
  372.            mov ecx, [resampler_params+ebx]
  373.            mov edx, [resampler_params+ebx+4]
  374.            mov esi, [resampler_params+ebx+8]
  375.  
  376.            mov [eax+STREAM.r_size],ecx
  377.            mov [eax+STREAM.r_dt],  edx
  378.            mov [eax+STREAM.resample], esi
  379.            xor ecx, ecx
  380.            mov [eax+STREAM.l_vol], ecx
  381.            mov [eax+STREAM.r_vol], ecx
  382.            mov dword [eax+STREAM.l_amp], 0x7FFF7FFF
  383.            mov [eax+STREAM.pan], ecx
  384.  
  385.            test [format], PCM_STATIC
  386.            jnz .static
  387.  
  388. ; ring and waveout
  389.  
  390.            mov ebx, 0x10000
  391.            test [format], PCM_RING
  392.            jz .waveout
  393.  
  394.            mov ebx, [eax+STREAM.r_size]
  395.            add ebx, 4095
  396.            and ebx, -4096
  397.            add ebx, ebx
  398. .waveout:
  399.            mov [ring_size], ebx
  400.            mov eax, ebx
  401.            shr ebx, 12
  402.            mov [ring_pages], ebx
  403.  
  404.            stdcall CreateRingBuffer, eax, PG_SW
  405.  
  406.            mov edi, [str]
  407.            mov ecx, [ring_size]
  408.            mov [edi+STREAM.in_base], eax
  409.            mov [edi+STREAM.in_size], ecx
  410.            add eax, 128
  411.         ;   sub ecx, 128
  412.            mov [edi+STREAM.in_wp], eax
  413.            mov [edi+STREAM.in_rp], eax
  414.            mov [edi+STREAM.in_count], 0
  415.  
  416.            mov [edi+STREAM.in_free], ecx
  417.            add eax, ecx
  418.            mov [edi+STREAM.in_top], eax
  419.  
  420.            jmp .out_buff
  421. .static:
  422.            mov ecx, [size]
  423.            add ecx, 128          ;resampler required
  424.            mov [eax+STREAM.in_size], ecx
  425.            stdcall KernelAlloc, ecx
  426.  
  427.            mov edi, [str]
  428.            mov [edi+STREAM.in_base], eax
  429.            add eax, 128
  430.            mov [edi+STREAM.in_wp], eax
  431.            mov [edi+STREAM.in_rp], eax
  432.            mov ebx, [size]
  433.            mov [edi+STREAM.in_count], ebx
  434.            mov [edi+STREAM.in_free], ebx
  435.            add eax, ebx
  436.            mov [edi+STREAM.in_top], eax
  437.  
  438. .out_buff:
  439.            stdcall AllocKernelSpace, dword 128*1024
  440.  
  441.            mov edi, [str]
  442.            mov [edi+STREAM.out_base], eax
  443.            mov [edi+STREAM.out_wp], eax
  444.            mov [edi+STREAM.out_rp], eax
  445.            mov [edi+STREAM.out_count], 0
  446.            add eax, 64*1024
  447.            mov [edi+STREAM.out_top], eax
  448.  
  449.            stdcall AllocPages, dword 64/4
  450.            mov edi, [str]
  451.            mov ebx, [edi+STREAM.out_base]
  452.            mov ecx, 16
  453.            or eax, PG_SW
  454.            push eax
  455.            push ebx
  456.            call CommitPages ;eax, ebx, ecx
  457.            mov ecx, 16
  458.            pop ebx
  459.            pop eax
  460.            add ebx, 64*1024
  461.            call CommitPages    ;double mapped
  462.  
  463.            mov edi, [str]
  464.            mov ecx, [edi+STREAM.in_top]
  465.            mov edi, [edi+STREAM.in_base]
  466.            sub ecx, edi
  467.            xor eax, eax
  468.            shr ecx, 2
  469.            cld
  470.            rep stosd
  471.  
  472.            mov edi, [str]
  473.            mov edi, [edi+STREAM.out_base]
  474.            mov ecx, (64*1024)/4
  475.            rep stosd
  476.  
  477.            xor edx, edx
  478.            mov ebx, MANUAL_DESTROY
  479.            call CreateEvent
  480.  
  481.            mov ebx, [str]
  482.            mov [ebx+STREAM.notify_event], eax
  483.            mov [ebx+STREAM.notify_id], edx
  484.  
  485.            mov [ebx+STREAM.magic], 'WAVE'
  486.            mov [ebx+STREAM.destroy], DestroyBuffer.destroy
  487.            mov [ebx+STREAM.size], STREAM_SIZE
  488.            mov [ebx+STREAM.flags], SND_STOP
  489.  
  490.            pushf
  491.            cli
  492.            mov eax, str.fd-FD_OFFSET
  493.            mov edx, [eax+STREAM.str_fd]
  494.            mov [ebx+STREAM.str_fd], edx
  495.            mov [ebx+STREAM.str_bk], eax
  496.            mov [eax+STREAM.str_fd], ebx
  497.            mov [edx+STREAM.str_bk], ebx
  498.            popf
  499.  
  500.            xor eax, eax
  501.            ret
  502. .fail:
  503.            xor ebx, ebx
  504.            or eax, -1
  505.            ret
  506. endp
  507.  
  508. ;param
  509. ; eax= buffer handle
  510.  
  511. align 4
  512. DestroyBuffer:
  513.            .handle  equ esp       ;local
  514.  
  515.            mov [eax+STREAM.flags], SND_STOP
  516. .destroy:
  517.            push eax
  518.  
  519.            pushfd
  520.            cli
  521.            mov ebx, [eax+STREAM.str_fd]
  522.            mov ecx, [eax+STREAM.str_bk]
  523.            mov [ebx+STREAM.str_bk], ecx
  524.            mov [ecx+STREAM.str_fd], ebx
  525.            popf
  526.  
  527.            stdcall KernelFree, [eax+STREAM.in_base]
  528.            mov eax, [.handle]
  529.            stdcall KernelFree, [eax+STREAM.out_base]
  530.  
  531.            pop eax               ;restore stack
  532.            call DestroyObject    ;eax= stream
  533.            xor eax, eax
  534.            ret
  535. .fail:
  536.            or eax, -1
  537.            ret
  538. restore .handle
  539.  
  540. align 4
  541. proc SetFormat stdcall, str:dword, format:dword
  542.  
  543.            cmp word [format], PCM_1_8_8
  544.            ja .fail
  545.  
  546.            mov edx, [str]
  547.            mov [edx+STREAM.flags], SND_STOP
  548.  
  549.            test [edx+STREAM.format], PCM_RING
  550.            jnz .fail
  551.  
  552. ;           mov eax,[edx+STREAM.out_base]
  553. ;           mov [edx+STREAM.out_wp], eax
  554. ;           mov [edx+STREAM.out_rp], eax
  555. ;           mov [edx+STREAM.out_count], 0
  556.  
  557.            movzx eax, word [format]
  558.            mov word [edx+STREAM.format], ax
  559.  
  560.            xor ebx, ebx
  561.            cmp eax, 19
  562.            jb @f
  563.            mov ebx, 0x80808080
  564. @@:
  565.            mov [edx+STREAM.r_silence], ebx
  566.  
  567.            shl eax, 2
  568.            lea eax, [eax+eax*2]     ;eax*=12
  569.  
  570.            mov edi, [resampler_params+eax]
  571.            mov ecx, [resampler_params+eax+4]
  572.            mov ebx, [resampler_params+eax+8]
  573.  
  574.            mov [edx+STREAM.r_size],edi
  575.            mov [edx+STREAM.r_dt],  ecx
  576.            mov [edx+STREAM.resample], ebx
  577.  
  578.            mov edi, [edx+STREAM.in_base]
  579.            mov ecx, 128/4
  580.            mov eax, [edx+STREAM.r_silence]
  581.            cld
  582.            rep stosd
  583.            xor eax, eax
  584.            ret
  585. .fail:
  586.            or eax, -1
  587.            ret
  588. endp
  589.  
  590. ; for static buffers only
  591. ; use waveout for streams
  592.  
  593. align 4
  594. proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
  595.  
  596.            mov edx, [str]
  597.            test [edx+STREAM.format], PCM_OUT
  598.            jnz .fail
  599.  
  600.            mov esi, [src]
  601.            mov edi, [offs]
  602.            add edi, [edx+STREAM.in_base]
  603.            add edi, 128
  604.  
  605.            cmp edi, [edx+STREAM.in_top]
  606.            jae .fail
  607.  
  608.            mov ecx, [size]
  609.            lea ebx, [ecx+edi]
  610.            sub ebx, [edx+STREAM.in_top]
  611.            jb @F
  612.            sub ecx, ebx
  613. @@:
  614.            shr ecx, 2
  615.            cld
  616.            rep movsd
  617.            xor eax,eax
  618.            ret
  619. .fail:
  620.            or eax, -1
  621.            ret
  622. endp
  623.  
  624. ; for stream buffers only
  625.  
  626. align 4
  627. proc wave_out stdcall, str:dword,src:dword,size:dword
  628.            locals
  629.              state_saved  dd ?
  630.              fpu_state    rb 528
  631.            endl
  632.  
  633.            mov edx, [str]
  634.            mov eax, [edx+STREAM.format]
  635.            test eax, PCM_OUT
  636.            jz .fail
  637.  
  638.            cmp ax, PCM_ALL
  639.            je .fail
  640.  
  641.            mov esi,[src]
  642.            test esi, esi
  643.            jz .fail
  644.  
  645.            cmp esi, OS_BASE
  646.            ja .fail
  647.  
  648.            mov [state_saved], 0
  649.  
  650. .main_loop:
  651.            mov edx, [str]
  652.  
  653.            mov ebx, [size]
  654.            test ebx, ebx
  655.            jz .done
  656.  
  657.            cmp [edx+STREAM.flags], SND_STOP
  658.            jne .fill
  659.  
  660.            mov edi, [edx+STREAM.in_base]
  661.            mov ecx, 128/4
  662.            mov eax, [edx+STREAM.r_silence]
  663.            cld
  664.            rep stosd
  665.  
  666.            mov ecx, [edx+STREAM.in_size]
  667.            sub ecx, 128
  668.            mov [edx+STREAM.in_wp], edi
  669.            mov [edx+STREAM.in_rp], edi
  670.            mov [edx+STREAM.in_count], 0
  671.            mov [edx+STREAM.in_free], ecx
  672.  
  673.            mov eax,[edx+STREAM.out_base]
  674.            mov [edx+STREAM.out_wp], eax
  675.            mov [edx+STREAM.out_rp], eax
  676.            mov [edx+STREAM.out_count], 0
  677. .fill:
  678.            mov ecx, [edx+STREAM.in_free]
  679.            test ecx, ecx
  680.            jz .wait
  681.  
  682.            cmp ecx, ebx
  683.            jbe @F
  684.  
  685.            mov ecx, ebx
  686. @@:
  687.            sub [size], ecx
  688.            add [edx+STREAM.in_count], ecx
  689.            sub [edx+STREAM.in_free], ecx
  690.  
  691.            shr ecx, 2
  692.            mov edi, [edx+STREAM.in_wp]
  693.            mov esi, [src]
  694.            cld
  695.            rep movsd
  696.  
  697.            mov [src], esi
  698.            cmp edi, [edx+STREAM.in_top]
  699.            jb @F
  700.            sub edi, [edx+STREAM.in_size]
  701. @@:
  702.            mov [edx+STREAM.in_wp], edi
  703.  
  704.            cmp [edx+STREAM.out_count], 32768
  705.            jae .skip
  706.  
  707.            cmp [state_saved], 0
  708.            jne @F
  709.            lea eax, [fpu_state+15]
  710.            and eax, -16
  711.            call FpuSave
  712.            mov [state_saved], 1
  713. @@:
  714.            stdcall refill, edx
  715. .skip:
  716.            mov ebx, [str]
  717.            mov [ebx+STREAM.flags], SND_PLAY
  718.            cmp [eng_state], SND_PLAY
  719.            je .main_loop
  720.  
  721.            stdcall dev_play, [hSound]
  722.            mov [eng_state], SND_PLAY
  723.            jmp .main_loop
  724. .wait:
  725.            mov edx, [str]
  726.            mov eax, [edx+STREAM.notify_event]
  727.            mov ebx, [edx+STREAM.notify_id]
  728.            call WaitEvent   ;eax ebx
  729.            jmp .main_loop
  730. .done:
  731.            cmp [state_saved], 1
  732.            jne @F
  733.  
  734.            lea eax, [fpu_state+15]
  735.            and eax, -16
  736.            call FpuRestore
  737. @@:
  738.            xor eax, eax
  739.            ret
  740. .fail:
  741.            or eax, -1
  742.            ret
  743. endp
  744.  
  745. ; both static and stream
  746. ; reset all but not clear buffers
  747.  
  748.  
  749. ; flags reserved
  750. ;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
  751. ;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
  752. ;  RESET_ALL    equ 3
  753.  
  754.  
  755. align 4
  756. proc ResetBuffer stdcall, str:dword, flags:dword
  757.  
  758.            mov edx, [str]
  759.            mov [edx+STREAM.flags], SND_STOP
  760.  
  761.            mov edi, [edx+STREAM.in_base]
  762.            mov ecx, 128/4
  763.            mov eax, [edx+STREAM.r_silence]
  764.            cld
  765.            rep stosd
  766.  
  767.            mov [edx+STREAM.in_wp], edi
  768.            mov [edx+STREAM.in_rp], edi
  769.  
  770.            test [edx+STREAM.flags], PCM_STATIC
  771.            jnz .static
  772.            mov [edx+STREAM.in_count], 0
  773.            jmp @F
  774. .static:
  775.            mov eax, [edx+STREAM.in_size]
  776.            mov [edx+STREAM.in_count], eax
  777. @@:
  778.  
  779.            mov eax, [edx+STREAM.in_size]
  780.            sub eax, 128
  781.            mov [edx+STREAM.in_free], eax
  782.  
  783.            xor eax, eax
  784.            mov ebx,[edx+STREAM.out_base]
  785.            mov [edx+STREAM.out_wp], ebx
  786.            mov [edx+STREAM.out_rp], ebx
  787.            mov [edx+STREAM.out_count], eax
  788.            ret
  789. .fail:
  790.            or eax, -1
  791.            ret
  792. endp
  793.  
  794. ; for static buffers only
  795.  
  796. align 4
  797. proc SetBufferPos stdcall, str:dword, pos:dword
  798.  
  799.            mov edx, [str]
  800.            test [edx+STREAM.format], PCM_STATIC
  801.            jz .fail
  802.  
  803.            mov [edx+STREAM.flags], SND_STOP
  804.  
  805.            mov eax, [pos]
  806.            add eax, [edx+STREAM.in_base]
  807.            mov ebx, [edx+STREAM.in_top]
  808.            add eax, 128
  809.  
  810.            cmp eax, ebx
  811.            jae .fail
  812.  
  813.            mov [edx+STREAM.in_rp], eax
  814.            sub ebx, eax
  815.            mov [edx+STREAM.in_count], ebx
  816.            xor eax, eax
  817.            ret
  818. .fail:
  819.            or eax, -1
  820.            ret
  821. endp
  822.  
  823. align 4
  824. proc GetBufferPos stdcall, str:dword
  825.  
  826.            mov edx, [str]
  827.            test [edx+STREAM.format], PCM_STATIC
  828.            jz .fail
  829.  
  830.            mov ebx, [edx+STREAM.in_rp]
  831.            sub ebx, [edx+STREAM.in_base]
  832.            sub ebx, 128
  833.            xor eax, eax
  834.            ret
  835. .fail:
  836.            xor ebx,ebx
  837.            or eax, -1
  838.            ret
  839. endp
  840.  
  841. ; both
  842.  
  843. align 4
  844. proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
  845.  
  846.            mov edx, [str]
  847.            stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
  848.            ret
  849. endp
  850.  
  851. proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
  852.            locals
  853.              _600    dd ?
  854.              _32767  dd ?
  855.              state   rb 108
  856.            endl
  857.  
  858.            mov [_600], 0x44160000   ;600.0
  859.            mov [_32767], 32767
  860.  
  861.            lea ebx, [state]
  862.            fnsave [ebx]
  863.  
  864.            movq mm0, qword [l_vol]
  865.            pminsw mm0, qword [vol_max]
  866.            pmaxsw mm0, qword [vol_min]
  867.            movq qword [l_vol], mm0
  868.            movq qword [edx+STREAM.l_vol], mm0
  869.  
  870.            movd mm1,[pan]
  871.            pminsw mm1, qword [pan_max]
  872.            pmaxsw mm1, qword [vol_min]
  873.            movd [edx+STREAM.pan], mm1
  874.  
  875.            cmp word [edx+STREAM.pan], 0
  876.            jl @F
  877.  
  878.            psubsw mm0,mm1
  879.            pminsw mm0, qword [vol_max]
  880.            pmaxsw mm0, qword [vol_min]
  881.            movd [l_vol],mm0
  882.            jmp .calc_amp
  883. @@:
  884.            punpckhdq mm0,mm0
  885.            paddsw mm0,mm1
  886.            pminsw mm0, qword [vol_max]
  887.            pmaxsw mm0, qword [vol_min]
  888.            movd [r_vol], mm0
  889. .calc_amp:
  890.            emms
  891.            fild word [l_vol]
  892.  
  893.            call .calc
  894.  
  895.            fistp word [edx+STREAM.l_amp]
  896.            fstp st0
  897.  
  898.            fild word [r_vol]
  899.  
  900.            call .calc
  901.  
  902.            fistp word [edx+STREAM.r_amp]
  903.            fstp st0
  904.  
  905.            fnclex
  906.            lea ebx, [state]
  907.            frstor [ebx]
  908.  
  909.            xor eax, eax
  910.            inc eax
  911.            ret
  912. .calc:
  913.            fdiv dword [_600]
  914.            fld st0
  915.            frndint
  916.            fxch st1
  917.            fsub st, st1
  918.            f2xm1
  919.            fld1
  920.            faddp st1, st0
  921.            fscale
  922.            fimul dword [_32767]
  923.            ret 0
  924. endp
  925.  
  926. align 4
  927. proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
  928.  
  929.            mov edx, [str]
  930.            mov eax, [p_lvol]
  931.            movsx ecx, word [edx+STREAM.l_vol]
  932.            mov [eax], ecx
  933.  
  934.            mov eax, [p_rvol]
  935.            movsx ecx, word [edx+STREAM.r_vol]
  936.            mov [eax], ecx
  937.            xor eax, eax
  938.            ret
  939. endp
  940.  
  941. align 4
  942. proc SetBufferPan stdcall, str:dword,pan:dword
  943.  
  944.            mov edx, [str]
  945.            stdcall set_vol_param,[edx+STREAM.l_vol],\
  946.                                  [edx+STREAM.r_vol],[pan]
  947.            ret
  948. endp
  949.  
  950. ; for static and ring buffers only
  951.  
  952. align 4
  953. proc play_buffer stdcall, str:dword, flags:dword
  954.  
  955.            mov ebx, [str]
  956.            mov eax, [ebx+STREAM.format]
  957.            test eax, PCM_OUT
  958.            jnz .fail
  959.  
  960.            cmp ax, PCM_ALL
  961.            je .fail
  962.  
  963.            mov [ebx+STREAM.flags], SND_PLAY
  964.            cmp [eng_state], SND_PLAY
  965.            je .done
  966.  
  967.            stdcall  dev_play, [hSound]
  968.            mov [eng_state], SND_PLAY
  969. .done:
  970.            test [flags], PLAY_SYNC
  971.            jz @F
  972.  
  973.            mov edx, [str]
  974. .wait:
  975.            mov eax, [edx+STREAM.notify_event]
  976.            mov ebx, [edx+STREAM.notify_id]
  977.            call WaitEvent   ;eax ebx
  978.  
  979.            mov edx, [str]
  980.            cmp [edx+STREAM.flags], SND_STOP
  981.            jne .wait
  982. @@:
  983.            xor eax, eax
  984.            ret
  985. .fail:
  986.            or eax, -1
  987.            ret
  988. endp
  989.  
  990. ; for static and ring buffers only
  991.  
  992. align 4
  993. proc stop_buffer stdcall, str:dword
  994.  
  995.            mov edx, [str]
  996.            test [edx+STREAM.format], PCM_STATIC+PCM_RING
  997.            jz .fail
  998.  
  999.            mov [edx+STREAM.flags], SND_STOP
  1000.  
  1001. ;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
  1002.  
  1003.            mov eax, [edx+STREAM.notify_event]
  1004.            mov ebx, [edx+STREAM.notify_id]
  1005.            call ClearEvent   ;eax ebx
  1006.  
  1007.            xor eax, eax
  1008.            ret
  1009. .fail:
  1010.            or eax, -1
  1011.            ret
  1012. endp
  1013.  
  1014. ; parm
  1015. ;  eax= mix_list
  1016.  
  1017. align 4
  1018. do_mix_list:
  1019.  
  1020.            xor edx, edx
  1021.            mov esi, str.fd-FD_OFFSET
  1022.            mov ebx, [esi+STREAM.str_fd]
  1023. @@:
  1024.            cmp ebx, esi
  1025.            je .done
  1026.  
  1027.            cmp [ebx+STREAM.magic], 'WAVE'
  1028.            jne .next
  1029.  
  1030.            cmp [ebx+STREAM.size], STREAM_SIZE
  1031.            jne .next
  1032.  
  1033.            cmp [ebx+STREAM.flags], SND_PLAY;
  1034.            jne .next
  1035.  
  1036.            mov ecx, [ebx+STREAM.out_count]
  1037.            test ecx, ecx
  1038.            jnz .l1
  1039.  
  1040.            test [ebx+STREAM.format], PCM_RING
  1041.            jnz .next
  1042.            mov [ebx+STREAM.flags], SND_STOP
  1043.            jmp .next
  1044. .l1:
  1045.            cmp ecx, 512
  1046.            jae .add_buff
  1047.  
  1048.            mov edi, [ebx+STREAM.out_rp]
  1049.            add edi, ecx
  1050.            sub ecx, 512
  1051.            neg ecx
  1052.            push eax
  1053.            xor eax, eax
  1054.            cld
  1055.            rep stosb
  1056.            pop eax
  1057.  
  1058.            mov [ebx+STREAM.out_count], 512
  1059.  
  1060. .add_buff:
  1061.            mov ecx, [ebx+STREAM.out_rp]
  1062.            mov [eax],ecx
  1063.            mov edi, dword [ebx+STREAM.l_amp]
  1064.            mov [eax+4], edi
  1065.            add [ebx+STREAM.out_rp], 512
  1066.            sub [ebx+STREAM.out_count], 512
  1067.  
  1068.            add eax, 8
  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 16384,      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 and 0xFFFF)
  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.