Subversion Repositories Kolibri OS

Rev

Rev 1058 | 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. ;   (C) copyright Serge 2006
  9. ;   email: infinity_sound@mail.ru
  10.  
  11.  
  12. align 4
  13.  
  14. mix_list rd 32*3
  15.  
  16. align 4
  17. proc new_mix stdcall, output:dword
  18.            locals
  19.              main_count   rd 1
  20.              fpu_state    rb 528   ;512+16
  21.            endl
  22.  
  23.            mov [main_count], 32
  24.            call prepare_playlist
  25.            cmp [play_count], 0
  26.            je .clear
  27.  
  28.            lea eax, [fpu_state+16]
  29.            and eax, -16             ;must be 16b aligned
  30.            call FpuSave
  31.  
  32.            call update_streams
  33. .mix:
  34.            lea eax, [mix_list]
  35.            call do_mix_list
  36.            test eax, eax
  37.            je .done
  38.  
  39. if USE_SSE2_MIXER
  40.  
  41.            cmp eax, 1
  42.            ja @F
  43.                                     ;use fast path
  44.            mov edi, [output]
  45.            lea edx, [mix_list]
  46.            call mix_fast
  47.            jmp .next
  48. @@:
  49.            cmp eax, 2
  50.            ja @F
  51.  
  52.            mov edi, [output]
  53.            lea edx, [mix_list]
  54.            call mix_fast_2_stream
  55.            jmp .next
  56. @@:
  57.  
  58. end if
  59.  
  60.            lea ebx, [mix_list]
  61.            stdcall mix_all, [output], ebx, eax
  62. .next:
  63.            add [output], 512
  64.            dec [main_count]
  65.            jnz .mix
  66. .exit:
  67.            lea eax, [fpu_state+16]
  68.            and eax, -16
  69.            call FpuRestore
  70.            ret
  71. .done:
  72.            mov ecx, [main_count]
  73.            shl ecx, 7     ;ecx*= 512/4
  74.  
  75.            mov edi, [output]
  76.            xor eax, eax
  77.            cld
  78.            rep stosd
  79.            jmp .exit
  80. .clear:
  81.            mov edi, [output]
  82.            mov ecx, 4096
  83.            xor eax, eax
  84.            cld
  85.            rep stosd
  86.            ret
  87. endp
  88.  
  89. align 4
  90. proc update_streams
  91.            locals
  92.              stream_index  dd ?
  93.              event         rd 6
  94.            endl
  95.  
  96.            mov [stream_index], 0
  97. .l1:
  98.            mov edx, [stream_index]
  99.            mov esi, [play_list+edx*4]
  100.  
  101.            add dword [esi+STREAM.time_stamp], 4096
  102.            adc dword [esi+STREAM.time_stamp+4], 0
  103.  
  104.            mov eax, [esi+STREAM.out_rp]
  105.            cmp eax, [esi+STREAM.out_top]
  106.            jb @f
  107.            sub eax, 64*1024
  108. @@:
  109.            mov [esi+STREAM.out_rp], eax
  110.  
  111.            cmp [esi+STREAM.out_count], 16384
  112.            ja .skip
  113.  
  114.            test [esi+STREAM.format], PCM_RING
  115.            jnz .ring
  116.  
  117.            stdcall refill, esi
  118. .skip:
  119.            inc [stream_index]
  120.            dec [play_count]
  121.            jnz .l1
  122.            ret
  123. .ring:
  124.            stdcall refill_ring, esi
  125.            jmp .skip
  126. endp
  127.  
  128. align 4
  129. proc refill stdcall, str:dword
  130.            locals
  131.              r_size    rd 1
  132.            endl
  133.  
  134.            mov ebx, [str]
  135.            mov edi, [ebx+STREAM.out_wp]
  136.            cmp edi, [ebx+STREAM.out_top]
  137.            jb @F
  138.            sub edi, 0x10000
  139.            mov [ebx+STREAM.out_wp], edi
  140. @@:
  141.            mov eax, [ebx+STREAM.in_count]
  142.            test eax, eax
  143.            jz .done
  144.  
  145.            mov ecx, [ebx+STREAM.r_size]
  146.            cmp eax, ecx
  147.            jle @F
  148.  
  149.            mov eax, ecx
  150. @@:
  151.            mov ecx, eax
  152.            cmp word [ebx+STREAM.format], PCM_1_16_8
  153.            ja @F
  154.  
  155.            shr eax, 1                   ;two channles
  156. @@:
  157.            test [ebx+STREAM.format], 1  ;even formats mono
  158.            jz @F
  159.  
  160.            shr eax, 1                   ;eax= samples
  161. @@:
  162.            shl eax, 15    ;eax*=32768 =r_end
  163.  
  164.            mov [r_size], ecx
  165.  
  166.            mov esi, [ebx+STREAM.in_rp]
  167.            mov edi, [ebx+STREAM.out_wp]
  168.  
  169.            stdcall [ebx+STREAM.resample], edi, esi, \
  170.            [ebx+STREAM.r_dt], ecx, eax
  171.  
  172.            mov ebx, [str]
  173.  
  174.            add [ebx+STREAM.out_count], eax;
  175.            add [ebx+STREAM.out_wp], eax;
  176.  
  177.            mov eax, [ebx+STREAM.in_rp]
  178.            mov ecx, [r_size]
  179.            add eax, ecx
  180.            add [ebx+STREAM.in_free], ecx
  181.            sub [ebx+STREAM.in_count], ecx
  182.  
  183.            cmp eax, [ebx+STREAM.in_top]
  184.            jb @f
  185.  
  186.            sub eax, [ebx+STREAM.in_size]
  187. @@:
  188.            mov [ebx+STREAM.in_rp], eax
  189.  
  190. .done:
  191.            mov eax, [ebx+STREAM.notify_event]
  192.            test eax, eax
  193.            jz .exit
  194.  
  195.            mov ebx, [ebx+STREAM.notify_id]
  196.            mov edx, EVENT_WATCHED
  197.            xor esi, esi
  198.            call RaiseEvent   ;eax, ebx, edx, esi
  199. .exit:
  200.            ret
  201. endp
  202.  
  203. align 4
  204. proc refill_ring stdcall, str:dword
  205.            locals
  206.              event     rd 6
  207.            endl
  208.  
  209.            mov ebx, [str]
  210.            mov edi, [ebx+STREAM.out_wp]
  211.            cmp edi, [ebx+STREAM.out_top]
  212.            jb @F
  213.            sub edi, 0x10000
  214.            mov [ebx+STREAM.out_wp], edi
  215. @@:
  216.            mov ecx, [ebx+STREAM.r_size]
  217.            mov eax, ecx
  218.            cmp word [ebx+STREAM.format], PCM_1_16_8
  219.            ja @F
  220.  
  221.            shr eax, 1                   ;two channles
  222. @@:
  223.            test [ebx+STREAM.format], 1  ;even formats mono
  224.            jz @F
  225.  
  226.            shr eax, 1                   ;eax= samples
  227. @@:
  228.            shl eax, 15    ;eax*=32768 =r_end
  229.  
  230.            mov esi, [ebx+STREAM.in_rp]
  231.            mov edi, [ebx+STREAM.out_wp]
  232.  
  233.            stdcall [ebx+STREAM.resample], edi, esi, \
  234.            [ebx+STREAM.r_dt], ecx, eax
  235.  
  236.            mov ebx, [str]
  237.  
  238.            add [ebx+STREAM.out_count], eax;
  239.            add [ebx+STREAM.out_wp], eax;
  240.  
  241.            mov eax, [ebx+STREAM.in_rp]
  242.            mov ecx, [ebx+STREAM.r_size]
  243.            add eax, ecx
  244.            add [ebx+STREAM.in_free], ecx
  245.            sub [ebx+STREAM.in_count], ecx
  246.  
  247.            cmp eax, [ebx+STREAM.in_top]
  248.            jb @f
  249.  
  250.            sub eax, [ebx+STREAM.in_size]
  251. @@:
  252.            mov [ebx+STREAM.in_rp], eax
  253.  
  254.            sub eax, [ebx+STREAM.in_base]
  255.            sub eax, 128
  256.            lea esi, [event]
  257.  
  258.            mov dword [esi], RT_INP_EMPTY
  259.            mov dword [esi+4], 0
  260.            mov dword [esi+8], ebx
  261.            mov dword [esi+12], eax
  262.  
  263.            mov eax, [ebx+STREAM.notify_event]
  264.            test eax, eax
  265.            jz .exit
  266.  
  267.            mov ebx, [ebx+STREAM.notify_id]
  268.            xor edx, edx
  269.            call RaiseEvent   ;eax, ebx, edx, esi
  270. .exit:
  271.            ret
  272. endp
  273.  
  274. if USE_SSE2_MIXER
  275.  
  276. align 4
  277. proc mix_all stdcall, dest:dword, list:dword, count:dword
  278.  
  279.            mov edi, [dest]
  280.            mov ebx, 32
  281. .mix:
  282.            mov edx, [list]
  283.            mov ecx, [count]
  284.  
  285.            mov eax, [edx]
  286.  
  287.            movdqa xmm1, [eax]
  288.            movss xmm2, [edx+4]
  289.            movss xmm3, [edx+8]
  290.  
  291.            punpcklwd xmm0, xmm1
  292.            punpckhwd xmm1, xmm1
  293.  
  294.            shufps xmm2, xmm3, 0
  295.            shufps xmm2, xmm2, 0x88
  296.  
  297.            psrad xmm0, 16
  298.            psrad xmm1, 16
  299.            cvtdq2ps xmm0, xmm0
  300.            cvtdq2ps xmm1, xmm1
  301.            mulps xmm0, xmm2
  302.            mulps xmm1, xmm2
  303.  
  304. .mix_loop:
  305.            add dword [edx], 16
  306.            add edx, 12
  307.            dec ecx
  308.            jz @F
  309.  
  310.            mov eax, [edx]
  311.  
  312.            movdqa xmm3, [eax]
  313.            movss xmm4, [edx+4]
  314.            movss xmm5, [edx+8]
  315.  
  316.            punpcklwd xmm2, xmm3
  317.            punpckhwd xmm3, xmm3
  318.  
  319.            shufps xmm4, xmm5, 0
  320.            shufps xmm4, xmm4, 0x88
  321.  
  322.            psrad xmm2, 16
  323.            psrad xmm3, 16
  324.  
  325.            cvtdq2ps xmm2, xmm2
  326.            cvtdq2ps xmm3, xmm3
  327.  
  328.            mulps xmm2, xmm4
  329.            mulps xmm3, xmm4
  330.            addps xmm0, xmm2
  331.            addps xmm1, xmm3
  332.  
  333.            jmp .mix_loop
  334. @@:
  335.            cvtps2dq xmm0, xmm0
  336.            cvtps2dq xmm1, xmm1
  337.            packssdw xmm0, xmm0
  338.            packssdw xmm1, xmm1
  339.            punpcklqdq xmm0, xmm1
  340.            movntdq [edi], xmm0
  341.  
  342.            add edi, 16
  343.            dec ebx
  344.            jnz .mix
  345.  
  346.            ret
  347. endp
  348.  
  349. ; param
  350. ;  edi = dest
  351. ;  edx = mix_list
  352.  
  353. align 4
  354. mix_fast:
  355.  
  356.            mov ebx, 32
  357.            mov eax, [edx]
  358.  
  359.            movss xmm2, [edx+4]       ; vol Lf
  360.            movss xmm3, [edx+8]       ; vol Rf
  361.            shufps xmm2, xmm3, 0      ; Rf Rf Lf Lf
  362.            shufps xmm2, xmm2, 0x88   ; volume level  Rf Lf Rf Lf
  363. .mix:
  364.            movdqa xmm1, [eax]        ; R3w L3w  R2w L2w  R1w L1w  R0w L0w
  365.            add eax, 16
  366.            punpcklwd xmm0, xmm1      ; R1w R1w  L1w L1W  R0w R0w  L0w L0w
  367.            punpckhwd xmm1, xmm1      ; R3w R3w  L3w L3w  R2w R2w  L2w L2w
  368.  
  369.            psrad xmm0, 16            ; R1d L1d R0d L0d
  370.            psrad xmm1, 16            ; R3d L3d R2d L2d
  371.  
  372.            cvtdq2ps xmm0, xmm0       ; time to use all power
  373.            cvtdq2ps xmm1, xmm1       ; of the dark side
  374.  
  375.            mulps xmm0, xmm2          ; R1f' L1f' R0f' L0f'
  376.            mulps xmm1, xmm2          ; R3f' L3f' R2f' L2f'
  377.  
  378.            cvtps2dq xmm0, xmm0       ; R1d' L1d' R0d' L0d'
  379.            cvtps2dq xmm1, xmm1       ; R3d' L3d' R2d' L2d'
  380.            packssdw xmm0, xmm0       ; R1w' L1w'  R0w' L0w'  R1w' L1w'  R0w' L0w'
  381.            packssdw xmm1, xmm1       ; R3w' L3w'  R2w' L2w'  R3w' L3w'  R2w' L2w'
  382.            punpcklqdq xmm0, xmm1     ; R3w' L3w'  R2w' L2w'  R1w' L1w'  R0w' L0w'
  383.            movntdq [edi], xmm0
  384.  
  385.            add edi, 16
  386.            dec ebx
  387.            jnz .mix
  388.  
  389.            ret
  390.  
  391. align 4
  392. mix_fast_2_stream:
  393.  
  394.            mov ebx, 32
  395.            mov eax, [edx]
  396.  
  397.            movss xmm4, [edx+4]       ; vol Lf
  398.            movss xmm5, [edx+8]       ; vol Rf
  399.            mov ecx, [edx+12]
  400.  
  401.            movss xmm6, [edx+16]      ; vol Lf
  402.            movss xmm7, [edx+20]      ; vol Rf
  403.  
  404.            shufps xmm4, xmm5, 0      ; Rf Rf Lf Lf
  405.            shufps xmm4, xmm4, 0x88   ; volume level  Rf Lf Rf Lf
  406.  
  407.            shufps xmm6, xmm7, 0      ; Rf Rf Lf Lf
  408.            shufps xmm6, xmm6, 0x88   ; volume level  Rf Lf Rf Lf
  409.  
  410. .mix:
  411.            movdqa xmm1, [eax]        ; R3w L3w  R2w L2w  R1w L1w  R0w L0w
  412.            movdqa xmm3, [ecx]        ; R3w L3w  R2w L2w  R1w L1w  R0w L0w
  413.  
  414.            add eax, 16
  415.            add ecx, 16
  416.  
  417.            punpcklwd xmm0, xmm1      ; R1w R1w  L1w L1W  R0w R0w  L0w L0w
  418.            punpckhwd xmm1, xmm1      ; R3w R3w  L3w L3w  R2w R2w  L2w L2w
  419.  
  420.            psrad xmm0, 16            ; R1d L1d R0d L0d
  421.            psrad xmm1, 16            ; R3d L3d R2d L2d
  422.  
  423.            cvtdq2ps xmm0, xmm0       ; time to use all power
  424.            cvtdq2ps xmm1, xmm1       ; of the dark side
  425.  
  426.            mulps xmm0, xmm4          ; R1f' L1f' R0f' L0f'
  427.            mulps xmm1, xmm4          ; R3f' L3f' R2f' L2f'
  428.  
  429.            punpcklwd xmm2, xmm3      ; R1w R1w  L1w L1W  R0w R0w  L0w L0w
  430.            punpckhwd xmm3, xmm3      ; R3w R3w  L3w L3w  R2w R2w  L2w L2w
  431.  
  432.            psrad xmm2, 16            ; R1d L1d R0d L0d
  433.            psrad xmm3, 16            ; R3d L3d R2d L2d
  434.  
  435.            cvtdq2ps xmm2, xmm2       ; time to use all power
  436.            cvtdq2ps xmm3, xmm3       ; of the dark side
  437.  
  438.            mulps xmm2, xmm6          ; R1f' L1f' R0f' L0f'
  439.            mulps xmm3, xmm6          ; R3f' L3f' R2f' L2f'
  440.  
  441.            addps xmm0, xmm2
  442.            addps xmm1, xmm3
  443.  
  444.            cvtps2dq xmm0, xmm0       ; R1d' L1d' R0d' L0d'
  445.            cvtps2dq xmm1, xmm1       ; R3d' L3d' R2d' L2d'
  446.            packssdw xmm0, xmm0       ; R1w' L1w'  R0w' L0w'  R1w' L1w'  R0w' L0w'
  447.            packssdw xmm1, xmm1       ; R3w' L3w'  R2w' L2w'  R3w' L3w'  R2w' L2w'
  448.            punpcklqdq xmm0, xmm1     ; R3w' L3w'  R2w' L2w'  R1w' L1w'  R0w' L0w'
  449.            movntdq [edi], xmm0
  450.  
  451.            add edi, 16
  452.            dec ebx
  453.            jnz .mix
  454.  
  455.            ret
  456.  
  457. else                                    ; fixed point mmx version
  458.  
  459. align 4
  460. proc mix_all stdcall, dest:dword, list:dword, count:dword
  461.  
  462.            mov edi, [dest]
  463.            mov ebx, 64
  464. .mix:
  465.            mov edx, [list]
  466.            mov ecx, [count]
  467.  
  468.            mov eax, [edx]
  469.  
  470.            movq mm0, [eax]
  471.  
  472.            movd mm1, [edx+4]
  473.            punpckldq mm1,mm1
  474.            pmulhw mm0, mm1
  475.            psllw  mm0, 1
  476.  
  477. .mix_loop:
  478.            add dword [edx], 8
  479.            add edx, 12
  480.            dec ecx
  481.            jz @F
  482.  
  483.            mov eax, [edx]
  484.            movq mm1, [eax]
  485.            movd mm2, [edx+4]
  486.            punpckldq mm2,mm2
  487.            pmulhw mm1, mm2
  488.            psllw  mm1, 1
  489.            paddsw mm0, mm1
  490.            jmp .mix_loop
  491. @@:
  492.            movq [edi], mm0
  493.            add edi, 8
  494.            dec ebx
  495.            jnz .mix
  496.  
  497.            ret
  498. endp
  499.  
  500. end if
  501.  
  502.  
  503. align 4
  504. proc resample_1 stdcall, dest:dword,src:dword,\
  505.                        r_dt:dword, r_size:dword,r_end:dword
  506.  
  507. ; dest equ esp+8
  508. ; src  equ esp+12
  509. ; r_dt equ esp+16
  510. ; r_size equ esp+20
  511. ; r_end equ esp+24
  512.  
  513.            mov edi, [dest]
  514.            mov edx, [src]
  515.            sub edx, 32*2
  516.            mov eax, 16
  517.  
  518. align 4
  519. .l1:
  520.            mov ecx, eax
  521.            mov esi, eax
  522.            and ecx, 0x7FFF
  523.            shr esi, 15
  524.            lea esi, [edx+esi*2]
  525.  
  526.            movsx ebp, word [esi]
  527.            movsx esi, word [esi+2]
  528.            mov ebx, 32768
  529.            imul esi, ecx
  530.            sub ebx, ecx
  531.            imul ebx, ebp
  532.            lea ecx, [ebx+esi+16384]
  533.            sar ecx, 15
  534.            cmp ecx, 32767         ; 00007fffH
  535.            jle @f
  536.            mov ecx, 32767         ; 00007fffH
  537.            jmp .write
  538. @@:
  539.            cmp ecx, -32768        ; ffff8000H
  540.            jge .write
  541.            mov ecx, -32768        ; ffff8000H
  542. .write:
  543.            mov ebx, ecx
  544.            shl ebx, 16
  545.            mov bx, cx
  546.            mov [edi], ebx
  547.            add edi, 4
  548.  
  549.            add eax, [esp+16]
  550.            cmp eax, [esp+24]
  551.            jb .l1
  552.  
  553.            mov ebp, esp
  554.  
  555.            sub edi, [dest]
  556.            mov eax, edi
  557.            ret
  558. endp
  559.  
  560. align 4
  561. proc resample_18 stdcall, dest:dword,src:dword,\
  562.                        r_dt:dword, r_size:dword,r_end:dword
  563.  
  564.  
  565.            mov edi, [dest]
  566.            mov edx, [src]
  567.            sub edx, 32
  568.  
  569.            mov esi, 16
  570.  
  571. align 4
  572. .l1:
  573.            mov ecx, esi
  574.            mov eax, esi
  575.            and ecx, 0x7FFF
  576.            shr eax, 15
  577.            lea eax, [edx+eax]
  578.  
  579.            mov bx, word [eax]
  580.            sub bh, 0x80
  581.            sub bl, 0x80
  582.            movsx eax, bh
  583.            shl eax,8
  584.            movsx ebp, bl
  585.            shl ebp,8
  586.            mov ebx, 32768
  587.            imul eax, ecx
  588.            sub ebx, ecx
  589.            imul ebx, ebp
  590.            lea ecx, [ebx+eax+16384]
  591.            sar ecx, 15
  592.            cmp ecx, 32767         ; 00007fffH
  593.            jle @f
  594.            mov ecx, 32767         ; 00007fffH
  595.            jmp .write
  596. @@:
  597.            cmp ecx, -32768        ; ffff8000H
  598.            jge .write
  599.            mov ecx, -32768        ; ffff8000H
  600. .write:
  601.            mov ebx, ecx
  602.            shl ebx, 16
  603.            mov bx, cx
  604.            mov [edi], ebx
  605.            add edi, 4
  606.  
  607.            add esi, [esp+16]
  608.            cmp esi, [esp+24]
  609.            jb .l1
  610.  
  611.            mov ebp, esp
  612.            sub edi, [dest]
  613.            mov eax, edi
  614.            ret
  615. endp
  616.  
  617. align 4
  618. proc copy_stream stdcall, dest:dword,src:dword,\
  619.                        r_dt:dword, r_size:dword,r_end:dword
  620.  
  621.            mov ecx, [r_size]
  622.            mov eax, ecx
  623.            shr ecx, 2
  624.            mov esi, [src]
  625.            mov edi, [dest]
  626.            cld
  627.            rep movsd
  628.            ret
  629. endp
  630.  
  631. align 4
  632. proc resample_2 stdcall, dest:dword,src:dword,\
  633.                        r_dt:dword, r_size:dword,r_end:dword
  634.  
  635.            mov edx, [src]
  636.            sub edx, 32*4
  637.            mov edi, [dest]
  638.            mov ebx, [r_dt]
  639.            mov eax, 16
  640.            emms
  641.  
  642. align 4
  643. .l1:
  644.            mov ecx, eax
  645.            mov esi, eax
  646.            and ecx, 0x7FFF
  647.            shr esi, 15
  648.            lea esi, [edx+esi*4]
  649.  
  650.            movq mm0, [esi]
  651.            movq mm1, mm0
  652.  
  653.            movd mm2, ecx
  654.            punpcklwd mm2, mm2
  655.            movq mm3, qword [m7]    ;0x8000
  656.  
  657.            psubw mm3, mm2 ;        ;0x8000 - iconst
  658.            punpckldq mm3, mm2
  659.  
  660.            pmulhw mm0, mm3
  661.            pmullw mm1, mm3
  662.  
  663.            movq mm4, mm1
  664.            punpcklwd mm1, mm0
  665.            punpckhwd mm4, mm0
  666.            paddd mm1, mm4
  667.            psrad  mm1, 15
  668.            packssdw mm1, mm1
  669.            movd [edi], mm1
  670.            add edi, 4
  671.  
  672.            add eax, ebx
  673.            cmp eax, [r_end]
  674.            jb .l1
  675.            emms
  676.  
  677.            sub edi, [dest]
  678.            mov eax, edi
  679.            ret
  680. endp
  681.  
  682. align 4
  683. proc resample_28 stdcall, dest:dword,src:dword,\
  684.                        r_dt:dword, r_size:dword,r_end:dword
  685.  
  686.            mov edx, [src]
  687.            sub edx, 32*2
  688.            mov edi, [dest]
  689.            mov ebx, [r_dt]
  690.            mov eax, 16
  691.            emms
  692.            movq mm7,[mm80]
  693.            movq mm6,[mm_mask]
  694.  
  695. align 4
  696. .l1:
  697.            mov ecx, eax
  698.            mov esi, eax
  699.            and ecx, 0x7FFF
  700.            shr esi, 15
  701.            lea esi, [edx+esi*2]
  702.  
  703.            movq mm0, [esi]
  704.            psubb mm0,mm7
  705.            punpcklbw mm0,mm0
  706.            pand mm0,mm6
  707.  
  708.            movq mm1, mm0
  709.  
  710.            movd mm2, ecx
  711.            punpcklwd mm2, mm2
  712.            movq mm3, qword [m7] ;                  // 0x8000
  713.  
  714.            psubw mm3, mm2       ;         // 0x8000 - iconst
  715.            punpckldq mm3, mm2
  716.  
  717.            pmulhw mm0, mm3
  718.            pmullw mm1, mm3
  719.  
  720.            movq mm4, mm1
  721.            punpcklwd mm1, mm0
  722.            punpckhwd mm4, mm0
  723.            paddd mm1, mm4
  724.            psrad  mm1, 15
  725.            packssdw mm1, mm1
  726.            movd [edi], mm1
  727.            add edi, 4
  728.  
  729.            add eax, ebx
  730.            cmp eax, [r_end]
  731.            jb .l1
  732.            emms
  733.  
  734.  
  735.            sub edi, [dest]
  736.            mov eax, edi
  737.            ret
  738. endp
  739.  
  740.  
  741. proc m16_stereo stdcall, dest:dword,src:dword,\
  742.                        r_dt:dword, r_size:dword,r_end:dword
  743.  
  744.            mov esi, [src]
  745.            mov edi, [dest]
  746.            mov ecx, [r_size]
  747.            shr ecx,8
  748. @@:
  749.            call m16_s_mmx
  750.            add edi, 128
  751.            add esi, 64
  752.            call m16_s_mmx
  753.            add edi, 128
  754.            add esi, 64
  755.            call m16_s_mmx
  756.            add edi, 128
  757.            add esi, 64
  758.            call m16_s_mmx
  759.            add edi, 128
  760.            add esi, 64
  761.            dec ecx
  762.            jnz @b
  763.  
  764.            mov eax, [r_size]
  765.            add eax, eax
  766.            ret
  767. endp
  768.  
  769. align 4
  770. proc s8_stereo stdcall, dest:dword,src:dword,\
  771.                        r_dt:dword, r_size:dword,r_end:dword
  772.  
  773.            mov esi, [src]
  774.            mov edi, [dest]
  775.            mov ecx, [r_size]
  776.            shr ecx, 7
  777.  
  778.            movq mm7, [mm80]
  779.            movq mm6, [mm_mask]
  780. @@:
  781.            call s8_s_mmx
  782.            add edi, 64
  783.            add esi, 32
  784.            call s8_s_mmx
  785.            add edi, 64
  786.            add esi, 32
  787.            call s8_s_mmx
  788.            add edi, 64
  789.            add esi, 32
  790.            call s8_s_mmx
  791.            add edi, 64
  792.            add esi, 32
  793.            dec ecx
  794.            jnz @b
  795.  
  796.            mov eax, [r_size]
  797.            add eax, eax
  798.            ret
  799. endp
  800.  
  801. proc m8_stereo stdcall, dest:dword,src:dword,\
  802.                        r_dt:dword, r_size:dword,r_end:dword
  803.  
  804.            mov esi, [src]
  805.            mov edi, [dest]
  806.            mov ecx, [r_size]
  807.            shr ecx, 6
  808.  
  809.            movq mm7, [mm80]
  810.            movq mm6, [mm_mask]
  811. @@:
  812.            call m8_s_mmx
  813.            add edi, 64
  814.            add esi, 16
  815.            call m8_s_mmx
  816.            add edi, 64
  817.            add esi, 16
  818.            call m8_s_mmx
  819.            add edi, 64
  820.            add esi, 16
  821.            call m8_s_mmx
  822.            add edi, 64
  823.            add esi, 16
  824.                   dec ecx
  825.            jnz @b
  826.  
  827.            mov eax, [r_size]
  828.            add eax, eax
  829.            add eax, eax
  830.            ret
  831. endp
  832.  
  833. align 4
  834. proc alloc_mix_buff
  835.  
  836.            bsf eax, [mix_buff_map]
  837.            jnz .find
  838.            xor eax, eax
  839.            ret
  840. .find:
  841.            btr [mix_buff_map], eax
  842.            shl eax, 9
  843.            add eax, [mix_buff]
  844.            ret
  845. endp
  846.  
  847. align 4
  848. proc m16_s_mmx
  849.  
  850.            movq    mm0, [esi]
  851.            movq    mm1, mm0
  852.            punpcklwd mm0, mm0
  853.            punpckhwd mm1, mm1
  854.            movq    [edi], mm0
  855.            movq    [edi+8], mm1
  856.  
  857.            movq    mm0, [esi+8]
  858.            movq    mm1, mm0
  859.            punpcklwd mm0, mm0
  860.            punpckhwd mm1, mm1
  861.            movq    [edi+16], mm0
  862.            movq    [edi+24], mm1
  863.  
  864.            movq    mm0, [esi+16]
  865.            movq    mm1, mm0
  866.            punpcklwd mm0, mm0
  867.            punpckhwd mm1, mm1
  868.            movq    [edi+32], mm0
  869.            movq    [edi+40], mm1
  870.  
  871.            movq    mm0, [esi+24]
  872.            movq    mm1, mm0
  873.            punpcklwd mm0, mm0
  874.            punpckhwd mm1, mm1
  875.            movq    [edi+48], mm0
  876.            movq    [edi+56], mm1
  877.  
  878.            movq    mm0, [esi+32]
  879.            movq    mm1, mm0
  880.            punpcklwd mm0, mm0
  881.            punpckhwd mm1, mm1
  882.            movq    [edi+64], mm0
  883.            movq    [edi+72], mm1
  884.  
  885.            movq    mm0, [esi+40]
  886.            movq    mm1, mm0
  887.            punpcklwd mm0, mm0
  888.            punpckhwd mm1, mm1
  889.            movq    [edi+80], mm0
  890.            movq    [edi+88], mm1
  891.  
  892.  
  893.            movq    mm0, [esi+48]
  894.            movq    mm1, mm0
  895.            punpcklwd mm0, mm0
  896.            punpckhwd mm1, mm1
  897.            movq    [edi+96], mm0
  898.            movq    [edi+104], mm1
  899.  
  900.            movq    mm0, [esi+56]
  901.            movq    mm1, mm0
  902.            punpcklwd mm0, mm0
  903.            punpckhwd mm1, mm1
  904.            movq    [edi+112], mm0
  905.            movq    [edi+120], mm1
  906.  
  907.            ret
  908. endp
  909.  
  910. align 4
  911. proc s8_s_mmx
  912.  
  913.            movq    mm0, [esi]
  914.            psubb   mm0, mm7
  915.            movq    mm1, mm0
  916.            punpcklbw mm0, mm0
  917.            pand mm0, mm6
  918.            punpckhbw mm1, mm1
  919.            pand mm1, mm6
  920.            movq    [edi], mm0
  921.            movq    [edi+8], mm1
  922.  
  923.            movq    mm0, [esi+8]
  924.            psubb   mm0, mm7
  925.            movq    mm1, mm0
  926.            punpcklbw mm0, mm0
  927.            pand mm0, mm6
  928.            punpckhbw mm1, mm1
  929.            pand mm1, mm6
  930.            movq    [edi+16], mm0
  931.            movq    [edi+24], mm1
  932.  
  933.            movq    mm0, [esi+16]
  934.            psubb   mm0, mm7
  935.            movq    mm1, mm0
  936.            punpcklbw mm0, mm0
  937.            pand mm0, mm6
  938.            punpckhbw mm1, mm1
  939.            pand mm1, mm6
  940.            movq    [edi+32], mm0
  941.            movq    [edi+40], mm1
  942.  
  943.            movq    mm0, [esi+24]
  944.            psubb   mm0, mm7
  945.            movq    mm1, mm0
  946.            punpcklbw mm0, mm0
  947.            pand    mm0, mm6
  948.            punpckhbw mm1, mm1
  949.            pand    mm1, mm6
  950.            movq    [edi+48], mm0
  951.            movq    [edi+56], mm1
  952.  
  953.            ret
  954.  
  955. endp
  956.  
  957. align 4
  958. proc m8_s_mmx
  959.  
  960.            movq    mm0, [esi]
  961.            psubb   mm0, mm7
  962.            movq    mm1, mm0
  963.            punpcklbw mm0, mm0
  964.            pand mm0, mm6
  965.            punpckhbw mm1, mm1
  966.            pand mm1, mm6
  967.            movq mm2, mm0
  968.            punpcklwd mm0, mm0
  969.            punpckhwd mm2, mm2
  970.  
  971.            movq mm3, mm1
  972.            punpcklwd mm1, mm1
  973.            punpckhwd mm3, mm3
  974.  
  975.            movq    [edi], mm0
  976.            movq    [edi+8], mm2
  977.            movq    [edi+16], mm1
  978.            movq    [edi+24], mm3
  979.  
  980.            movq    mm0, [esi+8]
  981.            psubb   mm0, mm7
  982.            movq    mm1, mm0
  983.            punpcklbw mm0, mm0
  984.            pand mm0, mm6
  985.            punpckhbw mm1, mm1
  986.            pand mm1, mm6
  987.            movq mm2, mm0
  988.            punpcklwd mm0, mm0
  989.            punpckhwd mm2, mm2
  990.  
  991.            movq mm3, mm1
  992.            punpcklwd mm1, mm1
  993.            punpckhwd mm3, mm3
  994.  
  995.            movq    [edi+32], mm0
  996.            movq    [edi+40], mm2
  997.            movq    [edi+48], mm1
  998.            movq    [edi+56], mm3
  999.  
  1000.            ret
  1001. endp
  1002.  
  1003. align 4
  1004. proc mix_2_1 stdcall, output:dword, str0:dword, str1:dword
  1005.  
  1006.            mov edi, [output]
  1007.            mov eax, [str0]
  1008.            mov ebx, [str1]
  1009.            mov esi, 128
  1010.            call [mix_2_core]   ;edi, eax, ebx
  1011.  
  1012.            add edi, esi
  1013.            add eax, esi
  1014.            add ebx, esi
  1015.            call [mix_2_core]   ;edi, eax, ebx
  1016.  
  1017.            add edi, esi
  1018.            add eax, esi
  1019.            add ebx, esi
  1020.            call [mix_2_core]   ;edi, eax, ebx
  1021.  
  1022.            add edi, esi
  1023.            add eax, esi
  1024.            add ebx, esi
  1025.            call [mix_2_core]   ;edi, eax, ebx
  1026.            ret
  1027. endp
  1028.  
  1029. align 4
  1030. proc mix_3_1 stdcall, output:dword, str0:dword, str1:dword, str2:dword
  1031.  
  1032.            mov edi, [output]
  1033.            mov eax, [str0]
  1034.            mov ebx, [str1]
  1035.            mov ecx, [str2]
  1036.            mov esi, 128
  1037.            call [mix_3_core]
  1038.  
  1039.            add edi, esi
  1040.            add eax, esi
  1041.            add ebx, esi
  1042.            add ecx, esi
  1043.            call [mix_3_core]
  1044.  
  1045.            add edi, esi
  1046.            add eax, esi
  1047.            add ebx, esi
  1048.            add ecx, esi
  1049.            call [mix_3_core]
  1050.  
  1051.            add edi, esi
  1052.            add eax, esi
  1053.            add ebx, esi
  1054.            add ecx, esi
  1055.            call [mix_3_core]
  1056.            ret
  1057. endp
  1058.  
  1059. align 4
  1060. proc mix_4_1 stdcall, str0:dword, str1:dword,\
  1061.                       str2:dword, str3:dword
  1062.  
  1063.            local output:DWORD
  1064.  
  1065.            call alloc_mix_buff
  1066.            and eax, eax
  1067.            jz .err
  1068.  
  1069.            mov [output], eax
  1070.  
  1071.            mov edi, eax
  1072.            mov eax, [str0]
  1073.            mov ebx, [str1]
  1074.            mov ecx, [str2]
  1075.            mov edx, [str3]
  1076.            mov esi, 128
  1077.            call [mix_4_core]  ;edi, eax, ebx, ecx, edx
  1078.  
  1079.            add edi, esi
  1080.            add eax, esi
  1081.            add ebx, esi
  1082.            add ecx, esi
  1083.            add edx, esi
  1084.            call [mix_4_core]  ;edi, eax, ebx, ecx, edx
  1085.  
  1086.            add edi, esi
  1087.            add eax, esi
  1088.            add ebx, esi
  1089.            add ecx, esi
  1090.            add edx, esi
  1091.            call [mix_4_core]  ;edi, eax, ebx, ecx, edx
  1092.  
  1093.            add edi, esi
  1094.            add eax, esi
  1095.            add ebx, esi
  1096.            add ecx, esi
  1097.            add edx, esi
  1098.            call [mix_4_core]  ;edi, eax, ebx, ecx, edx
  1099.            mov eax, [output]
  1100.            ret
  1101. .err:
  1102.            xor eax, eax
  1103.            ret
  1104. endp
  1105.  
  1106.  
  1107. align 4
  1108. proc final_mix stdcall, output:dword, str0:dword, str1:dword,\
  1109.                         str2:dword, str3:dword
  1110.  
  1111.            mov edi, [output]
  1112.  
  1113.            mov eax, [str0]
  1114.            mov ebx, [str1]
  1115.            mov ecx, [str2]
  1116.            mov edx, [str3]
  1117.            mov esi, 128
  1118.            call [mix_4_core]  ;edi, eax, ebx, ecx, edx
  1119.  
  1120.            add edi, esi
  1121.            add eax, esi
  1122.            add ebx, esi
  1123.            add ecx, esi
  1124.            add edx, esi
  1125.            call [mix_4_core]  ;edi, eax, ebx, ecx, edx
  1126.  
  1127.            add edi, esi
  1128.            add eax, esi
  1129.            add ebx, esi
  1130.            add ecx, esi
  1131.            add edx, esi
  1132.            call [mix_4_core]  ;edi, eax, ebx, ecx, edx
  1133.  
  1134.            add edi, esi
  1135.            add eax, esi
  1136.            add ebx, esi
  1137.            add ecx, esi
  1138.            add edx, esi
  1139.            call [mix_4_core]  ;edi, eax, ebx, ecx, edx
  1140.            ret
  1141. endp
  1142.  
  1143. align 4
  1144. proc copy_mem stdcall, output:dword, input:dword
  1145.  
  1146.            mov edi, [output]
  1147.            mov esi, [input]
  1148.            mov ecx, 0x80
  1149. .l1:
  1150.            mov eax, [esi]
  1151.            mov [edi], eax
  1152.            add esi, 4
  1153.            add edi, 4
  1154.            loop .l1
  1155.  
  1156.            ret
  1157. endp
  1158.  
  1159. proc memcpy
  1160. @@:
  1161.            mov eax, [esi]
  1162.            mov [edi], eax
  1163.            add esi, 4
  1164.            add edi, 4
  1165.            dec ecx
  1166.            jnz @B
  1167.            ret
  1168. endp
  1169.  
  1170. if 0
  1171.  
  1172. align 4
  1173. proc new_mix stdcall, output:dword
  1174.            locals
  1175.              mixCounter  dd ?
  1176.              mixIndex  dd ?
  1177.              streamIndex dd ?
  1178.              inputCount  dd ?
  1179.              main_count  dd ?
  1180.              blockCount  dd ?
  1181.              mix_out  dd ?
  1182.            endl
  1183.  
  1184.            call prepare_playlist
  1185.  
  1186.            cmp [play_count], 0
  1187.            je .exit
  1188.            call FpuSave
  1189.            mov [main_count], 32;
  1190. .l00:
  1191.            mov [mix_buff_map], 0x0000FFFF;
  1192.            xor eax, eax
  1193.            mov [mixCounter], eax
  1194.            mov [mixIndex],eax
  1195.            mov [streamIndex], eax;
  1196.            mov ebx, [play_count]
  1197.            mov [inputCount], ebx
  1198. .l0:
  1199.            mov ecx, 4
  1200. .l1:
  1201.            mov ebx, [streamIndex]
  1202.            mov esi, [play_list+ebx*4]
  1203.            mov eax, [esi+STREAM.work_read]
  1204.            add [esi+STREAM.work_read], 512
  1205.  
  1206.            mov ebx, [mixIndex]
  1207.            mov [mix_input+ebx*4], eax
  1208.            inc [mixCounter]
  1209.            inc [mixIndex]
  1210.            inc [streamIndex]
  1211.            dec [inputCount]
  1212.            jz .m2
  1213.  
  1214.            dec ecx
  1215.            jnz .l1
  1216.  
  1217.            cmp [mixCounter], 4
  1218.            jnz .m2
  1219.  
  1220.            stdcall mix_4_1, [mix_input],[mix_input+4],[mix_input+8],[mix_input+12]
  1221.            sub [mixIndex],4
  1222.            mov ebx, [mixIndex]
  1223.            mov [mix_input+ebx*4], eax
  1224.            inc [mixIndex]
  1225.            mov [mixCounter], 0
  1226.  
  1227.            cmp [inputCount], 0
  1228.            jnz .l0
  1229. .m2:
  1230.            cmp [mixIndex], 1
  1231.            jne @f
  1232.            stdcall copy_mem, [output], [mix_input]
  1233.            jmp .m3
  1234. @@:
  1235.            cmp [mixIndex], 2
  1236.            jne @f
  1237.            stdcall mix_2_1, [output], [mix_input], [mix_input+4]
  1238.            jmp .m3
  1239. @@:
  1240.            cmp [mixIndex], 3
  1241.            jne @f
  1242.            stdcall mix_3_1, [output],[mix_input],[mix_input+4],[mix_input+8]
  1243.            jmp .m3
  1244. @@:
  1245.            stdcall final_mix, [output],[mix_input],[mix_input+4],[mix_input+8], [mix_input+12]
  1246. .m3:
  1247.            add [output],512
  1248.  
  1249.            dec [main_count]
  1250.            jnz .l00
  1251.  
  1252.            call update_stream
  1253.            emms
  1254.            call FpuRestore
  1255.            ret
  1256. .exit:
  1257.            mov edi, [output]
  1258.            mov ecx, 0x1000
  1259.            xor eax, eax
  1260.            cld
  1261.            rep stosd
  1262.            ret
  1263. endp
  1264.  
  1265. end if
  1266.