Subversion Repositories Kolibri OS

Rev

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

  1. ;
  2. ;   This file is part of the Infinity sound library.
  3. ;   (C) copyright Serge 2006
  4. ;   email: infinity_sound@mail.ru
  5. ;
  6. ;   This program is free software; you can redistribute it and/or modify
  7. ;   it under the terms of the GNU General Public License as published by
  8. ;   the Free Software Foundation; either version 2 of the License, or
  9. ;   (at your option) any later version.
  10. ;
  11. ;   This program is distributed in the hope that it will be useful,
  12. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;   GNU General Public License for more details.
  15.  
  16. format MS COFF
  17.  
  18. include 'proc32.inc'
  19. include 'main.inc'
  20. include 'imports.inc'
  21.  
  22. FORCE_MMX        equ 0  ;set to 1 to force use mmx or
  23. FORCE_MMX_128    equ 0  ;integer sse2 extensions
  24.                         ;and reduce driver size
  25. ;USE_SSE         equ 0
  26.  
  27. DEBUG            equ 1
  28.  
  29. EVENT_NOTIFY     equ 0x00000200
  30.  
  31. OS_BASE          equ 0
  32. new_app_base     equ 0x60400000
  33. PROC_BASE        equ OS_BASE+0x0080000
  34.  
  35. CAPS_SSE2        equ 26
  36.  
  37.  
  38. public START
  39. public service_proc
  40. public version
  41.  
  42. SND_CREATE_BUFF     equ 2
  43. SND_PLAY            equ 3
  44. SND_STOP            equ 4
  45. SND_SETBUFF         equ 5
  46. SND_DESTROY_BUFF    equ 6
  47.  
  48. DEV_PLAY            equ 1
  49. DEV_STOP            equ 2
  50. DEV_CALLBACK        equ 3
  51.  
  52. struc IOCTL
  53. {  .handle           dd ?
  54.    .io_code          dd ?
  55.    .input            dd ?
  56.    .inp_size         dd ?
  57.    .output           dd ?
  58.    .out_size         dd ?
  59. }
  60.  
  61. virtual at 0
  62.   IOCTL IOCTL
  63. end virtual
  64.  
  65. section '.flat' code readable align 16
  66.  
  67. proc START stdcall, state:dword
  68.  
  69.            cmp [state], 1
  70.            jne .exit
  71.  
  72.            stdcall GetService, szSound
  73.            test eax, eax
  74.            jz .fail
  75.            mov [hSound], eax
  76.  
  77.            stdcall KernelAlloc, 16*512
  78.            test eax, eax
  79.            jz .out_of_mem
  80.            mov [mix_buff], eax
  81.  
  82.            mov eax, str.fd-FD_OFFSET
  83.            mov [str.fd], eax
  84.            mov [str.bk], eax
  85.  
  86. if FORCE_MMX
  87.  if FORCE_MMX_128
  88.   display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10
  89.   stop
  90.  end if
  91.            mov [mix_2_core], mmx_mix_2
  92.            mov [mix_3_core], mmx_mix_3
  93.            mov [mix_4_core], mmx_mix_4
  94. end if
  95.  
  96. if FORCE_MMX_128
  97.  if FORCE_MMX
  98.   display 'Use only FORCE_MMX or FORCE_MMX_128 not both together',13,10
  99.   stop
  100.  end if
  101.            mov [mix_2_core], mmx128_mix_2
  102.            mov [mix_3_core], mmx128_mix_3
  103.            mov [mix_4_core], mmx128_mix_4
  104. end if
  105.  
  106. if ~(FORCE_MMX or FORCE_MMX_128)  ;autodetect
  107.            mov eax, 1
  108.            cpuid
  109.            bt edx, CAPS_SSE2
  110.            jc .mmx128
  111.                                            ;old 64-bit mmx
  112.            mov [mix_2_core], mmx_mix_2
  113.            mov [mix_3_core], mmx_mix_3
  114.            mov [mix_4_core], mmx_mix_4
  115.            jmp @F
  116. .mmx128:                                   ;new 128-bit sse2 extensions
  117.            mov [mix_2_core], mmx128_mix_2
  118.            mov [mix_3_core], mmx128_mix_3
  119.            mov [mix_4_core], mmx128_mix_4
  120. @@:
  121. end if
  122.            stdcall set_handler, [hSound], new_mix
  123.            stdcall RegService, szInfinity, service_proc
  124.            ret
  125. .fail:
  126.      if DEBUG
  127.            mov esi, msgFail
  128.            call SysMsgBoardStr
  129.      end if
  130. .exit:
  131.            xor eax, eax
  132.            ret
  133.  
  134. .out_of_mem:
  135.      if DEBUG
  136.            mov esi, msgMem
  137.            call SysMsgBoardStr
  138.      end if
  139.            xor eax, eax
  140.            ret
  141. endp
  142.  
  143. handle     equ  IOCTL.handle
  144. io_code    equ  IOCTL.io_code
  145. input      equ  IOCTL.input
  146. inp_size   equ  IOCTL.inp_size
  147. output     equ  IOCTL.output
  148. out_size   equ  IOCTL.out_size
  149.  
  150. align 4
  151. proc service_proc stdcall, ioctl:dword
  152.  
  153.            mov edi, [ioctl]
  154.            mov eax, [edi+io_code]
  155.  
  156.            cmp eax, SND_CREATE_BUFF
  157.            jne @F
  158.            mov ebx, [edi+input]
  159.            stdcall CreateBuffer,[ebx]
  160.            ret
  161. @@:
  162.            cmp eax, SND_PLAY
  163.            jne @F
  164.  
  165.            mov ebx, [edi+input]
  166.            stdcall play_buffer, [ebx]
  167.            ret
  168. @@:
  169.            cmp eax, SND_STOP
  170.            jne @F
  171.  
  172. ;       if DEBUG
  173. ;          mov esi, msgStop
  174. ;          call   [SysMsgBoardStr]
  175. ;       end if
  176.  
  177.            mov ebx, [edi+input]
  178.            stdcall stop_buffer, [ebx]
  179.            ret
  180. @@:
  181.            cmp eax, SND_SETBUFF
  182.            jne @F
  183.  
  184.            mov ebx, [edi+input]
  185.            mov eax, [ebx+4]
  186.            add eax, new_app_base
  187.            stdcall set_buffer, [ebx],eax,[ebx+8],[ebx+12]
  188.            ret
  189. @@:
  190.            cmp eax, SND_DESTROY_BUFF
  191.            jne @F
  192.  
  193.            mov eax, [edi+input]
  194.            mov eax, [eax]
  195.            call DestroyBuffer    ;eax
  196.            ret
  197. @@:
  198.            xor eax, eax
  199.            ret
  200. endp
  201.  
  202. restore   handle
  203. restore   io_code
  204. restore   input
  205. restore   inp_size
  206. restore   output
  207. restore   out_size
  208.  
  209. TASK_COUNT    equ 0x0003004
  210. CURRENT_TASK  equ 0x0003000
  211.  
  212. align 8
  213. proc CreateBuffer stdcall, format:dword
  214.            locals
  215.              str dd ?
  216.            endl
  217.  
  218.            mov ebx, [CURRENT_TASK]      ;hack: direct accsess
  219.            shl ebx, 5                   ;to kernel data
  220.            mov ebx, [0x3000+ebx+4]
  221.            mov eax, STREAM_SIZE
  222.  
  223.            call CreateObject
  224.            test eax, eax
  225.            jz .fail
  226.            mov [str], eax
  227.  
  228.            mov [eax+STREAM.magic], 'WAVE'
  229.            mov [eax+STREAM.destroy], DestroyBuffer.destroy
  230.            mov [eax+STREAM.size], STREAM_SIZE
  231.  
  232.            pushf
  233.            cli
  234.            mov ebx, str.fd-FD_OFFSET
  235.            mov edx, [ebx+STREAM.str_fd]
  236.            mov [eax+STREAM.str_fd], edx
  237.            mov [eax+STREAM.str_bk], ebx
  238.            mov [ebx+STREAM.str_fd], eax
  239.            mov [edx+STREAM.str_bk], eax
  240.            popf
  241.  
  242.            stdcall KernelAlloc, 168*1024
  243.  
  244.            mov edi, [str]
  245.            mov [edi+STREAM.base], eax
  246.            add eax, 0x1000
  247.            mov [edi+STREAM.seg_0], eax
  248.            mov [edi+STREAM.curr_seg], eax
  249.            mov [edi+STREAM.notify_off1], eax
  250.            add eax, 0x8000
  251.            mov [edi+STREAM.lim_0], eax
  252.            add eax, 0x1000
  253.            mov [edi+STREAM.seg_1], eax
  254.            mov [edi+STREAM.notify_off2], eax
  255.            add eax, 0x8000
  256.            mov [edi+STREAM.limit], eax
  257.            mov [edi+STREAM.lim_1], eax
  258.  
  259.            mov [edi+STREAM.work_buff], eax
  260.            mov [edi+STREAM.work_read], eax
  261.            mov [edi+STREAM.work_write], eax
  262.            mov [edi+STREAM.work_count], 0
  263.            add eax, 0x10000
  264.            mov [edi+STREAM.work_top], eax
  265.  
  266.            mov eax, [format]
  267.            mov [edi+STREAM.format], eax
  268.            mov [edi+STREAM.flags], SND_STOP
  269.  
  270.            xor ebx, ebx
  271.            cmp eax, 19
  272.            jb @f
  273.            mov ebx, 0x80808080
  274. @@:
  275.            mov [edi+STREAM.r_silence], ebx
  276.  
  277.            shl eax, 4
  278.            mov ebx, [resampler_params+eax]
  279.            mov ecx, [resampler_params+eax+4]
  280.            mov edx, [resampler_params+eax+8]
  281.  
  282.            mov [edi+STREAM.r_size],ebx
  283.            mov [edi+STREAM.r_end], ecx
  284.            mov [edi+STREAM.r_dt],  edx
  285.  
  286.            mov ebx, [resampler_params+eax+12]
  287.            mov [edi+STREAM.resample], ebx
  288.  
  289.            mov edx, [edi+STREAM.base]
  290.            lea eax, [edx+0x9000]
  291.            call GetPgAddr  ;eax
  292.            call FreePage   ;eax
  293.  
  294.            mov eax, edx
  295.            lea ebx, [edx+0x9000]
  296.            call GetPgAddr  ;eax
  297.            stdcall MapPage, ebx, eax, dword 3
  298.  
  299.            mov edi, [edi+STREAM.base]
  300.            mov ecx, (168*1024)/4
  301.            xor eax, eax
  302.            rep stosd
  303.  
  304.            mov eax, [str]
  305.            ret
  306. .fail:
  307.            xor eax, eax
  308.            ret
  309. endp
  310.  
  311. align 4
  312. pid_to_slot:
  313.  
  314.            push   ebx
  315.            push   ecx
  316.            mov    ebx,[TASK_COUNT]
  317.            shl    ebx,5
  318.            mov    ecx,2*32
  319. .loop:
  320.            cmp    byte [CURRENT_TASK+ecx+0xa],9
  321.            jz     .endloop              ;skip empty slots
  322.            cmp    [CURRENT_TASK+ecx+0x4],eax ;check PID
  323.            jz     .pid_found
  324. .endloop:
  325.            add    ecx,32
  326.            cmp    ecx,ebx
  327.            jle    .loop
  328.            pop    ecx
  329.            pop    ebx
  330.            xor    eax,eax
  331.            ret
  332.  
  333. .pid_found:
  334.            shr    ecx,5
  335.            mov    eax,ecx
  336.            pop    ecx
  337.            pop    ebx
  338.            ret
  339.  
  340. ;param
  341. ; eax= buffer handle
  342.  
  343. align 4
  344. DestroyBuffer:
  345.  
  346.            cmp [eax+STREAM.magic], 'WAVE'
  347.            jne .fail
  348.  
  349.            cmp [eax+STREAM.size], STREAM_SIZE
  350.            jne .fail
  351. .destroy:
  352.            pushf
  353.            cli
  354.            mov ebx, [eax+STREAM.str_fd]
  355.            mov ecx, [eax+STREAM.str_bk]
  356.            mov [ebx+STREAM.str_bk], ecx
  357.            mov [ecx+STREAM.str_fd], ebx
  358.            popf
  359.  
  360.            push eax
  361.            stdcall KernelFree, [eax+STREAM.base]
  362.            pop eax
  363.            call DestroyObject    ;eax
  364.            ret
  365. .fail:
  366.            ret
  367.  
  368. align 4
  369. proc play_buffer stdcall, str:dword
  370.  
  371.            mov ebx, [str]
  372.            cmp [ebx+STREAM.magic], 'WAVE'
  373.            jne .fail
  374.  
  375.            cmp [ebx+STREAM.size], STREAM_SIZE
  376.            jne .fail
  377.  
  378.            mov edi,[ebx+STREAM.work_buff]
  379.            mov [ebx+STREAM.work_read], edi
  380.            mov [ebx+STREAM.work_write], edi
  381.            mov [ebx+STREAM.work_count], 0
  382.  
  383.            mov edx, [ebx+STREAM.base]
  384.            add edx, 0x1000
  385.            mov [ebx+STREAM.seg_0], edx
  386.            mov [ebx+STREAM.curr_seg], edx
  387.            add edx, 0x8000
  388.            mov [ebx+STREAM.lim_0], edx
  389.            add edx, 0x1000
  390.            mov [ebx+STREAM.seg_1], edx
  391.            add edx, 0x8000
  392.            mov [ebx+STREAM.lim_1], edx
  393.  
  394.            mov edx, [ebx+STREAM.seg_0]
  395.            mov ecx, -128
  396.            mov eax, [ebx+STREAM.r_silence]
  397. @@:
  398.            mov [edx+ecx], eax
  399.            add ecx, 4
  400.            jnz @B
  401.  
  402.            stdcall [ebx+STREAM.resample], edi, edx,\
  403.            [ebx+STREAM.r_dt],[ebx+STREAM.r_size],[ebx+STREAM.r_end]
  404.  
  405.            mov ebx, [str]
  406.  
  407.            add [ebx+STREAM.work_count], eax
  408.            add [ebx+STREAM.work_write], eax
  409.  
  410.            mov edx, [ebx+STREAM.r_size]
  411.            add [ebx+STREAM.curr_seg], edx
  412.  
  413.            mov [ebx+STREAM.flags], SND_PLAY
  414.  
  415.            mov eax, [ebx+STREAM.r_silence]
  416.            mov edi, [ebx+STREAM.work_write]
  417.            mov ecx, [ebx+STREAM.work_top]
  418.            sub ecx, edi
  419.            shr ecx, 2
  420.            cld
  421.            rep stosd
  422.  
  423.            stdcall  dev_play, [hSound]
  424.            xor eax, eax
  425.            inc eax
  426.            ret
  427. .fail:
  428.            xor eax, eax
  429.            ret
  430. endp
  431.  
  432. align 4
  433. proc stop_buffer stdcall, str:dword
  434.  
  435.            mov edi, [str]
  436.  
  437.            cmp [edi+STREAM.magic], 'WAVE'
  438.            jne .fail
  439.  
  440.            cmp [edi+STREAM.size], STREAM_SIZE
  441.            jne .fail
  442.  
  443.            mov [edi+STREAM.flags], SND_STOP
  444.  
  445. ;           stdcall [ServiceHandler], [hSound], dword DEV_STOP, 0
  446.  
  447.            xor eax, eax
  448.            inc eax
  449.            ret
  450. .fail:
  451.            xor eax, eax
  452.            ret
  453. endp
  454.  
  455. align 4
  456. proc set_buffer stdcall, str:dword,src:dword,offs:dword,size:dword
  457.  
  458.            mov edx, [str]
  459.            test edx, edx
  460.            jz .fail
  461.  
  462.            cmp [edx+STREAM.magic], 'WAVE'
  463.            jne .fail
  464.  
  465.            cmp [edx+STREAM.size], STREAM_SIZE
  466.            jne .fail
  467.  
  468.            mov esi,[src]
  469.            test esi, esi
  470.            jz .fail
  471.  
  472.            cmp esi, new_app_base
  473.            jb .fail
  474.  
  475.            mov edi, [offs]
  476.            mov ecx, 0x8000
  477.  
  478.            sub ecx, edi
  479.            jbe .seg_1
  480.  
  481.            sub [size], ecx
  482.            jb .fail
  483.  
  484.            add edi, [edx+STREAM.base]
  485.            add edi, 0x1000
  486.            shr ecx, 2
  487.            cld
  488.            rep movsd
  489.            jmp @F
  490. .seg_1:
  491.            add edi, [edx+STREAM.base]
  492.            add edi, 0x1000
  493. @@:
  494.            add edi, 0x1000
  495.            mov ecx, [size]
  496.            test ecx, ecx
  497.            jz .done
  498.            cmp ecx, 0x8000
  499.            ja .fail
  500.  
  501.            shr ecx, 2
  502.            rep movsd
  503. .done:
  504.            xor eax, eax
  505.            inc eax
  506.            ret
  507. .fail:
  508.            xor eax, eax
  509.            ret
  510. endp
  511.  
  512. align 4
  513. prepare_playlist:
  514.  
  515.            xor edx, edx
  516.            mov [play_count], edx
  517.            mov esi, str.fd-FD_OFFSET
  518.            mov edi, [esi+STREAM.str_fd]
  519. @@:
  520.            cmp edi, esi
  521.            je .done
  522.  
  523.            cmp [edi+STREAM.magic], 'WAVE'
  524.            jne .next
  525.  
  526.            cmp [edi+STREAM.size], STREAM_SIZE
  527.            jne .next
  528.  
  529. ;           mov eax,[edi+STREAM.pid]
  530. ;           cmp eax, -1
  531. ;           je .next
  532. ;           call pid_to_slot
  533. ;           test eax, eax
  534. ;           jz .next
  535.  
  536.            cmp [edi+STREAM.flags], SND_PLAY;
  537.            jne .next
  538.            cmp [edi+STREAM.work_count], 16384
  539.            jb .next
  540.  
  541.            mov [play_list+edx], edi
  542.            inc [play_count]
  543.            add edx, 4
  544. .next:
  545.            mov edi, [edi+STREAM.str_fd]
  546.            jmp @B
  547. .done:
  548.            ret
  549.  
  550. align 4
  551. proc set_handler stdcall, hsrv:dword, handler_proc:dword
  552.            locals
  553.              handler    dd ?
  554.              io_code    dd ?
  555.              input      dd ?
  556.              inp_size   dd ?
  557.              output     dd ?
  558.              out_size   dd ?
  559.              val        dd ?
  560.            endl
  561.  
  562.            mov eax, [hsrv]
  563.            lea ecx, [handler_proc]
  564.            xor ebx, ebx
  565.  
  566.            mov [handler], eax
  567.            mov [io_code], DEV_CALLBACK
  568.            mov [input], ecx
  569.            mov [inp_size], 4
  570.            mov [output], ebx
  571.            mov [out_size], 0
  572.  
  573.            lea eax, [handler]
  574.            stdcall ServiceHandler, eax
  575.            ret
  576. endp
  577.  
  578. align 4
  579. proc dev_play stdcall, hsrv:dword
  580.            locals
  581.              handle     dd ?
  582.              io_code    dd ?
  583.              input      dd ?
  584.              inp_size   dd ?
  585.              output     dd ?
  586.              out_size   dd ?
  587.              val        dd ?
  588.            endl
  589.  
  590.            mov eax, [hsrv]
  591.            xor ebx, ebx
  592.  
  593.            mov [handle], eax
  594.            mov [io_code], DEV_PLAY
  595.            mov [input], ebx
  596.            mov [inp_size], ebx
  597.            mov [output], ebx
  598.            mov [out_size], ebx
  599.  
  600.            lea eax, [handle]
  601.            stdcall ServiceHandler, eax
  602.            ret
  603. endp
  604.  
  605. include 'mixer.asm'
  606. include 'mix_mmx.inc'
  607. include 'mix_sse2.inc'
  608.  
  609. ;if USE_SSE
  610. ; include 'mix_sse.inc'
  611. ;end if
  612.  
  613. align 16
  614. resampler_params:
  615.      ;r_size    r_end   r_dt   resampler_func
  616.      dd 0,0,0,0                                  ; 0  PCM_ALL
  617.      dd 16384,          0,     0, copy_stream    ; 1  PCM_2_16_48
  618.      dd 16384,          0,     0, m16_stereo     ; 2  PCM_1_16_48
  619.  
  620.      dd 16384, 0x08000000, 30109, resample_2     ; 3  PCM_2_16_44
  621.      dd  8192, 0x08000000, 30109, resample_1     ; 4  PCM_1_16_44
  622.  
  623.      dd 16384, 0x08000000, 21846, resample_2     ; 5  PCM_2_16_32
  624.      dd  8192, 0x08000000, 21846, resample_1     ; 6  PCM_1_16_32
  625.  
  626.      dd 16384, 0x08000000, 16384, resample_2     ; 7  PCM_2_16_24
  627.      dd  8192, 0x08000000, 16384, resample_1     ; 8  PCM_1_16_24
  628.  
  629.      dd  8192, 0x04000000, 15052, resample_2     ; 9  PCM_2_16_22
  630.      dd  4096, 0x04000000, 15052, resample_1     ;10  PCM_1_16_22
  631.  
  632.      dd  8192, 0x04000000, 10923, resample_2     ;11  PCM_2_16_16
  633.      dd  4096, 0x04000000, 10923, resample_1     ;12  PCM_1_16_16
  634.  
  635.      dd  8192, 0x04000000,  8192, resample_2     ;13  PCM_2_16_12
  636.      dd  4096, 0x04000000,  8192, resample_1     ;14  PCM_1_16_12
  637.  
  638.      dd  4096, 0x02000000,  7527, resample_2     ;15  PCM_2_16_11
  639.      dd  2048, 0x02000000,  7527, resample_1     ;16  PCM_1_16_11
  640.  
  641.      dd  4096, 0x02000000,  5462, resample_2     ;17  PCM_2_16_8
  642.      dd  2048, 0x02000000,  5462, resample_1     ;18  PCM_1_16_8
  643.  
  644.      dd 16384,          0,     0, s8_stereo      ;19  PCM_2_8_48
  645.      dd  8192,          0,     0, m8_stereo      ;20  PCM_1_8_48
  646.  
  647.      dd  8192, 0x08000000, 30109, resample_28    ;21  PCM_2_8_44
  648.      dd  4096, 0x08000000, 30109, resample_18    ;22  PCM_1_8_44
  649.  
  650.      dd  8192, 0x08000000, 21846, resample_28    ;23  PCM_2_8_32
  651.      dd  4096, 0x08000000, 21846, resample_18    ;24  PCM_1_8_32
  652.  
  653.      dd  8192, 0x08000000, 16384, resample_28    ;25  PCM_2_8_24
  654.      dd  4096, 0x08000000, 16384, resample_18    ;26  PCM_1_8_24
  655.  
  656.      dd  4096, 0x04000000, 15052, resample_28    ;27  PCM_2_8_22
  657.      dd  2048, 0x04000000, 15052, resample_18    ;28  PCM_1_8_22
  658.  
  659.      dd  4096, 0x04000000, 10923, resample_28    ;29  PCM_2_8_16
  660.      dd  2048, 0x04000000, 10923, resample_18    ;30  PCM_1_8_16
  661.  
  662.      dd  4096, 0x04000000,  8192, resample_28    ;31  PCM_2_8_12
  663.      dd  2048, 0x04000000,  8192, resample_18    ;32  PCM_1_8_12
  664.  
  665.      dd  2048, 0x02000000,  7527, resample_28    ;33  PCM_2_8_11
  666.      dd  1024, 0x02000000,  7527, resample_18    ;34  PCM_1_8_11
  667.  
  668.      dd  2048, 0x02000000,  5462, resample_28    ;35  PCM_2_8_8
  669.      dd  1024, 0x02000000,  5462, resample_18    ;36  PCM_1_8_8
  670.  
  671. m7            dw 0x8000,0x8000,0x8000,0x8000
  672. mm80          dq 0x8080808080808080
  673. mm_mask       dq 0xFF00FF00FF00FF00
  674.  
  675. ;stream_map    dd 0xFFFF       ; 16
  676. version       dd 0x00030003
  677.  
  678. szInfinity    db 'INFINITY',0
  679. szSound       db 'SOUND',0
  680.  
  681. if DEBUG
  682. msgFail       db 'Sound service not loaded',13,10,0
  683. msgPlay       db 'Play buffer',13,10,0
  684. msgStop       db 'Stop',13,10,0
  685. msgUser       db 'User callback',13,10,0
  686. msgMem        db 'Not enough memory',13,10,0
  687. msgDestroy    db 'Destroy sound buffer', 13,10,0
  688. end if
  689.  
  690. section '.data' data readable writable align 16
  691.  
  692. play_list     rd 16
  693. mix_input     rd 16
  694. play_count    rd 1
  695. hSound        rd 1
  696. mix_buff      rd 1
  697. mix_buff_map  rd 1
  698. str.fd        rd 1
  699. str.bk        rd 1
  700.  
  701. mix_2_core    rd 1
  702. mix_3_core    rd 1
  703. mix_4_core    rd 1
  704.  
  705.