Subversion Repositories Kolibri OS

Rev

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