Subversion Repositories Kolibri OS

Rev

Rev 1505 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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