|
MythTV
0.26-pre
|
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 }
1.7.6.1