MythTV  0.26-pre
FIRFilter.cpp
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 //
00014 // Last changed  : $Date$
00015 // File revision : $Revision$
00016 //
00017 // $Id$
00018 //
00020 //
00021 // License :
00022 //
00023 //  SoundTouch audio processing library
00024 //  Copyright (c) Olli Parviainen
00025 //
00026 //  This library is free software; you can redistribute it and/or
00027 //  modify it under the terms of the GNU Lesser General Public
00028 //  License as published by the Free Software Foundation; either
00029 //  version 2.1 of the License, or (at your option) any later version.
00030 //
00031 //  This library is distributed in the hope that it will be useful,
00032 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00033 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00034 //  Lesser General Public License for more details.
00035 //
00036 //  You should have received a copy of the GNU Lesser General Public
00037 //  License along with this library; if not, write to the Free Software
00038 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00039 //
00041 
00042 #include <memory.h>
00043 #include <assert.h>
00044 #include <math.h>
00045 #include <stdlib.h>
00046 #include <stdexcept>
00047 #include "FIRFilter.h"
00048 #include "cpu_detect.h"
00049 
00050 using namespace soundtouch;
00051 
00052 /*****************************************************************************
00053  *
00054  * Implementation of the class 'FIRFilter'
00055  *
00056  *****************************************************************************/
00057 
00058 FIRFilter::FIRFilter()
00059 {
00060     resultDivFactor = 0;
00061     resultDivider = 0;
00062     length = 0;
00063     lengthDiv8 = 0;
00064     filterCoeffs = NULL;
00065 }
00066 
00067 
00068 FIRFilter::~FIRFilter()
00069 {
00070     delete[] filterCoeffs;
00071 }
00072 
00073 // Usual C-version of the filter routine for stereo sound
00074 uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
00075 {
00076     uint i, j, end;
00077     LONG_SAMPLETYPE suml, sumr;
00078 #ifdef FLOAT_SAMPLES
00079     // when using floating point samples, use a scaler instead of a divider
00080     // because division is much slower operation than multiplying.
00081     double dScaler = 1.0 / (double)resultDivider;
00082 #endif
00083 
00084     assert(length != 0);
00085 
00086     end = 2 * (numSamples - length);
00087 
00088     for (j = 0; j < end; j += 2) 
00089     {
00090         const SAMPLETYPE *ptr;
00091 
00092         suml = sumr = 0;
00093         ptr = src + j;
00094 
00095         for (i = 0; i < length; i += 4) 
00096         {
00097             // loop is unrolled by factor of 4 here for efficiency
00098             suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
00099                     ptr[2 * i + 2] * filterCoeffs[i + 1] +
00100                     ptr[2 * i + 4] * filterCoeffs[i + 2] +
00101                     ptr[2 * i + 6] * filterCoeffs[i + 3];
00102             sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
00103                     ptr[2 * i + 3] * filterCoeffs[i + 1] +
00104                     ptr[2 * i + 5] * filterCoeffs[i + 2] +
00105                     ptr[2 * i + 7] * filterCoeffs[i + 3];
00106         }
00107 
00108 #ifdef INTEGER_SAMPLES
00109         suml >>= resultDivFactor;
00110         sumr >>= resultDivFactor;
00111         // saturate to 16 bit integer limits
00112         suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
00113         // saturate to 16 bit integer limits
00114         sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
00115 #else
00116         suml *= dScaler;
00117         sumr *= dScaler;
00118 #endif // INTEGER_SAMPLES
00119         dest[j] = (SAMPLETYPE)suml;
00120         dest[j + 1] = (SAMPLETYPE)sumr;
00121     }
00122     return numSamples - length;
00123 }
00124 
00125 
00126 
00127 
00128 // Usual C-version of the filter routine for mono sound
00129 uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
00130 {
00131     uint i, j, end;
00132     LONG_SAMPLETYPE sum;
00133 #ifdef FLOAT_SAMPLES
00134     // when using floating point samples, use a scaler instead of a divider
00135     // because division is much slower operation than multiplying.
00136     double dScaler = 1.0 / (double)resultDivider;
00137 #endif
00138 
00139 
00140     assert(length != 0);
00141 
00142     end = numSamples - length;
00143     for (j = 0; j < end; j ++) 
00144     {
00145         sum = 0;
00146         for (i = 0; i < length; i += 4) 
00147         {
00148             // loop is unrolled by factor of 4 here for efficiency
00149             sum += src[i + 0] * filterCoeffs[i + 0] + 
00150                    src[i + 1] * filterCoeffs[i + 1] + 
00151                    src[i + 2] * filterCoeffs[i + 2] + 
00152                    src[i + 3] * filterCoeffs[i + 3];
00153         }
00154 #ifdef INTEGER_SAMPLES
00155         sum >>= resultDivFactor;
00156         // saturate to 16 bit integer limits
00157         sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
00158 #else
00159         sum *= dScaler;
00160 #endif // INTEGER_SAMPLES
00161         dest[j] = (SAMPLETYPE)sum;
00162         src ++;
00163     }
00164     return end;
00165 }
00166 
00167 
00168 // Set filter coeffiecients and length.
00169 //
00170 // Throws an exception if filter length isn't divisible by 8
00171 void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
00172 {
00173     assert(newLength > 0);
00174     if (newLength % 8) throw std::runtime_error("FIR filter length not divisible by 8");
00175 
00176     lengthDiv8 = newLength / 8;
00177     length = lengthDiv8 * 8;
00178     assert(length == newLength);
00179 
00180     resultDivFactor = uResultDivFactor;
00181     resultDivider = (SAMPLETYPE)pow( (SAMPLETYPE)2, (int)resultDivFactor);
00182 
00183     delete[] filterCoeffs;
00184     filterCoeffs = new SAMPLETYPE[length];
00185     memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
00186 }
00187 
00188 
00189 uint FIRFilter::getLength() const
00190 {
00191     return length;
00192 }
00193 
00194 
00195 
00196 // Applies the filter to the given sequence of samples. 
00197 //
00198 // Note : The amount of outputted samples is by value of 'filter_length' 
00199 // smaller than the amount of input samples.
00200 uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
00201 {
00202     assert(numChannels == 1 || numChannels == 2);
00203 
00204     assert(length > 0);
00205     assert(lengthDiv8 * 8 == length);
00206     if (numSamples < length) return 0;
00207     //assert(resultDivFactor >= 0); // Commented out in MythTV : see #4846
00208     if (numChannels == 2) 
00209     {
00210         return evaluateFilterStereo(dest, src, numSamples);
00211     } else {
00212         return evaluateFilterMono(dest, src, numSamples);
00213     }
00214 }
00215 
00216 
00217 
00218 // Operator 'new' is overloaded so that it automatically creates a suitable instance 
00219 // depending on if we've a MMX-capable CPU available or not.
00220 void * FIRFilter::operator new(size_t s)
00221 {
00222     // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
00223     throw std::runtime_error("Don't use 'new FIRFilter', use 'newInstance' member instead!");
00224     return NULL;
00225 }
00226 
00227 
00228 FIRFilter * FIRFilter::newInstance()
00229 {
00230     uint uExtensions;
00231 
00232     uExtensions = detectCPUextensions();
00233 
00234     // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
00235 #ifdef ALLOW_SSE2
00236     if (uExtensions & MM_SSE2)
00237     {
00238         // SSE support
00239         return ::new FIRFilterSSE2;
00240     }
00241     else
00242 #endif // ALLOW_SSE2
00243     {
00244         // ISA optimizations not supported, use plain C version
00245         return ::new FIRFilter;
00246     }
00247 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends