Subversion Repositories Kolibri OS

Rev

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

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