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 ////////////////////////////////////////////////////////////////////////////////
17 // SoundTouch audio processing library
18 // Copyright (c) Olli Parviainen
20 // This library is free software; you can redistribute it and/or
21 // modify it under the terms of the GNU Lesser General Public
22 // License as published by the Free Software Foundation; either
23 // version 2.1 of the License, or (at your option) any later version.
25 // This library is distributed in the hope that it will be useful,
26 // but WITHOUT ANY WARRANTY; without even the implied warranty of
27 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 // Lesser General Public License for more details.
30 // You should have received a copy of the GNU Lesser General Public
31 // License along with this library; if not, write to the Free Software
32 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 ////////////////////////////////////////////////////////////////////////////////
41 #include "FIRFilter.h"
43 using namespace soundtouch
;
46 #define TWOPI (2 * PI)
48 // define this to save AA filter coefficients to a file
49 // #define _DEBUG_SAVE_AAFILTER_COEFFICIENTS 1
51 #ifdef _DEBUG_SAVE_AAFILTER_COEFFICIENTS
54 static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE
*coeffs
, int len
)
56 FILE *fptr
= fopen("aa_filter_coeffs.txt", "wt");
57 if (fptr
== NULL
) return;
59 for (int i
= 0; i
< len
; i
++)
61 double temp
= coeffs
[i
];
62 fprintf(fptr
, "%lf\n", temp
);
68 #define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
71 /*****************************************************************************
73 * Implementation of the class 'AAFilter'
75 *****************************************************************************/
77 AAFilter::AAFilter(uint len
)
79 pFIR
= FIRFilter::newInstance();
91 // Sets new anti-alias filter cut-off edge frequency, scaled to
92 // sampling frequency (nyquist frequency = 0.5).
93 // The filter will cut frequencies higher than the given frequency.
94 void AAFilter::setCutoffFreq(double newCutoffFreq
)
96 cutoffFreq
= newCutoffFreq
;
101 // Sets number of FIR filter taps
102 void AAFilter::setLength(uint newLength
)
109 // Calculates coefficients for a low-pass FIR filter using Hamming window
110 void AAFilter::calculateCoeffs()
113 double cntTemp
, temp
, tempCoeff
,h
, w
;
115 double scaleCoeff
, sum
;
120 assert(length
% 4 == 0);
121 assert(cutoffFreq
>= 0);
122 assert(cutoffFreq
<= 0.5);
124 work
= new double[length
];
125 coeffs
= new SAMPLETYPE
[length
];
127 wc
= 2.0 * PI
* cutoffFreq
;
128 tempCoeff
= TWOPI
/ (double)length
;
131 for (i
= 0; i
< length
; i
++)
133 cntTemp
= (double)i
- (double)(length
/ 2);
138 h
= sin(temp
) / temp
; // sinc function
144 w
= 0.54 + 0.46 * cos(tempCoeff
* cntTemp
); // hamming window
149 // calc net sum of coefficients
153 // ensure the sum of coefficients is larger than zero
156 // ensure we've really designed a lowpass filter...
157 assert(work
[length
/2] > 0);
158 assert(work
[length
/2 + 1] > -1e-6);
159 assert(work
[length
/2 - 1] > -1e-6);
161 // Calculate a scaling coefficient in such a way that the result can be
163 scaleCoeff
= 16384.0f
/ sum
;
165 for (i
= 0; i
< length
; i
++)
167 temp
= work
[i
] * scaleCoeff
;
168 // scale & round to nearest integer
169 temp
+= (temp
>= 0) ? 0.5 : -0.5;
170 // ensure no overfloods
171 assert(temp
>= -32768 && temp
<= 32767);
172 coeffs
[i
] = (SAMPLETYPE
)temp
;
175 // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
176 pFIR
->setCoefficients(coeffs
, length
, 14);
178 _DEBUG_SAVE_AAFIR_COEFFS(coeffs
, length
);
185 // Applies the filter to the given sequence of samples.
186 // Note : The amount of outputted samples is by value of 'filter length'
187 // smaller than the amount of input samples.
188 uint
AAFilter::evaluate(SAMPLETYPE
*dest
, const SAMPLETYPE
*src
, uint numSamples
, uint numChannels
) const
190 return pFIR
->evaluate(dest
, src
, numSamples
, numChannels
);
194 /// Applies the filter to the given src & dest pipes, so that processed amount of
195 /// samples get removed from src, and produced amount added to dest
196 /// Note : The amount of outputted samples is by value of 'filter length'
197 /// smaller than the amount of input samples.
198 uint
AAFilter::evaluate(FIFOSampleBuffer
&dest
, FIFOSampleBuffer
&src
) const
201 const SAMPLETYPE
*psrc
;
204 int numChannels
= src
.getChannels();
206 assert(numChannels
== dest
.getChannels());
208 numSrcSamples
= src
.numSamples();
209 psrc
= src
.ptrBegin();
210 pdest
= dest
.ptrEnd(numSrcSamples
);
211 result
= pFIR
->evaluate(pdest
, psrc
, numSrcSamples
, numChannels
);
212 src
.receiveSamples(result
);
213 dest
.putSamples(result
);
219 uint
AAFilter::getLength() const
221 return pFIR
->getLength();