home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Priss / source / convert.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  18.1 KB  |  832 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Audio processing library
  3. //    Copyright (C) 1998-2004 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <vd2/system/cpuaccel.h>
  20. #include <vd2/Priss/convert.h>
  21.  
  22. ///////////////////////////////////////////////////////////////////////////
  23. //
  24. //    scalar implementations
  25. //
  26. ///////////////////////////////////////////////////////////////////////////
  27.  
  28. void VDAPIENTRY VDConvertPCM32FToPCM8(void *dst0, const void *src0, uint32 samples) {
  29.     if (!samples)
  30.         return;
  31.  
  32.     uint8 *dst = (uint8 *)dst0;
  33.     const float *src = (const float *)src0;
  34.  
  35.     do {
  36.         const float ftmp = 98304.0f + *src++;
  37.         sint32 v = reinterpret_cast<const sint32&>(ftmp) - 0x47bfff80;
  38.  
  39.         if ((uint32)v >= 256)
  40.             v = (~v) >> 31;
  41.  
  42.         *dst++ = (uint8)v;
  43.     } while(--samples);
  44. }
  45.  
  46. void VDAPIENTRY VDConvertPCM32FToPCM16(void *dst0, const void *src0, uint32 samples) {
  47.     if (!samples)
  48.         return;
  49.  
  50.     sint16 *dst = (sint16 *)dst0;
  51.     const float *src = (const float *)src0;
  52.  
  53.     do {
  54.         const float ftmp = 384.0f + *src++;
  55.         sint32 v = reinterpret_cast<const sint32&>(ftmp) - 0x43bf8000;
  56.  
  57.         if ((uint32)v >= 0x10000)
  58.             v = (~v) >> 31;
  59.  
  60.         *dst++ = (sint16)(v - 0x8000);
  61.     } while(--samples);
  62. }
  63.  
  64. void VDAPIENTRY VDConvertPCM16ToPCM8(void *dst0, const void *src0, uint32 samples) {
  65.     if (!samples)
  66.         return;
  67.  
  68.     uint8 *dst = (uint8 *)dst0;
  69.     const sint16 *src = (const sint16 *)src0;
  70.  
  71.     do {
  72.         *dst++ = (uint8)((*src++ >> 8)^0x80);
  73.     } while(--samples);
  74. }
  75.  
  76. void VDAPIENTRY VDConvertPCM16ToPCM32F(void *dst0, const void *src0, uint32 samples) {
  77.     if (!samples)
  78.         return;
  79.  
  80.     float *dst = (float *)dst0;
  81.     const sint16 *src = (const sint16 *)src0;
  82.  
  83.     do {
  84.         *dst++ = (float)*src++ * (1.0f / 32768.0f);
  85.     } while(--samples);
  86. }
  87.  
  88. void VDAPIENTRY VDConvertPCM8ToPCM16(void *dst0, const void *src0, uint32 samples) {
  89.     if (!samples)
  90.         return;
  91.  
  92.     sint16 *dst = (sint16 *)dst0;
  93.     const uint8 *src = (const uint8 *)src0;
  94.  
  95.     do {
  96.         *dst++ = (sint16)(((int)*src++ - 0x80) << 8);
  97.     } while(--samples);
  98. }
  99.  
  100. void VDAPIENTRY VDConvertPCM8ToPCM32F(void *dst0, const void *src0, uint32 samples) {
  101.     if (!samples)
  102.         return;
  103.  
  104.     float *dst = (float *)dst0;
  105.     const uint8 *src = (const uint8 *)src0;
  106.  
  107.     do {
  108.         *dst++ = (float)((int)*src++ - 0x80) * (1.0f / 128.0f);
  109.     } while(--samples);
  110. }
  111.  
  112. sint16 VDAPIENTRY VDAudioFilterPCM16(const sint16 *src, const sint16 *filter, uint32 filterquadsize) {
  113.     sint32 v = 0x2000;
  114.  
  115.     const uint32 n = filterquadsize*4;
  116.     for(uint32 j=0; j<n; j+=4) {
  117.         v += (sint32)filter[j  ] * (sint32)src[j  ];
  118.         v += (sint32)filter[j+1] * (sint32)src[j+1];
  119.         v += (sint32)filter[j+2] * (sint32)src[j+2];
  120.         v += (sint32)filter[j+3] * (sint32)src[j+3];
  121.     }
  122.  
  123.     v = (v>>14) + 0x8000;
  124.  
  125.     if ((uint32)v >= 0x10000)
  126.         v = ~v >> 31;
  127.  
  128.     return (sint16)(v - 0x8000);
  129. }
  130.  
  131. void VDAPIENTRY VDAudioFilterPCM16End() {
  132. }
  133.  
  134. void VDAPIENTRY VDAudioFilterPCM16SymmetricArray(sint16 *dst, ptrdiff_t dst_stride, const sint16 *src, uint32 count, const sint16 *filter, uint32 filterquadsizeminus1) {
  135.     uint32 filterelsizeminus4 = filterquadsizeminus1*4;
  136.  
  137.     filter += filterquadsizeminus1*4;
  138.     src += filterquadsizeminus1*4;
  139.  
  140.     for(uint32 i=0; i<count; ++i) {
  141.         sint32 v = 0x2000 + (sint32)filter[0] * src[i];
  142.  
  143.         for(uint32 j=1; j<=filterelsizeminus4; j+=4) {
  144.             int k = -(int)j;
  145.             v += (sint32)filter[j  ] * ((sint32)src[i+j  ] + (sint32)src[i+k  ]);
  146.             v += (sint32)filter[j+1] * ((sint32)src[i+j+1] + (sint32)src[i+k-1]);
  147.             v += (sint32)filter[j+2] * ((sint32)src[i+j+2] + (sint32)src[i+k-2]);
  148.             v += (sint32)filter[j+3] * ((sint32)src[i+j+3] + (sint32)src[i+k-3]);
  149.         }
  150.  
  151.         v = (v>>14) + 0x8000;
  152.  
  153.         if ((uint32)v >= 0x10000)
  154.             v = ~v >> 31;
  155.  
  156.         *dst = (sint16)(v - 0x8000);
  157.         dst += dst_stride;
  158.     }
  159. }
  160.  
  161.  
  162. #ifdef _M_IX86
  163.  
  164. ///////////////////////////////////////////////////////////////////////////
  165. //
  166. //    MMX implementations
  167. //
  168. ///////////////////////////////////////////////////////////////////////////
  169.  
  170. #ifdef _MSC_VER
  171.     #pragma warning(disable: 4799)        // warning C4799: function has no MMX instruction
  172. #endif
  173.  
  174. namespace {
  175.     const __int64 x80b = 0x8080808080808080;
  176. }
  177.  
  178. void __declspec(naked) VDAPIENTRY VDConvertPCM16ToPCM8_MMX(void *dst0, const void *src0, uint32 samples) {
  179.  
  180.     __asm {
  181.         mov            eax, [esp+12]
  182.         mov            ecx, [esp+8]
  183.         mov            edx, [esp+4]
  184.         or            eax, eax
  185.         jz            xit
  186.  
  187.         movq        mm7, x80b
  188.         neg            eax
  189.         add            eax, 7
  190.         jc            nodq
  191.  
  192.         ;process quads (8n samples)
  193. dqloop:
  194.         movq        mm0, [ecx]
  195.         movq        mm1, [ecx+8]
  196.         psrlw        mm0, 8
  197.         add            edx, 8
  198.         psrlw        mm1, 8
  199.         add            ecx, 16
  200.         packuswb    mm0, mm1
  201.         pxor        mm0, mm7
  202.         add            eax, 8
  203.         movq        [edx-8], mm0
  204.         ja            dqloop
  205. nodq:
  206.         cmp            eax, 3
  207.         jg            noq
  208.         add            eax, 4
  209.  
  210.         ;process leftover quad (4 samples)
  211.         movq        mm0, [ecx]
  212.         add            edx, 4
  213.         psrlw        mm0, 8
  214.         packuswb    mm0, mm0
  215.         add            ecx, 8
  216.         pxor        mm0, mm7
  217.         movd        [edx-4], mm0
  218. noq:
  219.         sub            eax, 7
  220.         jz            xit2
  221.  
  222.         ;process leftover samples
  223.         movd        mm0, ebx
  224. singleloop:
  225.         mov            bl, byte ptr [ecx+1]
  226.         add            ecx, 2
  227.         xor            bl, 80h
  228.         mov            byte ptr [edx], bl
  229.         inc            edx
  230.         inc            eax
  231.         jne            singleloop
  232.         movd        ebx, mm0
  233. xit2:
  234.         emms
  235. xit:
  236.         ret
  237.     }
  238. }
  239.  
  240. void __declspec(naked) VDAPIENTRY VDConvertPCM8ToPCM16_MMX(void *dst0, const void *src0, uint32 samples) {
  241.     __asm {
  242.         mov        eax, [esp+12]
  243.         mov        ecx, [esp+8]
  244.         mov        edx, [esp+4]
  245.         or        eax, eax
  246.         jz        xit
  247.  
  248.         movq        mm7, x80b
  249.         neg            eax
  250.         movq        mm0, mm7
  251.         add            eax, 7
  252.         jc            nodq
  253.  
  254.         ;process quads (8n samples)
  255. dqloop:
  256.         pxor        mm0, [ecx]
  257.         pxor        mm1, mm1
  258.         add            edx, 16
  259.         punpcklbw    mm1, mm0
  260.         add            ecx, 8
  261.         pxor        mm2, mm2
  262.         punpckhbw    mm2, mm0
  263.         add            eax, 8
  264.         movq        [edx-16], mm1
  265.         movq        mm0, mm7
  266.         movq        [edx-8], mm2
  267.         ja            dqloop
  268. nodq:
  269.         cmp            eax, 3
  270.         jg            noq
  271.         add            eax, 4
  272.  
  273.         ;process leftover quad (4 samples)
  274.         movd        mm0, [ecx]
  275.         pxor        mm1, mm1
  276.         pxor        mm0, mm7
  277.         add            edx, 8
  278.         punpcklbw    mm1, mm0
  279.         add            ecx, 4
  280.         movq        [edx-8], mm1
  281. noq:
  282.         sub            eax, 7
  283.         jz            xit2
  284.  
  285.         ;process leftover samples
  286.         movd        mm0, ebx
  287. singleloop:
  288.         movzx        ebx, byte ptr [ecx]
  289.         add            edx, 2
  290.         shl            ebx, 8
  291.         inc            ecx
  292.         xor            ebx, 8000h
  293.         inc            eax
  294.         mov            word ptr [edx-2], bx
  295.         jne            singleloop
  296.         movd        ebx, mm0
  297. xit2:
  298.         emms
  299. xit:
  300.         ret
  301.     }
  302. }
  303.  
  304.  
  305. sint16 __declspec(naked) VDAPIENTRY VDAudioFilterPCM16_MMX(const sint16 *src, const sint16 *filter, uint32 filterquadsize) {
  306.     static const uint64 roundconst = 0x0000200000002000;
  307.  
  308.     __asm {
  309.         mov        eax,[esp+12]
  310.         mov        ecx,[esp+4]
  311.         shl        eax,3
  312.         mov        edx,[esp+8]
  313.         movq    mm0,roundconst
  314.         add        ecx, eax
  315.         add        edx, eax
  316.         neg        eax
  317. xloop:
  318.         movq    mm1,[ecx+eax]
  319.         pmaddwd    mm1,[edx+eax]
  320.         add        eax,8
  321.         paddd    mm0,mm1
  322.         jne        xloop
  323.  
  324.         punpckldq    mm1,mm0
  325.         paddd        mm0,mm1
  326.         psrad        mm0,14
  327.         packssdw    mm0,mm0
  328.         psrlq        mm0,48
  329.         movd    eax, mm0
  330.         ret
  331.     }
  332. }
  333.  
  334. sint16 __declspec(naked) VDAPIENTRY VDAudioFilterPCM16_128_MMX(const sint16 *src, const sint16 *filter, uint32 filterquadsize) {
  335.     static const uint64 roundconst = 0x0000200000002000;
  336.  
  337.     __asm {
  338.         mov        eax,[esp+12]
  339.         mov        ecx,[esp+4]
  340.         mov        edx,[esp+8]
  341.  
  342.         movq    mm4,roundconst        ;1
  343.         movq    mm0,[ecx+  0]        ;1
  344.         pmaddwd    mm0,[edx+  0]        ;2
  345.         movq    mm1,[ecx+  8]        ;1
  346.         pmaddwd    mm1,[edx+  8]        ;1
  347.         movq    mm2,[ecx+ 16]        ;2
  348.         pmaddwd    mm2,[edx+ 16]        ;1
  349.         movq    mm3,[ecx+ 24]        ;1
  350.         pmaddwd    mm3,[edx+ 24]        ;2
  351.  
  352.         paddd    mm0,mm4                ;1
  353.         movq    mm4,[ecx+ 32]        ;1
  354.         pmaddwd    mm4,[edx+ 32]        ;2
  355.         movq    mm5,[ecx+ 40]        ;1
  356.         pmaddwd    mm5,[edx+ 40]        ;2
  357.         movq    mm6,[ecx+ 48]        ;1
  358.         pmaddwd    mm6,[edx+ 48]        ;2
  359.         movq    mm7,[ecx+ 56]        ;1
  360.         pmaddwd    mm7,[edx+ 56]        ;2
  361.  
  362.         paddd    mm0,mm4                ;1
  363.         movq    mm4,[ecx+ 64]        ;1
  364.         pmaddwd    mm4,[edx+ 64]        ;2
  365.         paddd    mm1,mm5                ;1
  366.         movq    mm5,[ecx+ 72]        ;1
  367.         pmaddwd    mm5,[edx+ 72]        ;2
  368.         paddd    mm2,mm6                ;1
  369.         movq    mm6,[ecx+ 80]        ;1
  370.         pmaddwd    mm6,[edx+ 80]        ;2
  371.         paddd    mm3,mm7                ;1
  372.         movq    mm7,[ecx+ 88]        ;1
  373.         pmaddwd    mm7,[edx+ 88]        ;2
  374.  
  375.         paddd    mm0,mm4                ;1
  376.         movq    mm4,[ecx+ 96]        ;1
  377.         pmaddwd    mm4,[edx+ 96]        ;2
  378.         paddd    mm1,mm5                ;1
  379.         movq    mm5,[ecx+104]        ;1
  380.         pmaddwd    mm5,[edx+104]        ;2
  381.         paddd    mm2,mm6                ;1
  382.         movq    mm6,[ecx+112]        ;1
  383.         pmaddwd    mm6,[edx+112]        ;2
  384.         paddd    mm3,mm7                ;1
  385.         movq    mm7,[ecx+120]        ;1
  386.         pmaddwd    mm7,[edx+120]        ;2
  387.  
  388.         paddd    mm0,mm4                ;1
  389.         movq    mm4,[ecx+128]        ;1
  390.         pmaddwd    mm4,[edx+128]        ;2
  391.         paddd    mm1,mm5                ;1
  392.         movq    mm5,[ecx+136]        ;1
  393.         pmaddwd    mm5,[edx+136]        ;2
  394.         paddd    mm2,mm6                ;1
  395.         movq    mm6,[ecx+144]        ;1
  396.         pmaddwd    mm6,[edx+144]        ;2
  397.         paddd    mm3,mm7                ;1
  398.         movq    mm7,[ecx+152]        ;1
  399.         pmaddwd    mm7,[edx+152]        ;2
  400.  
  401.         paddd    mm0,mm4                ;1
  402.         movq    mm4,[ecx+160]        ;1
  403.         pmaddwd    mm4,[edx+160]        ;2
  404.         paddd    mm1,mm5                ;1
  405.         movq    mm5,[ecx+168]        ;1
  406.         pmaddwd    mm5,[edx+168]        ;2
  407.         paddd    mm2,mm6                ;1
  408.         movq    mm6,[ecx+176]        ;1
  409.         pmaddwd    mm6,[edx+176]        ;2
  410.         paddd    mm3,mm7                ;1
  411.         movq    mm7,[ecx+184]        ;1
  412.         pmaddwd    mm7,[edx+184]        ;2
  413.  
  414.         paddd    mm0,mm4                ;1
  415.         movq    mm4,[ecx+192]        ;1
  416.         pmaddwd    mm4,[edx+192]        ;2
  417.         paddd    mm1,mm5                ;1
  418.         movq    mm5,[ecx+200]        ;1
  419.         pmaddwd    mm5,[edx+200]        ;2
  420.         paddd    mm2,mm6                ;1
  421.         movq    mm6,[ecx+208]        ;1
  422.         pmaddwd    mm6,[edx+208]        ;2
  423.         paddd    mm3,mm7                ;1
  424.         movq    mm7,[ecx+216]        ;1
  425.         pmaddwd    mm7,[edx+216]        ;2
  426.  
  427.         paddd    mm0,mm4                ;1
  428.         movq    mm4,[ecx+224]        ;1
  429.         pmaddwd    mm4,[edx+224]        ;2
  430.         paddd    mm1,mm5                ;1
  431.         movq    mm5,[ecx+232]        ;1
  432.         pmaddwd    mm5,[edx+232]        ;2
  433.         paddd    mm2,mm6                ;1
  434.         movq    mm6,[ecx+240]        ;1
  435.         pmaddwd    mm6,[edx+240]        ;2
  436.         paddd    mm3,mm7                ;1
  437.         movq    mm7,[ecx+248]        ;1
  438.         pmaddwd    mm7,[edx+248]        ;2
  439.  
  440.         paddd        mm0, mm4        ;1
  441.         paddd        mm1, mm5        ;1
  442.         paddd        mm2, mm6        ;1
  443.         paddd        mm3, mm7        ;1
  444.  
  445.         paddd        mm0, mm2        ;1
  446.         paddd        mm1, mm3        ;1
  447.         paddd        mm0, mm1        ;1
  448.         punpckldq    mm1, mm0        ;1
  449.         paddd        mm0, mm1        ;1
  450.         psrad        mm0, 14            ;1
  451.         packssdw    mm0, mm0        ;1
  452.         psrld        mm0, 16
  453.         movd        eax, mm0
  454.         ret
  455.     }
  456. }
  457.  
  458. void VDAPIENTRY VDAudioFilterPCM16End_MMX() {
  459.     __asm emms
  460. }
  461.  
  462. void __declspec(naked) VDAPIENTRY VDAudioFilterPCM16SymmetricArray_MMX(sint16 *dst, ptrdiff_t dst_stride, const sint16 *src_center, uint32 count, const sint16 *filter, uint32 filterquadsizeminus1) {
  463.     static const uint64 roundconst = 0x0000200000002000;
  464.  
  465.     __asm {
  466.         push        ebp
  467.         push        edi
  468.         push        esi
  469.         push        ebx
  470.         mov            ebx,[esp+24+16]
  471.         mov            ecx,[esp+12+16]
  472.         shl            ebx,4
  473.         mov            edx,[esp+20+16]
  474.         lea            ecx, [ecx+ebx+8]
  475.         lea            edx, [edx+ebx+8]
  476.         neg            ebx
  477.         mov            esi, [esp+16+16]
  478.         mov            edi, [esp+4+16]
  479.         mov            ebp, [esp+8+16]
  480.         add            ebp, ebp
  481. yloop:
  482.         mov            eax, ebx
  483.         movq        mm0,roundconst
  484.         movq        mm1,[ecx+eax-8]
  485.         pmaddwd        mm1,[edx+eax-8]
  486. xloop:
  487.         movq        mm2, [ecx+eax]
  488.         movq        mm3, [ecx+eax+8]
  489.         pmaddwd        mm2, [edx+eax]
  490.         pmaddwd        mm3, [edx+eax+8]
  491.         add            eax, 16
  492.         paddd        mm0, mm2
  493.         paddd        mm1, mm3
  494.         jne            xloop
  495.  
  496.         paddd        mm0, mm1
  497.         add            ecx, 2
  498.         punpckldq    mm1, mm0
  499.         paddd        mm0, mm1
  500.         psrad        mm0, 14
  501.         packssdw    mm0, mm0
  502.         psrlq        mm0, 48
  503.         movd        eax, mm0
  504.         mov            word ptr [edi], ax
  505.         add            edi, ebp
  506.         dec            esi
  507.         jne            yloop
  508.         emms
  509.         pop            ebx
  510.         pop            esi
  511.         pop            edi
  512.         pop            ebp
  513.         ret
  514.     }
  515. }
  516.  
  517. ///////////////////////////////////////////////////////////////////////////
  518. //
  519. //    SSE implementations
  520. //
  521. ///////////////////////////////////////////////////////////////////////////
  522.  
  523. static const float __declspec(align(16)) sse_32K[4]={32768.0f, 32768.0f, 32768.0f, 32768.0f};
  524. static const float __declspec(align(16)) sse_128[4]={128.0f, 128.0f, 128.0f, 128.0f};
  525. static const float __declspec(align(16)) sse_inv_32K[4]={1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f};
  526. static const float __declspec(align(16)) sse_inv_128[4]={1.0f/128.0f, 1.0f/128.0f, 1.0f/128.0f, 1.0f/128.0f};
  527.  
  528. void __declspec(naked) VDAPIENTRY VDConvertPCM32FToPCM16_SSE(void *dst, const void *src, uint32 samples) {
  529.     __asm {
  530.         push        ebx
  531.         mov            edx, [esp+4+4]
  532.         mov            ecx, [esp+8+4]
  533.         movaps        xmm1, sse_32K
  534.         mov            ebx, [esp+12+4]
  535.  
  536.         neg            ebx
  537.         jz            xit
  538.  
  539.         test        ecx, 15
  540.         jz            majorloopstart
  541. prealignloop:
  542.         movss        xmm0, [ecx]
  543.         add            ecx, 4
  544.         mulss        xmm0, xmm1
  545.         cvtps2pi    mm0, xmm0
  546.         packssdw    mm0, mm0
  547.         movd        eax, mm0
  548.         mov            word ptr [edx], ax
  549.         add            edx, 2
  550.         inc            ebx
  551.         jz            xit
  552.         test        ecx, 15
  553.         jnz            prealignloop
  554.  
  555. majorloopstart:
  556.         add            ebx, 3
  557.         jc            postloopstart
  558.  
  559. majorloop:
  560.         movaps        xmm0, [ecx]
  561.         add            ecx, 16
  562.         mulps        xmm0, xmm1
  563.         cvtps2pi    mm0, xmm0
  564.         movhlps        xmm0, xmm0
  565.         cvtps2pi    mm1, xmm0
  566.         packssdw    mm0, mm1
  567.         movq        [edx], mm0
  568.         add            edx, 8
  569.         add            ebx, 4
  570.         jnc            majorloop
  571.  
  572. postloopstart:
  573.         sub            ebx, 3
  574.         jz            xit
  575. postloop:
  576.         movss        xmm0, [ecx]
  577.         add            ecx, 4
  578.         mulss        xmm0, xmm1
  579.         cvtps2pi    mm0, xmm0
  580.         packssdw    mm0, mm0
  581.         movd        eax, mm0
  582.         mov            word ptr [edx], ax
  583.         add            edx, 2
  584.         inc            ebx
  585.         jnz            postloop
  586.  
  587. xit:
  588.         emms
  589.         pop            ebx
  590.         ret
  591.     }
  592. }
  593.  
  594. void __declspec(naked) VDAPIENTRY VDConvertPCM32FToPCM8_SSE(void *dst, const void *src, uint32 samples) {
  595.     __asm {
  596.         push        ebx
  597.         mov            edx, [esp+4+4]
  598.         mov            ecx, [esp+8+4]
  599.         movaps        xmm1, sse_128
  600.         mov            ebx, [esp+12+4]
  601.  
  602.         neg            ebx
  603.         jz            xit
  604.  
  605.         test        ecx, 15
  606.         jz            majorloopstart
  607. prealignloop:
  608.         movss        xmm0, [ecx]
  609.         add            ecx, 4
  610.         mulss        xmm0, xmm1
  611.         addss        xmm0, xmm1
  612.         cvtps2pi    mm0, xmm0
  613.         packssdw    mm0, mm0
  614.         packuswb    mm0, mm0
  615.         movd        eax, mm0
  616.         mov            byte ptr [edx], al
  617.         inc            edx
  618.         inc            ebx
  619.         jz            xit
  620.         test        ecx, 15
  621.         jnz            prealignloop
  622.  
  623. majorloopstart:
  624.         add            ebx, 3
  625.         jc            postloopstart
  626.  
  627. majorloop:
  628.         movaps        xmm0, [ecx]
  629.         add            ecx, 16
  630.         mulps        xmm0, xmm1
  631.         addps        xmm0, xmm1
  632.         cvtps2pi    mm0, xmm0
  633.         movhlps        xmm0, xmm0
  634.         cvtps2pi    mm1, xmm0
  635.         packssdw    mm0, mm1
  636.         packuswb    mm0, mm0
  637.         movd        [edx], mm0
  638.         add            edx, 4
  639.         add            ebx, 4
  640.         jnc            majorloop
  641.  
  642. postloopstart:
  643.         sub            ebx, 3
  644.         jz            xit
  645. postloop:
  646.         movss        xmm0, [ecx]
  647.         add            ecx, 4
  648.         mulss        xmm0, xmm1
  649.         addss        xmm0, xmm1
  650.         cvtps2pi    mm0, xmm0
  651.         packssdw    mm0, mm0
  652.         packuswb    mm0, mm0
  653.         movd        eax, mm0
  654.         mov            byte ptr [edx], al
  655.         inc            edx
  656.         inc            ebx
  657.         jnz            postloop
  658.  
  659. xit:
  660.         emms
  661.         pop            ebx
  662.         ret
  663.     }
  664. }
  665.  
  666. void __declspec(naked) VDAPIENTRY VDConvertPCM16ToPCM32F_SSE(void *dst, const void *src, uint32 samples) {
  667.     __asm {
  668.         movaps        xmm4, sse_inv_32K
  669.         push        ebx
  670.         mov            eax, [esp+12+4]
  671.         neg            eax
  672.         jz            xit
  673.         mov            ecx, [esp+8+4]
  674.         add            eax, eax
  675.         mov            edx, [esp+4+4]
  676.         sub            ecx, eax
  677.  
  678.         ;align destination
  679. alignloop:
  680.         test        edx, 15
  681.         jz            fastloop_start
  682.         movsx        ebx, word ptr [ecx+eax]
  683.         cvtsi2ss    xmm0, ebx
  684.         mulss        xmm0, xmm4
  685.         movss        [edx],xmm0
  686.         add            edx, 4
  687.         add            eax, 2
  688.         jne            alignloop
  689.         pop            ebx
  690.         ret
  691.  
  692. fastloop_start:
  693.         add            eax, 6
  694.         jns            skip_fastloop
  695.         jmp            short fastloop
  696.  
  697.         align        16
  698. fastloop:
  699.         movq        mm0, [ecx+eax-6]
  700.         pxor        mm1, mm1
  701.         punpckhwd    mm1, mm0
  702.         punpcklwd    mm0, mm0
  703.         psrad        mm0, 16
  704.         psrad        mm1, 16
  705.         cvtpi2ps    xmm0, mm0
  706.         cvtpi2ps    xmm1, mm1
  707.         movlhps        xmm0, xmm1
  708.         mulps        xmm0, xmm4
  709.         movaps        [edx], xmm0
  710.         add            edx, 16
  711.         add            eax, 8
  712.         jnc            fastloop
  713.         emms
  714. skip_fastloop:
  715.         sub            eax, 6
  716.         jz            xit
  717. tidyloop:
  718.         movsx        ebx, word ptr [ecx+eax]
  719.         cvtsi2ss    xmm0, ebx
  720.         mulss        xmm0, xmm4
  721.         movss        [edx],xmm0
  722.         add            edx, 4
  723.         add            eax, 2
  724.         jne            tidyloop
  725. xit:
  726.         pop            ebx
  727.         ret
  728.     }
  729. }
  730.  
  731. void __declspec(naked) VDAPIENTRY VDConvertPCM8ToPCM32F_SSE(void *dst, const void *src, uint32 samples) {
  732.     __asm {
  733.         movaps        xmm1, sse_inv_128
  734.         push        ebx
  735.         mov            eax, [esp+12+4]
  736.         neg            eax
  737.         jz            xit
  738.         mov            ecx, [esp+8+4]
  739.         mov            edx, [esp+4+4]
  740.         sub            ecx, eax
  741. lup:
  742.         movzx        ebx, byte ptr [ecx+eax]
  743.         sub            ebx, 80h
  744.         cvtsi2ss    xmm0, ebx
  745.         mulss        xmm0, xmm1
  746.         movss        [edx],xmm0
  747.         add            edx, 4
  748.         inc            eax
  749.         jne            lup
  750. xit:
  751.         pop            ebx
  752.         ret
  753.     }
  754. }
  755. #endif
  756.  
  757. ///////////////////////////////////////////////////////////////////////////
  758. //
  759. //    vtables
  760. //
  761. ///////////////////////////////////////////////////////////////////////////
  762.  
  763. static const tpVDConvertPCM g_VDConvertPCMTable_scalar[3][3]={
  764.     {    0,                            VDConvertPCM8ToPCM16,            VDConvertPCM8ToPCM32F        },
  765.     {    VDConvertPCM16ToPCM8,        0,                                VDConvertPCM16ToPCM32F        },
  766.     {    VDConvertPCM32FToPCM8,        VDConvertPCM32FToPCM16,            0                            },
  767. };
  768.  
  769. #ifdef _M_IX86
  770. static const tpVDConvertPCM g_VDConvertPCMTable_MMX[3][3]={
  771.     {    0,                            VDConvertPCM8ToPCM16_MMX,        VDConvertPCM8ToPCM32F        },
  772.     {    VDConvertPCM16ToPCM8_MMX,    0,                                VDConvertPCM16ToPCM32F        },
  773.     {    VDConvertPCM32FToPCM8,        VDConvertPCM32FToPCM16,            0                            },
  774. };
  775.  
  776. static const tpVDConvertPCM g_VDConvertPCMTable_SSE[3][3]={
  777.     {    0,                            VDConvertPCM8ToPCM16_MMX,        VDConvertPCM8ToPCM32F_SSE    },
  778.     {    VDConvertPCM16ToPCM8_MMX,    0,                                VDConvertPCM16ToPCM32F_SSE    },
  779.     {    VDConvertPCM32FToPCM8_SSE,    VDConvertPCM32FToPCM16_SSE,        0                            },
  780. };
  781. #endif
  782.  
  783. tpVDConvertPCMVtbl VDGetPCMConversionVtable() {
  784. #ifdef _M_IX86
  785.     uint32 exts = CPUGetEnabledExtensions();
  786.  
  787.     if (exts & CPUF_SUPPORTS_MMX) {
  788.         if (exts & CPUF_SUPPORTS_SSE)
  789.             return g_VDConvertPCMTable_SSE;
  790.         else
  791.             return g_VDConvertPCMTable_MMX;
  792.     }
  793. #endif
  794.     return g_VDConvertPCMTable_scalar;
  795. }
  796.  
  797. static const VDAudioFilterVtable g_VDAudioFilterVtable_scalar = {
  798.     VDAudioFilterPCM16,
  799.     VDAudioFilterPCM16End,
  800.     VDAudioFilterPCM16SymmetricArray
  801. };
  802.  
  803. #ifdef _M_IX86
  804. static const VDAudioFilterVtable g_VDAudioFilterVtable_MMX = {
  805.     VDAudioFilterPCM16_MMX,
  806.     VDAudioFilterPCM16End_MMX,
  807.     VDAudioFilterPCM16SymmetricArray_MMX
  808. };
  809.  
  810. static const VDAudioFilterVtable g_VDAudioFilterVtable_128_MMX = {
  811.     VDAudioFilterPCM16_128_MMX,
  812.     VDAudioFilterPCM16End_MMX,
  813.     VDAudioFilterPCM16SymmetricArray_MMX
  814. };
  815. #endif
  816.  
  817. const VDAudioFilterVtable *VDGetAudioFilterVtable(uint32 taps) {
  818. #ifdef _M_IX86
  819.     uint32 exts = CPUGetEnabledExtensions();
  820.  
  821.     if (exts & CPUF_SUPPORTS_MMX) {
  822.         if (taps == 128) {
  823.             return &g_VDAudioFilterVtable_128_MMX;
  824.         }
  825.  
  826.         return &g_VDAudioFilterVtable_MMX;
  827.     }
  828. #endif
  829.  
  830.     return &g_VDAudioFilterVtable_scalar;
  831. }
  832.