1
////////////////////////////////////////////////////////////////////////////////
3
/// FIR low-pass (anti-alias) filter with filter coefficient design routine and
6
/// Anti-alias filter is used to prevent folding of high frequencies when
7
/// transposing the sample rate with interpolation.
9
/// Author : Copyright (c) Olli Parviainen
10
/// Author e-mail : oparviai 'at' iki.fi
11
/// SoundTouch WWW: http://www.surina.net/soundtouch
13
////////////////////////////////////////////////////////////////////////////////
15
// Last changed : $Date: 2006/09/18 22:29:22 $
16
// File revision : $Revision: 1.4 $
18
// $Id: AAFilter.cpp,v 1.4 2006/09/18 22:29:22 martynshaw Exp $
20
////////////////////////////////////////////////////////////////////////////////
24
// SoundTouch audio processing library
25
// Copyright (c) Olli Parviainen
27
// This library is free software; you can redistribute it and/or
28
// modify it under the terms of the GNU Lesser General Public
29
// License as published by the Free Software Foundation; either
30
// version 2.1 of the License, or (at your option) any later version.
32
// This library is distributed in the hope that it will be useful,
33
// but WITHOUT ANY WARRANTY; without even the implied warranty of
34
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35
// Lesser General Public License for more details.
37
// You should have received a copy of the GNU Lesser General Public
38
// License along with this library; if not, write to the Free Software
39
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
41
////////////////////////////////////////////////////////////////////////////////
48
#include "FIRFilter.h"
50
using namespace soundtouch;
52
#define PI 3.141592655357989
53
#define TWOPI (2 * PI)
55
/*****************************************************************************
57
* Implementation of the class 'AAFilter'
59
*****************************************************************************/
61
AAFilter::AAFilter(const uint length)
63
pFIR = FIRFilter::newInstance();
77
// Sets new anti-alias filter cut-off edge frequency, scaled to
78
// sampling frequency (nyquist frequency = 0.5).
79
// The filter will cut frequencies higher than the given frequency.
80
void AAFilter::setCutoffFreq(const double newCutoffFreq)
82
cutoffFreq = newCutoffFreq;
88
// Sets number of FIR filter taps
89
void AAFilter::setLength(const uint newLength)
97
// Calculates coefficients for a low-pass FIR filter using Hamming window
98
void AAFilter::calculateCoeffs()
101
double cntTemp, temp, tempCoeff,h, w;
103
double scaleCoeff, sum;
108
assert(length % 4 == 0);
109
assert(cutoffFreq >= 0);
110
assert(cutoffFreq <= 0.5);
112
work = new double[length];
113
coeffs = new SAMPLETYPE[length];
115
fc2 = 2.0 * cutoffFreq;
117
tempCoeff = TWOPI / (double)length;
120
for (i = 0; i < length; i ++)
122
cntTemp = (double)i - (double)(length / 2);
127
h = fc2 * sin(temp) / temp; // sinc function
133
w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
138
// calc net sum of coefficients
142
// ensure the sum of coefficients is larger than zero
145
// ensure we've really designed a lowpass filter...
146
assert(work[length/2] > 0);
147
assert(work[length/2 + 1] > -1e-6);
148
assert(work[length/2 - 1] > -1e-6);
150
// Calculate a scaling coefficient in such a way that the result can be
152
scaleCoeff = 16384.0f / sum;
154
for (i = 0; i < length; i ++)
156
// scale & round to nearest integer
157
temp = work[i] * scaleCoeff;
158
temp += (temp >= 0) ? 0.5 : -0.5;
159
// ensure no overfloods
160
assert(temp >= -32768 && temp <= 32767);
161
coeffs[i] = (SAMPLETYPE)temp;
164
// Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
165
pFIR->setCoefficients(coeffs, length, 14);
172
// Applies the filter to the given sequence of samples.
173
// Note : The amount of outputted samples is by value of 'filter length'
174
// smaller than the amount of input samples.
175
uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
177
return pFIR->evaluate(dest, src, numSamples, numChannels);
181
uint AAFilter::getLength() const
183
return pFIR->getLength();