no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / media / libsoundtouch / src / AAFilter.cpp
blob3fd4e9fe6d93cf781180ffbf6d3306cdbba24d36
1 ////////////////////////////////////////////////////////////////////////////////
2 ///
3 /// FIR low-pass (anti-alias) filter with filter coefficient design routine and
4 /// MMX optimization.
5 ///
6 /// Anti-alias filter is used to prevent folding of high frequencies when
7 /// transposing the sample rate with interpolation.
8 ///
9 /// Author : Copyright (c) Olli Parviainen
10 /// Author e-mail : oparviai 'at' iki.fi
11 /// SoundTouch WWW: http://www.surina.net/soundtouch
12 ///
13 ////////////////////////////////////////////////////////////////////////////////
15 // License :
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 ////////////////////////////////////////////////////////////////////////////////
36 #include <memory.h>
37 #include <assert.h>
38 #include <math.h>
39 #include <stdlib.h>
40 #include "AAFilter.h"
41 #include "FIRFilter.h"
43 using namespace soundtouch;
45 #define PI M_PI
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
52 #include <stdio.h>
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);
64 fclose(fptr);
67 #else
68 #define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
69 #endif
71 /*****************************************************************************
73 * Implementation of the class 'AAFilter'
75 *****************************************************************************/
77 AAFilter::AAFilter(uint len)
79 pFIR = FIRFilter::newInstance();
80 cutoffFreq = 0.5;
81 setLength(len);
85 AAFilter::~AAFilter()
87 delete pFIR;
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;
97 calculateCoeffs();
101 // Sets number of FIR filter taps
102 void AAFilter::setLength(uint newLength)
104 length = newLength;
105 calculateCoeffs();
109 // Calculates coefficients for a low-pass FIR filter using Hamming window
110 void AAFilter::calculateCoeffs()
112 uint i;
113 double cntTemp, temp, tempCoeff,h, w;
114 double wc;
115 double scaleCoeff, sum;
116 double *work;
117 SAMPLETYPE *coeffs;
119 assert(length >= 2);
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;
130 sum = 0;
131 for (i = 0; i < length; i ++)
133 cntTemp = (double)i - (double)(length / 2);
135 temp = cntTemp * wc;
136 if (temp != 0)
138 h = sin(temp) / temp; // sinc function
140 else
142 h = 1.0;
144 w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
146 temp = w * h;
147 work[i] = temp;
149 // calc net sum of coefficients
150 sum += temp;
153 // ensure the sum of coefficients is larger than zero
154 assert(sum > 0);
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
162 // divided by 16384
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);
180 delete[] work;
181 delete[] coeffs;
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
200 SAMPLETYPE *pdest;
201 const SAMPLETYPE *psrc;
202 uint numSrcSamples;
203 uint result;
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);
215 return result;
219 uint AAFilter::getLength() const
221 return pFIR->getLength();