1
////////////////////////////////////////////////////////////////////////////////
3
/// General FIR digital filter routines with MMX optimization.
5
/// Note : MMX optimized functions reside in a separate, platform-specific file,
6
/// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
8
/// Author : Copyright (c) Olli Parviainen
9
/// Author e-mail : oparviai 'at' iki.fi
10
/// SoundTouch WWW: http://www.surina.net/soundtouch
12
////////////////////////////////////////////////////////////////////////////////
14
// Last changed : $Date: 2006/09/18 22:29:22 $
15
// File revision : $Revision: 1.4 $
17
// $Id: FIRFilter.cpp,v 1.4 2006/09/18 22:29:22 martynshaw Exp $
19
////////////////////////////////////////////////////////////////////////////////
23
// SoundTouch audio processing library
24
// Copyright (c) Olli Parviainen
26
// This library is free software; you can redistribute it and/or
27
// modify it under the terms of the GNU Lesser General Public
28
// License as published by the Free Software Foundation; either
29
// version 2.1 of the License, or (at your option) any later version.
31
// This library is distributed in the hope that it will be useful,
32
// but WITHOUT ANY WARRANTY; without even the implied warranty of
33
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34
// Lesser General Public License for more details.
36
// You should have received a copy of the GNU Lesser General Public
37
// License along with this library; if not, write to the Free Software
38
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40
////////////////////////////////////////////////////////////////////////////////
47
#include "FIRFilter.h"
48
#include "cpu_detect.h"
50
using namespace soundtouch;
52
/*****************************************************************************
54
* Implementation of the class 'FIRFilter'
56
*****************************************************************************/
58
FIRFilter::FIRFilter()
67
FIRFilter::~FIRFilter()
69
delete[] filterCoeffs;
72
// Usual C-version of the filter routine for stereo sound
73
uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
76
LONG_SAMPLETYPE suml, sumr;
78
// when using floating point samples, use a scaler instead of a divider
79
// because division is much slower operation than multiplying.
80
double dScaler = 1.0 / (double)resultDivider;
85
end = 2 * (numSamples - length);
87
for (j = 0; j < end; j += 2)
89
const SAMPLETYPE *ptr;
94
for (i = 0; i < length; i += 4)
96
// loop is unrolled by factor of 4 here for efficiency
97
suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
98
ptr[2 * i + 2] * filterCoeffs[i + 1] +
99
ptr[2 * i + 4] * filterCoeffs[i + 2] +
100
ptr[2 * i + 6] * filterCoeffs[i + 3];
101
sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
102
ptr[2 * i + 3] * filterCoeffs[i + 1] +
103
ptr[2 * i + 5] * filterCoeffs[i + 2] +
104
ptr[2 * i + 7] * filterCoeffs[i + 3];
107
#ifdef INTEGER_SAMPLES
108
suml >>= resultDivFactor;
109
sumr >>= resultDivFactor;
110
// saturate to 16 bit integer limits
111
suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
112
// saturate to 16 bit integer limits
113
sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
117
#endif // INTEGER_SAMPLES
118
dest[j] = (SAMPLETYPE)suml;
119
dest[j + 1] = (SAMPLETYPE)sumr;
121
return numSamples - length;
127
// Usual C-version of the filter routine for mono sound
128
uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
133
// when using floating point samples, use a scaler instead of a divider
134
// because division is much slower operation than multiplying.
135
double dScaler = 1.0 / (double)resultDivider;
141
end = numSamples - length;
142
for (j = 0; j < end; j ++)
145
for (i = 0; i < length; i += 4)
147
// loop is unrolled by factor of 4 here for efficiency
148
sum += src[i + 0] * filterCoeffs[i + 0] +
149
src[i + 1] * filterCoeffs[i + 1] +
150
src[i + 2] * filterCoeffs[i + 2] +
151
src[i + 3] * filterCoeffs[i + 3];
153
#ifdef INTEGER_SAMPLES
154
sum >>= resultDivFactor;
155
// saturate to 16 bit integer limits
156
sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
159
#endif // INTEGER_SAMPLES
160
dest[j] = (SAMPLETYPE)sum;
167
// Set filter coeffiecients and length.
169
// Throws an exception if filter length isn't divisible by 8
170
void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
172
assert(newLength > 0);
173
if (newLength % 8) throw std::runtime_error("FIR filter length not divisible by 8");
175
lengthDiv8 = newLength / 8;
176
length = lengthDiv8 * 8;
177
assert(length == newLength);
179
resultDivFactor = uResultDivFactor;
180
resultDivider = (SAMPLETYPE)pow(2., (double)resultDivFactor);
182
delete[] filterCoeffs;
183
filterCoeffs = new SAMPLETYPE[length];
184
memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
188
uint FIRFilter::getLength() const
195
// Applies the filter to the given sequence of samples.
197
// Note : The amount of outputted samples is by value of 'filter_length'
198
// smaller than the amount of input samples.
199
uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
201
assert(numChannels == 1 || numChannels == 2);
204
assert(lengthDiv8 * 8 == length);
205
if (numSamples < length) return 0;
206
assert(resultDivFactor >= 0);
207
if (numChannels == 2)
209
return evaluateFilterStereo(dest, src, numSamples);
211
return evaluateFilterMono(dest, src, numSamples);
217
// Operator 'new' is overloaded so that it automatically creates a suitable instance
218
// depending on if we've a MMX-capable CPU available or not.
219
void * FIRFilter::operator new(size_t s)
221
// Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
222
throw std::runtime_error("Don't use 'new FIRFilter', use 'newInstance' member instead!");
227
FIRFilter * FIRFilter::newInstance()
231
uExtensions = detectCPUextensions();
233
// Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
236
// MMX routines available only with integer sample types
237
if (uExtensions & SUPPORT_MMX)
239
return ::new FIRFilterMMX;
245
if (uExtensions & SUPPORT_SSE)
248
return ::new FIRFilterSSE;
254
if (uExtensions & SUPPORT_3DNOW)
257
return ::new FIRFilter3DNow;
260
#endif // ALLOW_3DNOW
263
// ISA optimizations not supported, use plain C version
264
return ::new FIRFilter;