RAResampler.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:20k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #include "hlxclib/string.h" // memcpy
  36. #include "RAResampler.h"
  37. #include "allresamplers.h"
  38. #include "cpuident.h"
  39. static void cvtShortShortSimple(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  40. {
  41.     memcpy(d,s,n*sizeof(short)) ; /* Flawfinder: ignore */
  42. }
  43. static void cvtFloatFloatSimple(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  44. {
  45.     memcpy(d,s,n*sizeof(float)) ; /* Flawfinder: ignore */
  46. }
  47. static void cvtIntFloatSimple(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  48. {
  49.     int i ;
  50.     const int* src = (const int*)s ;
  51.     float* dst = (float*)d ;
  52.     for (i = 0 ; i < n ; i++)
  53.         *dst++ = (1.0f/65536.0f)*(float)*src++ ;
  54. }
  55. static void cvtIntShortSimple(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  56. {
  57.     int i ;
  58.     const int* src = (const int*)s ;
  59.     short* dst = (short*)d ;
  60.     for (i = 0 ; i < n ; i++)
  61.     {
  62.         int t = *src++ ;
  63.         if (t < 0x7fff8000L) t += 0x8000L ; // rounding
  64.         *dst++ = (short)(t >> 16);
  65.     }
  66. }
  67. static void cvtShortFloatSimple(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  68. {
  69.     int i ;
  70.     const short* src = (const short*)s ;
  71.     float* dst = (float*)d ;
  72.     for (i = 0 ; i < n ; i++)
  73.         *dst++ = (float)*src++ ;
  74. }
  75. // generic convert functions for multichannel operation
  76. static int cvtShortShort(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  77. {
  78.     const short* src = (const short *)s ;
  79.     const short* srcEnd = src + n ;
  80.     short* dst = (short *)d ;
  81.     while (src != srcEnd)
  82.     {
  83.         *dst = *src ;
  84.         src += pState->incInput ;
  85.         dst += pState->incOutput ;
  86.         pState = pState->pNext ;
  87.     }
  88.     return dst - (short *)d ;
  89. }
  90. static int cvtFloatFloat(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  91. {
  92.     const float* src = (const float *)s ;
  93.     const float* srcEnd = src + n ;
  94.     float* dst = (float *)d ;
  95.     while (src != srcEnd)
  96.     {
  97.         *dst = *src ;
  98.         src += pState->incInput ;
  99.         dst += pState->incOutput ;
  100.         pState = pState->pNext ;
  101.     }
  102.     return dst - (float *)d ;
  103. }
  104. static int cvtIntFloat(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  105. {
  106.     const int* src = (const int *)s ;
  107.     const int* srcEnd = src + n ;
  108.     float* dst = (float *)d ;
  109.     while (src != srcEnd)
  110.     {
  111.         *dst = (1.0f/65536.0f) * (*src) ;
  112.         src += pState->incInput ;
  113.         dst += pState->incOutput ;
  114.         pState = pState->pNext ;
  115.     }
  116.     return dst - (float *)d ;
  117. }
  118. static int cvtIntShort(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  119. {
  120.     const int* src = (const int *)s ;
  121.     const int* srcEnd = src + n ;
  122.     short* dst = (short *)d ;
  123.     while (src != srcEnd)
  124.     {
  125.         int t = (int)(*src) ;
  126.         if (t < 0x7fff8000L) t += 0x8000L ; // rounding
  127.         *dst = (short)(t >> 16) ;
  128.         src += pState->incInput ;
  129.         dst += pState->incOutput ;
  130.         pState = pState->pNext ;
  131.     }
  132.     return dst - (short *)d ;
  133. }
  134. static int cvtShortFloat(void *d, const void *s, int n, const struct CVTSTATEMACHINE *pState)
  135. {
  136.     const short* src = (const short *)s ;
  137.     const short* srcEnd = src + n ;
  138.     float* dst = (float *)d ;
  139.     while (src != srcEnd)
  140.     {
  141.         *dst = (float)(*src) ;
  142.         src += pState->incInput ;
  143.         dst += pState->incOutput ;
  144.         pState = pState->pNext ;
  145.     }
  146.     return dst - (float *)d ;
  147. }
  148. typedef int  (*tfResample)(void *inbuf, int insamps, tConverter *pCvt, short *outbuf, int outstride, void *inst);
  149. typedef void* (*tfInitResamplerCopy)(int nchans, const void *inst);
  150. typedef void (*tfFreeResampler)(void *inst);
  151. typedef int  (*tfGetDelay)(void *inst);
  152. typedef int  (*tfGetDelay)(void *inst);
  153. typedef int  (*tfGetMinInput)(int nSamples, void *inst);
  154. typedef int  (*tfGetMaxOutput)(int nSamples, void *inst);
  155. static cvtFunctionType const cvtFunc[3][3] = {
  156.     {cvtShortShort,0,cvtShortFloat},
  157.     {cvtIntShort,  0,cvtIntFloat},
  158.     {0,            0,cvtFloatFloat}
  159. } ;
  160. RAExactResampler::RAExactResampler() {}
  161. RAExactResampler::~RAExactResampler() {}
  162. class RAAnyResampler : public RAExactResampler
  163. {
  164. public:
  165.     int Resample(void *_inbuf, int insamps, signed short *outbuf) ;
  166.     int Resample(void *_inbuf, int insamps, signed int *outbuf) ;
  167.     int GetMinInput(int insamps)
  168.     {
  169.         int t = insamps / m_nChannelsTotal * m_nChannels[0] ;
  170.         t = m_pfGetMinInput(t, m_pResampler[0]) ;
  171.         return t / m_nChannels[0] * m_nChannelsTotal ;
  172.     }
  173.     int GetMaxOutput(int insamps)
  174.     {
  175.         int t = insamps / m_nChannelsTotal * m_nChannels[0] ;
  176.         t = m_pfGetMaxOutput(t, m_pResampler[0]) ;
  177.         return t / m_nChannels[0] * m_nChannelsTotal ;
  178.     }
  179.     int GetDelay()
  180.     {
  181.         return m_pfGetDelay(m_pResampler[0]) ;
  182.     }
  183. protected:
  184.     RAAnyResampler() ;
  185.     virtual ~RAAnyResampler();
  186.     /*
  187.      * function pointers
  188.      */
  189.     tfResample      m_pfResample[2] ; // one for mono, one for stereo
  190.     tfGetMinInput   m_pfGetMinInput ;
  191.     tfGetMaxOutput  m_pfGetMaxOutput ;
  192.     tfGetDelay      m_pfGetDelay ;
  193.     tfFreeResampler m_pfFreeResampler ;
  194.     tfInitResamplerCopy m_pfInitResamplerCopy ;
  195.     tConverter m_converter[2] ; // one for mono, one for stereo
  196.     int intype, resType;
  197.     enum {
  198.         MAX_RESAMPLERS = 5
  199.     } ;
  200.     int m_nResamplers ;
  201.     int m_nBytesPerSampleIn ;
  202.     int m_nChannelsTotal ;
  203.     void *m_pResampler[MAX_RESAMPLERS] ;
  204.     int m_nChannels[MAX_RESAMPLERS] ;
  205.     int m_nBlock[MAX_RESAMPLERS] ;
  206.     int m_nOffsetIn[MAX_RESAMPLERS] ;
  207.     HX_RESULT Init(int inrate, int outrate, int chans, int intype, float atten, float passband, float stopband, float dcgain) ;
  208.     // these need to be supplied by the base classes
  209.     virtual int GetResamplerInputType(void) = 0 ;
  210.     virtual HX_RESULT SetupFunctionPointers(void) = 0 ;
  211.     virtual void* InitResampler(int inrate, int outrate, int nchans, float atten, float passband, float stopband, float dcgain) = 0;
  212. private:
  213.     HX_RESULT SetupNumChannels(int chans) ;
  214.     HX_RESULT SetupConverter(int intype, int restype) ;
  215. } ;
  216. RAAnyResampler::RAAnyResampler()
  217. : m_nResamplers(0)
  218. {
  219.     memset(m_pResampler, 0, sizeof(m_pResampler)) ;
  220. }
  221. HX_RESULT RAAnyResampler::Init(int inrate, int outrate, int chans, int intype, float atten, float passband, float stopband, float dcgain)
  222. {
  223.     HX_RESULT res = HXR_OK ;
  224.     int i ;
  225.     if (SUCCEEDED(res))
  226.         res = SetupFunctionPointers() ;
  227.     if (SUCCEEDED(res))
  228.         res = SetupNumChannels(chans) ;
  229.     m_converter[0].pStateMachine = 0 ;
  230.     m_converter[1].pStateMachine = 0 ;
  231.     if (SUCCEEDED(res))
  232.         res = SetupConverter(intype, GetResamplerInputType()) ;
  233.     for (i = 0 ; i < m_nResamplers; i++)
  234.     {
  235.         m_pResampler[i] = 0 ;
  236.         if (SUCCEEDED(res))
  237.         {
  238.             if (i == 0)
  239.                 m_pResampler[i] = InitResampler(inrate, outrate, m_nChannels[i],  atten, passband, stopband, dcgain) ;
  240.             else
  241.                 m_pResampler[i] = m_pfInitResamplerCopy(m_nChannels[i], m_pResampler[0]) ;
  242.         }
  243.         if (!m_pResampler[i])
  244.             res = HXR_OUTOFMEMORY ;
  245.     }
  246.     return res ;
  247. }
  248. RAAnyResampler::~RAAnyResampler()
  249. {
  250.     int i ;
  251.     for (i = 0 ; i < MAX_RESAMPLERS ; i++)
  252.     {
  253.         if (m_pResampler[i]) m_pfFreeResampler(m_pResampler[i]) ;
  254.         m_pResampler[i] = 0; // paranoia code.
  255.     }
  256.     HX_VECTOR_DELETE(m_converter[0].pStateMachine) ;
  257.     HX_VECTOR_DELETE(m_converter[1].pStateMachine) ;
  258. }
  259. HX_RESULT RAAnyResampler::SetupNumChannels(int chans)
  260. {
  261.     int i ;
  262.     if (chans > 2*MAX_RESAMPLERS)
  263.         return HXR_FAIL ;
  264.     m_nChannelsTotal = chans ;
  265.     m_nResamplers = 0 ;
  266.     for (i = 0 ; i < chans ; i+=2)
  267.     {
  268.         m_nChannels[m_nResamplers] = (i + 2 > chans) ? 1 : 2 ;
  269.         m_nBlock[m_nResamplers] = NBLOCK - NBLOCK % m_nChannels[m_nResamplers] ;
  270.         m_nOffsetIn[m_nResamplers] = 2 * m_nResamplers ;
  271.         m_nResamplers++ ;
  272.     }
  273.     return HXR_OK ;
  274. }
  275. HX_RESULT RAAnyResampler::SetupConverter(int _intype, int _restype)
  276. {
  277.     static const int bps[] = {2,4,4} ;
  278.     intype = _intype;
  279.     resType = _restype ;
  280.     m_converter[0].pfCvt         = cvtFunc[intype][resType] ;
  281.     m_converter[1].pfCvt         = cvtFunc[intype][resType] ;
  282.     m_converter[0].pStateMachine = new struct CVTSTATEMACHINE[1] ;
  283.     m_converter[1].pStateMachine = new struct CVTSTATEMACHINE[2] ;
  284.     // mono converter
  285.     m_converter[0].pStateMachine[0].pNext = m_converter[0].pStateMachine ;
  286.     m_converter[0].pStateMachine[0].incInput = m_nChannelsTotal ;
  287.     m_converter[0].pStateMachine[0].incOutput = 1 ;
  288.     // stereo converter
  289.     m_converter[1].pStateMachine[0].pNext = &(m_converter[1].pStateMachine[1]) ;
  290.     m_converter[1].pStateMachine[0].incInput = 1 ;
  291.     m_converter[1].pStateMachine[0].incOutput = 1 ;
  292.     m_converter[1].pStateMachine[1].pNext = &(m_converter[1].pStateMachine[0]) ;
  293.     m_converter[1].pStateMachine[1].incInput = m_nChannelsTotal - 1 ;
  294.     m_converter[1].pStateMachine[1].incOutput = 1 ;
  295.     m_nBytesPerSampleIn = bps[intype] ;
  296.     return HXR_OK ;
  297. }
  298. int RAAnyResampler::Resample(void *_inbuf, int _insamps, signed short *_outbuf)
  299. {
  300.     int i ;
  301.     int outsamps ;
  302.     for (i = 0 ; i < m_nResamplers; i++)
  303.     {
  304.         int insamps = _insamps ;
  305.         int nChannels = m_nChannels[i] ;
  306.         char* inbuf = (char*)_inbuf + m_nOffsetIn[i] * m_nBytesPerSampleIn ;
  307.         signed short* outbuf = _outbuf + m_nOffsetIn[i] ;
  308.         outsamps = 0 ;
  309.         while (insamps)
  310.         {
  311.             int nin = min(insamps, m_nBlock[i]);
  312.             int nout = m_pfResample[nChannels-1](inbuf, nin, &m_converter[nChannels-1], outbuf, m_nChannelsTotal, m_pResampler[i]);
  313.             inbuf    += nin * m_nBytesPerSampleIn ;
  314.             insamps  -= nin;
  315.             outbuf   += nout;
  316.             outsamps += nout;
  317.         }
  318.     }
  319.     return outsamps;
  320. }
  321. int RAAnyResampler::Resample(void *_inbuf, int _insamps, signed int *_outbuf)
  322. {
  323.     // fake it!
  324.     int outsamps = Resample(_inbuf, _insamps, (signed short*) _outbuf) ;
  325.     for (int j=outsamps-1; j>=0; --j)
  326.     {
  327.       _outbuf[j] = ((signed short*)_outbuf)[j] << 16 ;
  328.     }
  329.     return outsamps;
  330. }
  331. /*
  332.  * Arbitrary resampler -- any rate to any rate
  333.  */
  334. class RAArbitraryResampler : public RAAnyResampler
  335. {
  336. public:
  337.     static HX_RESULT Create(RAExactResampler **pRes, int inrate, int outrate, int chans, int intype, float atten, float passband, float stopband, float dcgain)
  338.     {
  339.         HX_RESULT res = HXR_OK ;
  340.         RAArbitraryResampler *pr = new RAArbitraryResampler() ;
  341.         if (!pr)
  342.             res = HXR_OUTOFMEMORY ;
  343.         if (SUCCEEDED(res))
  344.             res = pr->Init(inrate, outrate, chans, intype, atten, passband, stopband, dcgain) ;
  345.         if (FAILED(res))
  346.         {
  347.             delete pr ; pr = 0 ;
  348.         }
  349.         *pRes = pr ;
  350.         return res ;
  351.     }
  352.     HX_RESULT SetupFunctionPointers(void)
  353.     {
  354.         m_pfResample[0] = &RAResampleMonoArb ; m_pfResample[1] = &RAResampleStereoArb ;
  355.         m_pfGetMaxOutput = &RAGetMaxOutputArb ; m_pfGetMinInput = &RAGetMinInputArb ;
  356.         m_pfGetDelay = &RAGetDelayArb ; m_pfFreeResampler = &RAFreeResamplerArb ;
  357.         m_pfInitResamplerCopy = &RAInitResamplerCopyArb;
  358.         return HXR_OK ;
  359.     }
  360.     int GetResamplerInputType(void) {return _FLOAT; }
  361.     void* InitResampler(int inrate, int outrate, int nchans, float atten, float passband, float stopband, float dcgain)
  362.     {
  363.         return RAInitResamplerArb(inrate, outrate, nchans, atten, passband, stopband, dcgain) ;
  364.     }
  365. } ;
  366. /*
  367.  * Rational resampler -- many rates to many rates, as long as the fraction
  368.  * inrate/outrate is reducible to "small numbers"
  369.  */
  370. class RARationalResampler : public RAAnyResampler
  371. {
  372. public:
  373.     static HX_RESULT Create(RAExactResampler **pRes, int inrate, int outrate, int chans, int intype, float atten, float passband, float stopband, float dcgain)
  374.     {
  375.         HX_RESULT res = HXR_OK ;
  376.         RARationalResampler *pr = new RARationalResampler() ;
  377.         if (!pr)
  378.             res = HXR_OUTOFMEMORY ;
  379.         if (SUCCEEDED(res))
  380.             res = pr->Init(inrate, outrate, chans, intype, atten, passband, stopband, dcgain) ;
  381.         if (FAILED(res))
  382.         {
  383.             delete pr ; pr = 0 ;
  384.         }
  385.         *pRes = pr ;
  386.         return res ;
  387.     }
  388.     int GetResamplerInputType(void) {return _FLOAT; }
  389.     HX_RESULT SetupFunctionPointers(void)
  390.     {
  391.         m_pfResample[0] = &RAResampleMonoRat ; m_pfResample[1] = &RAResampleStereoRat ;
  392.         m_pfGetMaxOutput = &RAGetMaxOutputRat ; m_pfGetMinInput = &RAGetMinInputRat ;
  393.         m_pfGetDelay = &RAGetDelayRat ; m_pfFreeResampler = &RAFreeResamplerRat ;
  394.         m_pfInitResamplerCopy = &RAInitResamplerCopyRat;
  395.         return HXR_OK ;
  396.     }
  397.     void* InitResampler(int inrate, int outrate, int nchans, float atten, float passband, float stopband, float dcgain)
  398.     {
  399.         return RAInitResamplerRat(inrate, outrate, nchans, atten, passband, stopband, dcgain) ;
  400.     }
  401. } ;
  402. #if defined(_M_IX86) /* || defined(__i386__) */ /* no unix mmx code yet */
  403. class RAMMXResampler : public RAAnyResampler
  404. {
  405. public:
  406.     static HX_RESULT Create(RAExactResampler **pRes, int inrate, int outrate, int chans, int intype, float atten, float passband, float stopband, float dcgain)
  407.     {
  408.         HX_RESULT res = HXR_OK ;
  409.         RAMMXResampler *pr = new RAMMXResampler() ;
  410.         if (!pr)
  411.             res = HXR_OUTOFMEMORY ;
  412.         if (SUCCEEDED(res))
  413.             res = pr->Init(inrate, outrate, chans, intype, atten, passband, stopband, dcgain) ;
  414.         if (FAILED(res))
  415.         {
  416.             delete pr ; pr = 0 ;
  417.         }
  418.         *pRes = pr ;
  419.         return res ;
  420.     }
  421.     int GetResamplerInputType(void) {return _INT16; }
  422.     HX_RESULT SetupFunctionPointers(void)
  423.     {
  424.         m_pfResample[0]  = &RAResampleMonoMMX ; m_pfResample[1] = &RAResampleStereoMMX ;
  425.         m_pfGetMaxOutput = &RAGetMaxOutputMMX ; m_pfGetMinInput = &RAGetMinInputMMX ;
  426.         m_pfGetDelay     = &RAGetDelayMMX ;   m_pfFreeResampler = &RAFreeResamplerMMX ;
  427.         m_pfInitResamplerCopy = &RAInitResamplerCopyMMX;
  428.         return HXR_OK ;
  429.     }
  430.     void* InitResampler(int inrate, int outrate, int nchans, float atten, float passband, float stopband, float dcgain)
  431.     {
  432.         // should maybe check for atten etc.
  433.         return RAInitResamplerMMX(inrate, outrate, nchans) ;
  434.     }
  435. } ;
  436. #endif /* defined(_M_IX86) */
  437. #if defined(HELIX_CONFIG_FIXEDPOINT)
  438. class RAHermiteResampler : public RAAnyResampler
  439. {
  440. public:
  441.     static HX_RESULT Create(RAExactResampler **pRes, int inrate, int outrate, int chans, int intype, float atten, float passband, float stopband, float dcgain)
  442.     {
  443.         HX_RESULT res = HXR_OK ;
  444.         /* intype must be _INT16 for the Hermite resampler */
  445.         if (intype != _INT16 || chans > 2)
  446.             return HXR_FAIL ;
  447.         RAHermiteResampler *pr = new RAHermiteResampler() ;
  448.         if (!pr)
  449.             res = HXR_OUTOFMEMORY ;
  450.         if (SUCCEEDED(res))
  451.             res = pr->Init(inrate, outrate, chans, intype, atten, passband, stopband, dcgain) ;
  452.         if (FAILED(res))
  453.         {
  454.             delete pr ; pr = 0 ;
  455.         }
  456.         *pRes = pr ;
  457.         return res ;
  458.     }
  459.     int GetResamplerInputType(void) {return _INT16; }
  460.     HX_RESULT SetupFunctionPointers(void)
  461.     {
  462.         m_pfResample[0]  = &RAResampleMonoHermite ; m_pfResample[1] = &RAResampleStereoHermite ;
  463.         m_pfGetMaxOutput = &RAGetMaxOutputHermite ; m_pfGetMinInput = &RAGetMinInputHermite ;
  464.         m_pfGetDelay     = &RAGetDelayHermite ;   m_pfFreeResampler = &RAFreeResamplerHermite ;
  465.         m_pfInitResamplerCopy = &RAInitResamplerCopyHermite;
  466.         return HXR_OK ;
  467.     }
  468.     void* InitResampler(int inrate, int outrate, int nchans, float atten, float passband, float stopband, float dcgain)
  469.     {
  470.         // should maybe check for atten etc.
  471.         return RAInitResamplerHermite(inrate, outrate, nchans) ;
  472.     }
  473. };
  474. #endif /* defined(HELIX_CONFIG_FIXEDPOINT) */
  475. HX_RESULT RAExactResampler::Create(RAExactResampler** pRes, int inrate, int outrate, int chans, int intype, int quality)
  476. {
  477.     float dcgain   = DEF_DCGAIN ;
  478.     float atten    ;
  479.     float passband ;
  480.     float stopband ;
  481.     switch(quality)
  482.     {
  483.     case qualityVeryLow:
  484.         passband = 0.77f ; // 32 tap
  485.         stopband = 1.09f ;
  486.         atten    = 80.0f ;
  487.         break ;
  488.     case qualityLow:
  489.         passband = 0.82f ; // 48 tap
  490.         stopband = 1.05f ;
  491.         atten    = 85.0f ;
  492.         break ;
  493.     case qualityMedium:
  494.         passband = 0.85f ; // 64 tap
  495.         stopband = 1.03f ;
  496.         atten    = 90.0f ;
  497.         break ;
  498.     case qualityHigh:
  499.         passband = 0.88f ; // 96 tap
  500.         stopband = 1.00f ;
  501.         atten    = 90.0f ;
  502.         break ;
  503.     case qualityHyper:
  504.         passband = 0.904f ; // 128 tap
  505.         stopband = 1.000f ;
  506.         atten    = 96.00f ;
  507.         break ;
  508.     default:
  509.         return HXR_INVALID_PARAMETER ;
  510.     }
  511.     return Create(pRes, inrate, outrate, chans, intype, atten, passband, stopband, dcgain) ;
  512. }
  513. HX_RESULT RAExactResampler::Create(RAExactResampler** pRes, int inrate, int outrate, int chans, int intype, float atten, float trans, float dcgain)
  514. {
  515.     return Create(pRes, inrate, outrate, chans, intype, atten, 1.0f-trans, 1.0f, dcgain) ;
  516. }
  517. HX_RESULT RAExactResampler::Create(RAExactResampler** pRes, int inrate, int outrate, int chans, int intype, float atten, float passband, float stopband, float dcgain)
  518. {
  519.     HX_RESULT res = HXR_FAIL ;
  520. #if defined (HELIX_CONFIG_FIXEDPOINT)
  521.     if (FAILED(res))
  522.         res = RAHermiteResampler::Create(pRes, inrate, outrate, chans, intype, atten, passband, stopband, dcgain);
  523. #else
  524.     /* only instantiate the MMX resampler if we are compiling on an x86 architecture
  525.        and running on a machine with MMX */
  526. #if defined(_M_IX86) /* || defined(__i386__) */ /* no unix mmx code yet */
  527.     
  528.     CPUInformation info ;
  529.     CPUIdentify(&info) ;
  530.     /* don't use the MMX resampler if the quality is "hyper" */
  531.     if (atten <= 90.0 &&
  532.         info.architecture == ulArchitectureIntel &&
  533.         info.specific.m_x86.hasMMX)
  534.     {
  535.         res = RAMMXResampler::Create(pRes, inrate, outrate, chans, intype, atten, passband, stopband, dcgain) ;
  536.     }
  537. #endif
  538.     if (FAILED(res))
  539.     {
  540.         res = RARationalResampler::Create(pRes, inrate, outrate, chans, intype, atten, passband, stopband, dcgain) ;
  541.     }
  542.     if (FAILED(res))
  543.     {
  544.         res = RAArbitraryResampler::Create(pRes, inrate, outrate, chans, intype, atten, passband, stopband, dcgain) ;
  545.     }
  546. #endif /*HELIX_CONFIG_FIXEDPOINT*/
  547.     return res ;
  548. }