00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
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
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
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
00080
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
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
00112 suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
00113
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
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
00135
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
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
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
00169
00170
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
00197
00198
00199
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
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
00219
00220 void * FIRFilter::operator new(size_t s)
00221 {
00222
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
00235 #ifdef ALLOW_SSE2
00236 if (uExtensions & MM_SSE2)
00237 {
00238
00239 return ::new FIRFilterSSE2;
00240 }
00241 else
00242 #endif // ALLOW_SSE2
00243 {
00244
00245 return ::new FIRFilter;
00246 }
00247 }