Subversion Repositories Kolibri OS

Rev

Rev 1690 | 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.            pushfd
  363.            cli
  364.  
  365.            xor ebx, ebx
  366.            push 48
  367.            push ebx            ; local storage
  368.  
  369.            cmp [edx+STREAM.flags], SND_STOP
  370.            je @F
  371.  
  372.            mov eax, esp
  373.  
  374.            push edx
  375.            push edi
  376.  
  377.            push 4              ;.out_size
  378.            push eax            ;.output
  379.            push ebx            ;.inp_size
  380.            push ebx            ;.input
  381.            push DEV_GET_POS    ;.code
  382.            push dword [hSound] ;.handle
  383.            mov eax, esp
  384.  
  385.            stdcall ServiceHandler, eax
  386.            add esp, 6*4
  387.  
  388.            pop edi
  389.            pop edx
  390.  
  391.            test eax, eax
  392.            jz @F
  393.  
  394.            mov dword [esp], 0   ; clear offset
  395. @@:
  396.            mov edi, [edi+output]
  397.  
  398.            emms
  399.            fild  qword [edx+STREAM.time_stamp]
  400.            fiadd dword [esp]    ; primary buffer offset
  401.            fidiv dword [esp+4]  ; total_samples / frequency
  402.            fadd  qword [edx+STREAM.time_base]
  403.            fstp  qword [edi]
  404.            add esp, 8
  405.  
  406.            popfd
  407.  
  408.            xor eax, eax
  409.            ret
  410. endp
  411.  
  412.  
  413. restore   handle
  414. restore   io_code
  415. restore   input
  416. restore   inp_size
  417. restore   output
  418. restore   out_size
  419.  
  420. align 4
  421. proc CreateBuffer stdcall, format:dword, size:dword
  422.            locals
  423.              str         dd ?
  424.              ring_size   dd ?
  425.              ring_pages  dd ?
  426.            endl
  427.  
  428.            mov eax, [format]
  429.            cmp ax, PCM_1_8_8
  430.            ja .fail
  431.  
  432.            test eax, PCM_OUT
  433.            jnz .test_out
  434.            test eax, PCM_RING
  435.            jnz .test_ring
  436. ;staic
  437.            test eax, PCM_STATIC
  438.            jz .test_out                   ;use PCM_OUT as default format
  439.            jmp .test_ok
  440. .test_out:
  441.            test eax, PCM_RING+PCM_STATIC
  442.            jnz .fail
  443.            or [format], PCM_OUT           ;force set
  444.            jmp .test_ok
  445. .test_ring:
  446.            test eax, PCM_OUT+PCM_STATIC
  447.            jnz .fail
  448. .test_ok:
  449.  
  450.            call GetPid
  451.            mov ebx, eax
  452.            mov eax, STREAM.sizeof
  453.  
  454.            call CreateObject
  455.            test eax, eax
  456.            jz .fail
  457.            mov [str], eax
  458.  
  459.            mov ebx, [format]
  460.            mov [eax+STREAM.format], ebx
  461.  
  462.            xor ecx, ecx
  463.            movzx ebx, bx
  464.            cmp ebx, 19
  465.            jb @f
  466.            mov ecx, 0x80808080
  467. @@:
  468.            mov [eax+STREAM.r_silence], ecx
  469.  
  470.            shl ebx, 2
  471.            lea ebx, [ebx+ebx*2]     ;ebx*=12
  472.  
  473.            mov ecx, [resampler_params+ebx]
  474.            mov edx, [resampler_params+ebx+4]
  475.            mov esi, [resampler_params+ebx+8]
  476.  
  477.            mov [eax+STREAM.r_size],ecx
  478.            mov [eax+STREAM.r_dt],  edx
  479.            mov [eax+STREAM.resample], esi
  480.            xor ecx, ecx
  481.            mov [eax+STREAM.l_vol], ecx
  482.            mov [eax+STREAM.r_vol], ecx
  483.            mov dword [eax+STREAM.l_amp], 0x7FFF7FFF
  484.            mov [eax+STREAM.pan], ecx
  485.  
  486.            test [format], PCM_STATIC
  487.            jnz .static
  488.  
  489. ; ring and waveout
  490.  
  491.            mov ebx, 0x10000
  492.            test [format], PCM_RING
  493.            jz .waveout
  494.  
  495.            mov ebx, [eax+STREAM.r_size]
  496.            add ebx, 4095
  497.            and ebx, -4096
  498.            add ebx, ebx
  499. .waveout:
  500.            mov [ring_size], ebx
  501.            mov eax, ebx
  502.            shr ebx, 12
  503.            mov [ring_pages], ebx
  504.  
  505.            stdcall CreateRingBuffer, eax, PG_SW
  506.  
  507.            mov edi, [str]
  508.            mov ecx, [ring_size]
  509.            mov [edi+STREAM.in_base], eax
  510.            mov [edi+STREAM.in_size], ecx
  511.            add eax, 128
  512.            mov [edi+STREAM.in_wp], eax
  513.            mov [edi+STREAM.in_rp], eax
  514.            mov [edi+STREAM.in_count], 0
  515.  
  516.            mov [edi+STREAM.in_free], ecx
  517.            add eax, ecx
  518.            mov [edi+STREAM.in_top], eax
  519.  
  520.            jmp .out_buff
  521. .static:
  522.            mov ecx, [size]
  523.            add ecx, 128          ;resampler required
  524.            mov [eax+STREAM.in_size], ecx
  525.            stdcall KernelAlloc, ecx
  526.  
  527.            mov edi, [str]
  528.            mov [edi+STREAM.in_base], eax
  529.            add eax, 128
  530.            mov [edi+STREAM.in_wp], eax
  531.            mov [edi+STREAM.in_rp], eax
  532.            mov ebx, [size]
  533.            mov [edi+STREAM.in_count], ebx
  534.            mov [edi+STREAM.in_free], ebx
  535.            add eax, ebx
  536.            mov [edi+STREAM.in_top], eax
  537.  
  538. .out_buff:
  539.            stdcall AllocKernelSpace, dword 128*1024
  540.  
  541.            mov edi, [str]
  542.            xor ebx, ebx
  543.  
  544.            mov [edi+STREAM.out_base], eax
  545.            mov [edi+STREAM.out_wp], eax
  546.            mov [edi+STREAM.out_rp], eax
  547.            mov [edi+STREAM.out_count], ebx
  548.            add eax, 64*1024
  549.            mov [edi+STREAM.out_top], eax
  550.  
  551.            mov dword [edi+STREAM.time_base],   ebx
  552.            mov dword [edi+STREAM.time_base+4], ebx
  553.  
  554.            mov dword [edi+STREAM.time_stamp],   ebx
  555.            mov dword [edi+STREAM.time_stamp+4], ebx
  556.            mov dword [edi+STREAM.last_ts], ebx
  557.  
  558.            stdcall AllocPages, dword 64/4
  559.            mov edi, [str]
  560.            mov ebx, [edi+STREAM.out_base]
  561.            mov ecx, 16
  562.            or eax, PG_SW
  563.            push eax
  564.            push ebx
  565.            call CommitPages ;eax, ebx, ecx
  566.            mov ecx, 16
  567.            pop ebx
  568.            pop eax
  569.            add ebx, 64*1024
  570.            call CommitPages    ;double mapped
  571.  
  572.            mov edi, [str]
  573.            mov ecx, [edi+STREAM.in_top]
  574.            mov edi, [edi+STREAM.in_base]
  575.            sub ecx, edi
  576.            xor eax, eax
  577.            shr ecx, 2
  578.            cld
  579.            rep stosd
  580.  
  581.            mov edi, [str]
  582.            mov edi, [edi+STREAM.out_base]
  583.            mov ecx, (64*1024)/4
  584.            rep stosd
  585.  
  586.            xor esi, esi
  587.            mov ecx, MANUAL_DESTROY
  588.            call CreateEvent
  589.  
  590.            mov ebx, [str]
  591.            mov [ebx+STREAM.notify_event], eax
  592.            mov [ebx+STREAM.notify_id], edx
  593.  
  594.            mov [ebx+STREAM.magic], 'WAVE'
  595.            mov [ebx+STREAM.destroy], DestroyBuffer.destroy
  596.            mov [ebx+STREAM.size], STREAM.sizeof
  597.            mov [ebx+STREAM.flags], SND_STOP
  598.  
  599.            pushf
  600.            cli
  601.            mov eax, str.fd-FD_OFFSET
  602.            mov edx, [eax+STREAM.str_fd]
  603.            mov [ebx+STREAM.str_fd], edx
  604.            mov [ebx+STREAM.str_bk], eax
  605.            mov [eax+STREAM.str_fd], ebx
  606.            mov [edx+STREAM.str_bk], ebx
  607.            popf
  608.  
  609.            xor eax, eax
  610.            ret
  611. .fail:
  612.            xor ebx, ebx
  613.            or eax, -1
  614.            ret
  615. endp
  616.  
  617. ;param
  618. ; eax= buffer handle
  619.  
  620. align 4
  621. DestroyBuffer:
  622.            .handle  equ esp       ;local
  623.  
  624.            mov [eax+STREAM.flags], SND_STOP
  625. .destroy:
  626.            push eax
  627.  
  628.            pushfd
  629.            cli
  630.            mov ebx, [eax+STREAM.str_fd]
  631.            mov ecx, [eax+STREAM.str_bk]
  632.            mov [ebx+STREAM.str_bk], ecx
  633.            mov [ecx+STREAM.str_fd], ebx
  634.            popf
  635.  
  636.            stdcall KernelFree, [eax+STREAM.in_base]
  637.            mov eax, [.handle]
  638.            stdcall KernelFree, [eax+STREAM.out_base]
  639.  
  640.            pop eax               ;restore stack
  641.            call DestroyObject    ;eax= stream
  642.            xor eax, eax
  643.            ret
  644. .fail:
  645.            or eax, -1
  646.            ret
  647. restore .handle
  648.  
  649. align 4
  650. proc SetFormat stdcall, str:dword, format:dword
  651.  
  652.            cmp word [format], PCM_1_8_8
  653.            ja .fail
  654.  
  655.            mov edx, [str]
  656.            mov [edx+STREAM.flags], SND_STOP
  657.  
  658.            test [edx+STREAM.format], PCM_RING
  659.            jnz .fail
  660.  
  661. ;           mov eax,[edx+STREAM.out_base]
  662. ;           mov [edx+STREAM.out_wp], eax
  663. ;           mov [edx+STREAM.out_rp], eax
  664. ;           mov [edx+STREAM.out_count], 0
  665.  
  666.            movzx eax, word [format]
  667.            mov word [edx+STREAM.format], ax
  668.  
  669.            xor ebx, ebx
  670.            cmp eax, 19
  671.            jb @f
  672.            mov ebx, 0x80808080
  673. @@:
  674.            mov [edx+STREAM.r_silence], ebx
  675.  
  676.            shl eax, 2
  677.            lea eax, [eax+eax*2]     ;eax*=12
  678.  
  679.            mov edi, [resampler_params+eax]
  680.            mov ecx, [resampler_params+eax+4]
  681.            mov ebx, [resampler_params+eax+8]
  682.  
  683.            mov [edx+STREAM.r_size],edi
  684.            mov [edx+STREAM.r_dt],  ecx
  685.            mov [edx+STREAM.resample], ebx
  686.  
  687.            mov edi, [edx+STREAM.in_base]
  688.            mov ecx, 128/4
  689.            mov eax, [edx+STREAM.r_silence]
  690.            cld
  691.            rep stosd
  692.            xor eax, eax
  693.            ret
  694. .fail:
  695.            or eax, -1
  696.            ret
  697. endp
  698.  
  699. ; for static buffers only
  700. ; use waveout for streams
  701.  
  702. align 4
  703. proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
  704.  
  705.            mov edx, [str]
  706.            test [edx+STREAM.format], PCM_OUT
  707.            jnz .fail
  708.  
  709.            mov esi, [src]
  710.            mov edi, [offs]
  711.            add edi, [edx+STREAM.in_base]
  712.            add edi, 128
  713.  
  714.            cmp edi, [edx+STREAM.in_top]
  715.            jae .fail
  716.  
  717.            mov ecx, [size]
  718.            lea ebx, [ecx+edi]
  719.            sub ebx, [edx+STREAM.in_top]
  720.            jb @F
  721.            sub ecx, ebx
  722. @@:
  723.            shr ecx, 2
  724.            cld
  725.            rep movsd
  726.            xor eax,eax
  727.            ret
  728. .fail:
  729.            or eax, -1
  730.            ret
  731. endp
  732.  
  733. ; for stream buffers only
  734.  
  735. align 4
  736. proc wave_out stdcall, str:dword,src:dword,size:dword
  737.            locals
  738.              state_saved  dd ?
  739.              fpu_state    rb 528
  740.            endl
  741.  
  742.            mov edx, [str]
  743.            mov eax, [edx+STREAM.format]
  744.            test eax, PCM_OUT
  745.            jz .fail
  746.  
  747.            cmp ax, PCM_ALL
  748.            je .fail
  749.  
  750.            mov esi,[src]
  751.            test esi, esi
  752.            jz .fail
  753.  
  754.            cmp esi, OS_BASE
  755.            jae .fail
  756.  
  757.            mov [state_saved], 0
  758.  
  759. .main_loop:
  760.            mov edx, [str]
  761.  
  762.            mov ebx, [size]
  763.            test ebx, ebx
  764.            jz .done
  765.  
  766.            cmp [edx+STREAM.flags], SND_STOP
  767.            jne .fill
  768.  
  769.            mov edi, [edx+STREAM.in_base]
  770.            mov ecx, 128/4
  771.            mov eax, [edx+STREAM.r_silence]
  772.            cld
  773.            rep stosd
  774.  
  775.            mov ecx, [edx+STREAM.in_size]
  776.            sub ecx, 128
  777.            mov [edx+STREAM.in_wp], edi
  778.            mov [edx+STREAM.in_rp], edi
  779.            mov [edx+STREAM.in_count], 0
  780.            mov [edx+STREAM.in_free], ecx
  781.  
  782.            mov eax,[edx+STREAM.out_base]
  783.            mov [edx+STREAM.out_wp], eax
  784.            mov [edx+STREAM.out_rp], eax
  785.            mov [edx+STREAM.out_count], 0
  786. .fill:
  787.            cli
  788.  
  789.            mov ecx, [edx+STREAM.in_free]
  790.            test ecx, ecx
  791.            jz .wait
  792.  
  793.            cmp ecx, ebx
  794.            jbe @F
  795.  
  796.            mov ecx, ebx
  797. @@:
  798.            sub [size], ecx
  799.            add [edx+STREAM.in_count], ecx
  800.            sub [edx+STREAM.in_free], ecx
  801.  
  802.            shr ecx, 2
  803.            mov edi, [edx+STREAM.in_wp]
  804.            mov esi, [src]
  805.            cld
  806.            rep movsd
  807.  
  808.            mov [src], esi
  809.            cmp edi, [edx+STREAM.in_top]
  810.            jb @F
  811.            sub edi, [edx+STREAM.in_size]
  812. @@:
  813.            mov [edx+STREAM.in_wp], edi
  814.  
  815.            cmp [edx+STREAM.out_count], 32768
  816.            jae .skip
  817.  
  818.            cmp [state_saved], 0
  819.            jne @F
  820.            lea eax, [fpu_state+15]
  821.            and eax, -16
  822.            call FpuSave
  823.            mov [state_saved], 1
  824. @@:
  825.            stdcall refill, edx
  826.  
  827. .skip:
  828.            sti
  829.            mov edx, [str]
  830.            mov [edx+STREAM.flags], SND_PLAY
  831.            cmp [eng_state], SND_PLAY
  832.            je .main_loop
  833.  
  834.            stdcall dev_play, [hSound]
  835.            mov [eng_state], SND_PLAY
  836.            jmp .main_loop
  837. .wait:
  838.            sti
  839.            mov edx, [str]
  840.            mov eax, [edx+STREAM.notify_event]
  841.            mov ebx, [edx+STREAM.notify_id]
  842.            call WaitEvent   ;eax ebx
  843.            jmp .main_loop
  844. .done:
  845.            cmp [state_saved], 1
  846.            jne @F
  847.  
  848.            lea eax, [fpu_state+15]
  849.            and eax, -16
  850.            call FpuRestore
  851. @@:
  852.            xor eax, eax
  853.            ret
  854. .fail:
  855.            or eax, -1
  856.            ret
  857. endp
  858.  
  859. ; both static and stream
  860. ; reset all but not clear buffers
  861.  
  862.  
  863. ; flags reserved
  864. ;  RESET_INPUT  equ 1   ;reserved reset and clear input buffer
  865. ;  RESET_OUTPUT equ 2   ;reserved reset and clear output buffer
  866. ;  RESET_ALL    equ 3
  867.  
  868.  
  869. align 4
  870. proc ResetBuffer stdcall, str:dword, flags:dword
  871.  
  872.            mov edx, [str]
  873.            mov [edx+STREAM.flags], SND_STOP
  874.  
  875.            mov edi, [edx+STREAM.in_base]
  876.            mov ecx, 128/4
  877.            mov eax, [edx+STREAM.r_silence]
  878.            cld
  879.            rep stosd
  880.  
  881.            mov [edx+STREAM.in_wp], edi
  882.            mov [edx+STREAM.in_rp], edi
  883.  
  884.            test [edx+STREAM.flags], PCM_STATIC
  885.            jnz .static
  886.            mov [edx+STREAM.in_count], 0
  887.            jmp @F
  888. .static:
  889.            mov eax, [edx+STREAM.in_size]
  890.            mov [edx+STREAM.in_count], eax
  891. @@:
  892.  
  893.            mov eax, [edx+STREAM.in_size]
  894.            sub eax, 128
  895.            mov [edx+STREAM.in_free], eax
  896.  
  897.            xor eax, eax
  898.            mov ebx,[edx+STREAM.out_base]
  899.            mov [edx+STREAM.out_wp], ebx
  900.            mov [edx+STREAM.out_rp], ebx
  901.            mov [edx+STREAM.out_count], eax
  902.            ret
  903. .fail:
  904.            or eax, -1
  905.            ret
  906. endp
  907.  
  908. ; for static buffers only
  909.  
  910. align 4
  911. proc SetBufferPos stdcall, str:dword, pos:dword
  912.  
  913.            mov edx, [str]
  914.            test [edx+STREAM.format], PCM_STATIC
  915.            jz .fail
  916.  
  917.            mov [edx+STREAM.flags], SND_STOP
  918.  
  919.            mov eax, [pos]
  920.            add eax, [edx+STREAM.in_base]
  921.            mov ebx, [edx+STREAM.in_top]
  922.            add eax, 128
  923.  
  924.            cmp eax, ebx
  925.            jae .fail
  926.  
  927.            mov [edx+STREAM.in_rp], eax
  928.            sub ebx, eax
  929.            mov [edx+STREAM.in_count], ebx
  930.            xor eax, eax
  931.            ret
  932. .fail:
  933.            or eax, -1
  934.            ret
  935. endp
  936.  
  937. align 4
  938. proc GetBufferPos stdcall, str:dword
  939.  
  940.            mov edx, [str]
  941.            test [edx+STREAM.format], PCM_STATIC
  942.            jz .fail
  943.  
  944.            mov ebx, [edx+STREAM.in_rp]
  945.            sub ebx, [edx+STREAM.in_base]
  946.            sub ebx, 128
  947.            xor eax, eax
  948.            ret
  949. .fail:
  950.            xor ebx,ebx
  951.            or eax, -1
  952.            ret
  953. endp
  954.  
  955. ; both
  956.  
  957. align 4
  958. proc SetBufferVol stdcall, str:dword,l_vol:dword,r_vol:dword
  959.  
  960.            mov edx, [str]
  961.            stdcall set_vol_param,[l_vol],[r_vol],[edx+STREAM.pan]
  962.            ret
  963. endp
  964.  
  965. proc set_vol_param stdcall, l_vol:dword,r_vol:dword,pan:dword
  966.            locals
  967.              _600    dd ?
  968.              _32767  dd ?
  969.              state   rb 108
  970.            endl
  971.  
  972.            mov [_600], 0x44160000   ;600.0
  973.            mov [_32767], 32767
  974.  
  975.            lea ebx, [state]
  976.            fnsave [ebx]
  977.  
  978.            movq mm0, qword [l_vol]
  979.            pminsw mm0, qword [vol_max]
  980.            pmaxsw mm0, qword [vol_min]
  981.            movq qword [l_vol], mm0
  982.            movq qword [edx+STREAM.l_vol], mm0
  983.  
  984.            movd mm1,[pan]
  985.            pminsw mm1, qword [pan_max]
  986.            pmaxsw mm1, qword [vol_min]
  987.            movd [edx+STREAM.pan], mm1
  988.  
  989.            cmp word [edx+STREAM.pan], 0
  990.            jl @F
  991.  
  992.            psubsw mm0,mm1
  993.            pminsw mm0, qword [vol_max]
  994.            pmaxsw mm0, qword [vol_min]
  995.            movd [l_vol],mm0
  996.            jmp .calc_amp
  997. @@:
  998.            punpckhdq mm0,mm0
  999.            paddsw mm0,mm1
  1000.            pminsw mm0, qword [vol_max]
  1001.            pmaxsw mm0, qword [vol_min]
  1002.            movd [r_vol], mm0
  1003. .calc_amp:
  1004.            emms
  1005.            fild word [l_vol]
  1006.  
  1007.            call .calc
  1008.  
  1009.            fistp word [edx+STREAM.l_amp]
  1010.            fstp dword [edx+STREAM.l_amp_f]
  1011.            fstp st0
  1012.  
  1013.            fild word [r_vol]
  1014.  
  1015.            call .calc
  1016.  
  1017.            fistp word [edx+STREAM.r_amp]
  1018.            fstp dword [edx+STREAM.r_amp_f]
  1019.            fstp st0
  1020.  
  1021.            fnclex
  1022.            lea ebx, [state]
  1023.            frstor [ebx]
  1024.  
  1025.            xor eax, eax
  1026.            inc eax
  1027.            ret
  1028. .calc:
  1029.            fdiv dword [_600]
  1030.            fld st0
  1031.            frndint
  1032.            fxch st1
  1033.            fsub st, st1
  1034.            f2xm1
  1035.            fld1
  1036.            faddp st1, st0
  1037.            fscale
  1038.            fld st0
  1039.            fimul dword [_32767]
  1040.            ret 0
  1041. endp
  1042.  
  1043. align 4
  1044. proc GetBufferVol stdcall, str:dword,p_lvol:dword,p_rvol:dword
  1045.  
  1046.            mov edx, [str]
  1047.            mov eax, [p_lvol]
  1048.            movsx ecx, word [edx+STREAM.l_vol]
  1049.            mov [eax], ecx
  1050.  
  1051.            mov eax, [p_rvol]
  1052.            movsx ecx, word [edx+STREAM.r_vol]
  1053.            mov [eax], ecx
  1054.            xor eax, eax
  1055.            ret
  1056. endp
  1057.  
  1058. align 4
  1059. proc SetBufferPan stdcall, str:dword,pan:dword
  1060.  
  1061.            mov edx, [str]
  1062.            stdcall set_vol_param,[edx+STREAM.l_vol],\
  1063.                                  [edx+STREAM.r_vol],[pan]
  1064.            ret
  1065. endp
  1066.  
  1067. ; for static and ring buffers only
  1068.  
  1069. align 4
  1070. proc play_buffer stdcall, str:dword, flags:dword
  1071.  
  1072.            mov ebx, [str]
  1073.            mov eax, [ebx+STREAM.format]
  1074.            test eax, PCM_OUT
  1075.            jnz .fail
  1076.  
  1077.            cmp ax, PCM_ALL
  1078.            je .fail
  1079.  
  1080.            mov [ebx+STREAM.flags], SND_PLAY
  1081.            cmp [eng_state], SND_PLAY
  1082.            je .done
  1083.  
  1084.            stdcall  dev_play, [hSound]
  1085.            mov [eng_state], SND_PLAY
  1086. .done:
  1087.            test [flags], PLAY_SYNC
  1088.            jz @F
  1089.  
  1090.            mov edx, [str]
  1091. .wait:
  1092.            mov eax, [edx+STREAM.notify_event]
  1093.            mov ebx, [edx+STREAM.notify_id]
  1094.            call WaitEvent   ;eax ebx
  1095.  
  1096.            mov edx, [str]
  1097.            cmp [edx+STREAM.flags], SND_STOP
  1098.            jne .wait
  1099. @@:
  1100.            xor eax, eax
  1101.            ret
  1102. .fail:
  1103.            or eax, -1
  1104.            ret
  1105. endp
  1106.  
  1107. ; for static and ring buffers only
  1108.  
  1109. align 4
  1110. proc stop_buffer stdcall, str:dword
  1111.  
  1112.            mov edx, [str]
  1113.            test [edx+STREAM.format], PCM_STATIC+PCM_RING
  1114.            jz .fail
  1115.  
  1116.            mov [edx+STREAM.flags], SND_STOP
  1117.  
  1118. ;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
  1119.  
  1120.            mov eax, [edx+STREAM.notify_event]
  1121.            mov ebx, [edx+STREAM.notify_id]
  1122.            call ClearEvent   ;eax ebx
  1123.  
  1124.            xor eax, eax
  1125.            ret
  1126. .fail:
  1127.            or eax, -1
  1128.            ret
  1129. endp
  1130.  
  1131. ; param
  1132. ;  eax= mix_list
  1133.  
  1134. align 4
  1135. do_mix_list:
  1136.  
  1137.            xor edx, edx
  1138.            mov esi, str.fd-FD_OFFSET
  1139.            mov ebx, [esi+STREAM.str_fd]
  1140. @@:
  1141.            cmp ebx, esi
  1142.            je .done
  1143.  
  1144.            cmp [ebx+STREAM.magic], 'WAVE'
  1145.            jne .next
  1146.  
  1147.            cmp [ebx+STREAM.size], STREAM.sizeof
  1148.            jne .next
  1149.  
  1150.            cmp [ebx+STREAM.flags], SND_PLAY;
  1151.            jne .next
  1152.  
  1153.            mov ecx, [ebx+STREAM.out_count]
  1154.            test ecx, ecx
  1155.            jnz .l1
  1156.  
  1157.            test [ebx+STREAM.format], PCM_RING
  1158.            jnz .next
  1159.            mov [ebx+STREAM.flags], SND_STOP
  1160.            jmp .next
  1161. .l1:
  1162.            cmp ecx, 512
  1163.            jae .add_buff
  1164.  
  1165.            mov edi, [ebx+STREAM.out_rp]
  1166.            add edi, ecx
  1167.            sub ecx, 512
  1168.            neg ecx
  1169.            push eax
  1170.            xor eax, eax
  1171.            cld
  1172.            rep stosb
  1173.            pop eax
  1174.  
  1175.            mov [ebx+STREAM.out_count], 512
  1176.  
  1177. .add_buff:
  1178.            mov ecx, [ebx+STREAM.out_rp]
  1179.            mov [eax],ecx
  1180.  
  1181. if USE_SSE2_MIXER
  1182.            mov edi, dword [ebx+STREAM.l_amp_f]
  1183.            mov [eax+4], edi
  1184.            mov edi, dword [ebx+STREAM.r_amp_f]
  1185.            mov [eax+8], edi
  1186. else
  1187.            mov edi, dword [ebx+STREAM.l_amp]
  1188.            mov [eax+4], edi
  1189. end if
  1190.            add [ebx+STREAM.out_rp], 512
  1191.            sub [ebx+STREAM.out_count], 512
  1192.  
  1193.            add eax, 12
  1194.            inc edx
  1195. .next:
  1196.            mov ebx, [ebx+STREAM.str_fd]
  1197.            jmp @B
  1198. .done:
  1199.            mov eax, edx
  1200.            ret
  1201.  
  1202. align 4
  1203. prepare_playlist:
  1204.  
  1205.            xor edx, edx
  1206.            mov [play_count], edx
  1207.            mov esi, str.fd-FD_OFFSET
  1208.            mov edi, [esi+STREAM.str_fd]
  1209. @@:
  1210.            cmp edi, esi
  1211.            je .done
  1212.  
  1213.            cmp [edi+STREAM.magic], 'WAVE'
  1214.            jne .next
  1215.  
  1216.            cmp [edi+STREAM.size], STREAM.sizeof
  1217.            jne .next
  1218.  
  1219.            cmp [edi+STREAM.flags], SND_PLAY;
  1220.            jne .next
  1221.  
  1222.            mov [play_list+edx], edi
  1223.            inc [play_count]
  1224.            add edx, 4
  1225. .next:
  1226.            mov edi, [edi+STREAM.str_fd]
  1227.            jmp @B
  1228. .done:
  1229.            ret
  1230.  
  1231. align 4
  1232. proc set_handler stdcall, hsrv:dword, handler_proc:dword
  1233.            locals
  1234.              handler    dd ?
  1235.              io_code    dd ?
  1236.              input      dd ?
  1237.              inp_size   dd ?
  1238.              output     dd ?
  1239.              out_size   dd ?
  1240.              val        dd ?
  1241.            endl
  1242.  
  1243.            mov eax, [hsrv]
  1244.            lea ecx, [handler_proc]
  1245.            xor ebx, ebx
  1246.  
  1247.            mov [handler], eax
  1248.            mov [io_code], DEV_CALLBACK
  1249.            mov [input], ecx
  1250.            mov [inp_size], 4
  1251.            mov [output], ebx
  1252.            mov [out_size], 0
  1253.  
  1254.            lea eax, [handler]
  1255.            stdcall ServiceHandler, eax
  1256.            ret
  1257. endp
  1258.  
  1259. align 4
  1260. proc dev_play stdcall, hsrv:dword
  1261.            locals
  1262.              handle     dd ?
  1263.              io_code    dd ?
  1264.              input      dd ?
  1265.              inp_size   dd ?
  1266.              output     dd ?
  1267.              out_size   dd ?
  1268.              val        dd ?
  1269.            endl
  1270.  
  1271.            mov eax, [hsrv]
  1272.            xor ebx, ebx
  1273.  
  1274.            mov [handle], eax
  1275.            mov [io_code], DEV_PLAY
  1276.            mov [input], ebx
  1277.            mov [inp_size], ebx
  1278.            mov [output], ebx
  1279.            mov [out_size], ebx
  1280.  
  1281.            lea eax, [handle]
  1282.            stdcall ServiceHandler, eax
  1283.            ret
  1284. endp
  1285.  
  1286. if 0
  1287. align 4
  1288. dword2str:
  1289.       mov  esi, hex_buff
  1290.       mov ecx, -8
  1291. @@:
  1292.       rol eax, 4
  1293.       mov ebx, eax
  1294.       and ebx, 0x0F
  1295.       mov bl, [ebx+hexletters]
  1296.       mov [8+esi+ecx], bl
  1297.       inc ecx
  1298.       jnz @B
  1299.       ret
  1300.  
  1301. hexletters   db '0123456789ABCDEF'
  1302. hex_buff     db 8 dup(0),13,10,0
  1303.  
  1304. end if
  1305.  
  1306. include 'mixer.asm'
  1307. include 'mix_mmx.inc'
  1308. include 'mix_sse2.inc'
  1309.  
  1310. ;if USE_SSE
  1311. ; include 'mix_sse.inc'
  1312. ;end if
  1313.  
  1314. align 16
  1315. resampler_params:
  1316.      ;r_size    r_dt   resampler_func
  1317.      dd 0,0,0                                  ; 0  PCM_ALL
  1318.      dd 16384,      0, copy_stream    ; 1  PCM_2_16_48
  1319.      dd  8192,      0, m16_stereo     ; 2  PCM_1_16_48
  1320.  
  1321.      dd 16384,  30109, resample_2     ; 3  PCM_2_16_44
  1322.      dd  8192,  30109, resample_1     ; 4  PCM_1_16_44
  1323.  
  1324.      dd 16384,  21846, resample_2     ; 5  PCM_2_16_32
  1325.      dd  8192,  21846, resample_1     ; 6  PCM_1_16_32
  1326.  
  1327.      dd 16384,  16384, resample_2     ; 7  PCM_2_16_24
  1328.      dd  8192,  16384, resample_1     ; 8  PCM_1_16_24
  1329.  
  1330.      dd  8192,  15052, resample_2     ; 9  PCM_2_16_22
  1331.      dd  4096,  15052, resample_1     ;10  PCM_1_16_22
  1332.  
  1333.      dd  8192,  10923, resample_2     ;11  PCM_2_16_16
  1334.      dd  4096,  10923, resample_1     ;12  PCM_1_16_16
  1335.  
  1336.      dd  8192,   8192, resample_2     ;13  PCM_2_16_12
  1337.      dd  4096,   8192, resample_1     ;14  PCM_1_16_12
  1338.  
  1339.      dd  4096,   7527, resample_2     ;15  PCM_2_16_11
  1340.      dd  2048,   7527, resample_1     ;16  PCM_1_16_11
  1341.  
  1342.      dd  4096,   5462, resample_2     ;17  PCM_2_16_8
  1343.      dd  2048,   5462, resample_1     ;18  PCM_1_16_8
  1344.  
  1345.      dd 16384,      0, s8_stereo      ;19  PCM_2_8_48
  1346.      dd  8192,      0, m8_stereo      ;20  PCM_1_8_48
  1347.  
  1348.      dd  8192,  30109, resample_28    ;21  PCM_2_8_44
  1349.      dd  4096,  30109, resample_18    ;22  PCM_1_8_44
  1350.  
  1351.      dd  8192,  21846, resample_28    ;23  PCM_2_8_32
  1352.      dd  4096,  21846, resample_18    ;24  PCM_1_8_32
  1353.  
  1354.      dd  8192,  16384, resample_28    ;25  PCM_2_8_24
  1355.      dd  4096,  16384, resample_18    ;26  PCM_1_8_24
  1356.  
  1357.      dd  4096,  15052, resample_28    ;27  PCM_2_8_22
  1358.      dd  2048,  15052, resample_18    ;28  PCM_1_8_22
  1359.  
  1360.      dd  4096,  10923, resample_28    ;29  PCM_2_8_16
  1361.      dd  2048,  10923, resample_18    ;30  PCM_1_8_16
  1362.  
  1363.      dd  4096,   8192, resample_28    ;31  PCM_2_8_12
  1364.      dd  2048,   8192, resample_18    ;32  PCM_1_8_12
  1365.  
  1366.      dd  2048,   7527, resample_28    ;33  PCM_2_8_11
  1367.      dd  1024,   7527, resample_18    ;34  PCM_1_8_11
  1368.  
  1369.      dd  2048,   5462, resample_28    ;35  PCM_2_8_8
  1370.      dd  1024,   5462, resample_18    ;36  PCM_1_8_8
  1371.  
  1372. m7            dw 0x8000,0x8000,0x8000,0x8000
  1373. mm80          dq 0x8080808080808080
  1374. mm_mask       dq 0xFF00FF00FF00FF00
  1375.  
  1376. vol_max       dd 0x00000000,0x00000000
  1377. vol_min       dd 0x0000D8F0,0x0000D8F0
  1378. pan_max       dd 0x00002710,0x00002710
  1379.  
  1380. ;stream_map    dd 0xFFFF       ; 16
  1381. version       dd (5 shl 16) or SOUND_VERSION
  1382.  
  1383. szInfinity    db 'INFINITY',0
  1384. szSound       db 'SOUND',0
  1385.  
  1386. if DEBUG
  1387. msgFail       db 'Sound service not loaded',13,10,0
  1388. msgPlay       db 'Play buffer',13,10,0
  1389. msgStop       db 'Stop',13,10,0
  1390. msgUser       db 'User callback',13,10,0
  1391. msgMem        db 'Not enough memory',13,10,0
  1392. msgDestroy    db 'Destroy sound buffer', 13,10,0
  1393. msgWaveout    db 'Play waveout', 13,10,0
  1394. msgSetVolume  db 'Set volume',13,10,0
  1395. end if
  1396.  
  1397. section '.data' data readable writable align 16
  1398.  
  1399. play_list     rd 16
  1400. mix_input     rd 16
  1401. play_count    rd 1
  1402. hSound        rd 1
  1403. eng_state     rd 1
  1404. mix_buff      rd 1
  1405. mix_buff_map  rd 1
  1406. str.fd        rd 1
  1407. str.bk        rd 1
  1408.  
  1409. mix_2_core    rd 1
  1410. mix_3_core    rd 1
  1411. mix_4_core    rd 1
  1412.