Subversion Repositories Kolibri OS

Rev

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