media/libsoundtouch/src/AAFilter.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 ////////////////////////////////////////////////////////////////////////////////
michael@0 2 ///
michael@0 3 /// FIR low-pass (anti-alias) filter with filter coefficient design routine and
michael@0 4 /// MMX optimization.
michael@0 5 ///
michael@0 6 /// Anti-alias filter is used to prevent folding of high frequencies when
michael@0 7 /// transposing the sample rate with interpolation.
michael@0 8 ///
michael@0 9 /// Author : Copyright (c) Olli Parviainen
michael@0 10 /// Author e-mail : oparviai 'at' iki.fi
michael@0 11 /// SoundTouch WWW: http://www.surina.net/soundtouch
michael@0 12 ///
michael@0 13 ////////////////////////////////////////////////////////////////////////////////
michael@0 14 //
michael@0 15 // Last changed : $Date: 2014-01-05 15:40:22 -0600 (Sun, 05 Jan 2014) $
michael@0 16 // File revision : $Revision: 4 $
michael@0 17 //
michael@0 18 // $Id: AAFilter.cpp 177 2014-01-05 21:40:22Z oparviai $
michael@0 19 //
michael@0 20 ////////////////////////////////////////////////////////////////////////////////
michael@0 21 //
michael@0 22 // License :
michael@0 23 //
michael@0 24 // SoundTouch audio processing library
michael@0 25 // Copyright (c) Olli Parviainen
michael@0 26 //
michael@0 27 // This library is free software; you can redistribute it and/or
michael@0 28 // modify it under the terms of the GNU Lesser General Public
michael@0 29 // License as published by the Free Software Foundation; either
michael@0 30 // version 2.1 of the License, or (at your option) any later version.
michael@0 31 //
michael@0 32 // This library is distributed in the hope that it will be useful,
michael@0 33 // but WITHOUT ANY WARRANTY; without even the implied warranty of
michael@0 34 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
michael@0 35 // Lesser General Public License for more details.
michael@0 36 //
michael@0 37 // You should have received a copy of the GNU Lesser General Public
michael@0 38 // License along with this library; if not, write to the Free Software
michael@0 39 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
michael@0 40 //
michael@0 41 ////////////////////////////////////////////////////////////////////////////////
michael@0 42
michael@0 43 #include <memory.h>
michael@0 44 #include <assert.h>
michael@0 45 #include <math.h>
michael@0 46 #include <stdlib.h>
michael@0 47 #include "AAFilter.h"
michael@0 48 #include "FIRFilter.h"
michael@0 49
michael@0 50 using namespace soundtouch;
michael@0 51
michael@0 52 #define PI 3.141592655357989
michael@0 53 #define TWOPI (2 * PI)
michael@0 54
michael@0 55 // define this to save AA filter coefficients to a file
michael@0 56 // #define _DEBUG_SAVE_AAFILTER_COEFFICIENTS 1
michael@0 57
michael@0 58 #ifdef _DEBUG_SAVE_AAFILTER_COEFFICIENTS
michael@0 59 #include <stdio.h>
michael@0 60
michael@0 61 static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len)
michael@0 62 {
michael@0 63 FILE *fptr = fopen("aa_filter_coeffs.txt", "wt");
michael@0 64 if (fptr == NULL) return;
michael@0 65
michael@0 66 for (int i = 0; i < len; i ++)
michael@0 67 {
michael@0 68 double temp = coeffs[i];
michael@0 69 fprintf(fptr, "%lf\n", temp);
michael@0 70 }
michael@0 71 fclose(fptr);
michael@0 72 }
michael@0 73
michael@0 74 #else
michael@0 75 #define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
michael@0 76 #endif
michael@0 77
michael@0 78
michael@0 79 /*****************************************************************************
michael@0 80 *
michael@0 81 * Implementation of the class 'AAFilter'
michael@0 82 *
michael@0 83 *****************************************************************************/
michael@0 84
michael@0 85 AAFilter::AAFilter(uint len)
michael@0 86 {
michael@0 87 pFIR = FIRFilter::newInstance();
michael@0 88 cutoffFreq = 0.5;
michael@0 89 setLength(len);
michael@0 90 }
michael@0 91
michael@0 92
michael@0 93
michael@0 94 AAFilter::~AAFilter()
michael@0 95 {
michael@0 96 delete pFIR;
michael@0 97 }
michael@0 98
michael@0 99
michael@0 100
michael@0 101 // Sets new anti-alias filter cut-off edge frequency, scaled to
michael@0 102 // sampling frequency (nyquist frequency = 0.5).
michael@0 103 // The filter will cut frequencies higher than the given frequency.
michael@0 104 void AAFilter::setCutoffFreq(double newCutoffFreq)
michael@0 105 {
michael@0 106 cutoffFreq = newCutoffFreq;
michael@0 107 calculateCoeffs();
michael@0 108 }
michael@0 109
michael@0 110
michael@0 111
michael@0 112 // Sets number of FIR filter taps
michael@0 113 void AAFilter::setLength(uint newLength)
michael@0 114 {
michael@0 115 length = newLength;
michael@0 116 calculateCoeffs();
michael@0 117 }
michael@0 118
michael@0 119
michael@0 120
michael@0 121 // Calculates coefficients for a low-pass FIR filter using Hamming window
michael@0 122 void AAFilter::calculateCoeffs()
michael@0 123 {
michael@0 124 uint i;
michael@0 125 double cntTemp, temp, tempCoeff,h, w;
michael@0 126 double wc;
michael@0 127 double scaleCoeff, sum;
michael@0 128 double *work;
michael@0 129 SAMPLETYPE *coeffs;
michael@0 130
michael@0 131 assert(length >= 2);
michael@0 132 assert(length % 4 == 0);
michael@0 133 assert(cutoffFreq >= 0);
michael@0 134 assert(cutoffFreq <= 0.5);
michael@0 135
michael@0 136 work = new double[length];
michael@0 137 coeffs = new SAMPLETYPE[length];
michael@0 138
michael@0 139 wc = 2.0 * PI * cutoffFreq;
michael@0 140 tempCoeff = TWOPI / (double)length;
michael@0 141
michael@0 142 sum = 0;
michael@0 143 for (i = 0; i < length; i ++)
michael@0 144 {
michael@0 145 cntTemp = (double)i - (double)(length / 2);
michael@0 146
michael@0 147 temp = cntTemp * wc;
michael@0 148 if (temp != 0)
michael@0 149 {
michael@0 150 h = sin(temp) / temp; // sinc function
michael@0 151 }
michael@0 152 else
michael@0 153 {
michael@0 154 h = 1.0;
michael@0 155 }
michael@0 156 w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
michael@0 157
michael@0 158 temp = w * h;
michael@0 159 work[i] = temp;
michael@0 160
michael@0 161 // calc net sum of coefficients
michael@0 162 sum += temp;
michael@0 163 }
michael@0 164
michael@0 165 // ensure the sum of coefficients is larger than zero
michael@0 166 assert(sum > 0);
michael@0 167
michael@0 168 // ensure we've really designed a lowpass filter...
michael@0 169 assert(work[length/2] > 0);
michael@0 170 assert(work[length/2 + 1] > -1e-6);
michael@0 171 assert(work[length/2 - 1] > -1e-6);
michael@0 172
michael@0 173 // Calculate a scaling coefficient in such a way that the result can be
michael@0 174 // divided by 16384
michael@0 175 scaleCoeff = 16384.0f / sum;
michael@0 176
michael@0 177 for (i = 0; i < length; i ++)
michael@0 178 {
michael@0 179 temp = work[i] * scaleCoeff;
michael@0 180 //#if SOUNDTOUCH_INTEGER_SAMPLES
michael@0 181 // scale & round to nearest integer
michael@0 182 temp += (temp >= 0) ? 0.5 : -0.5;
michael@0 183 // ensure no overfloods
michael@0 184 assert(temp >= -32768 && temp <= 32767);
michael@0 185 //#endif
michael@0 186 coeffs[i] = (SAMPLETYPE)temp;
michael@0 187 }
michael@0 188
michael@0 189 // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
michael@0 190 pFIR->setCoefficients(coeffs, length, 14);
michael@0 191
michael@0 192 _DEBUG_SAVE_AAFIR_COEFFS(coeffs, length);
michael@0 193
michael@0 194 delete[] work;
michael@0 195 delete[] coeffs;
michael@0 196 }
michael@0 197
michael@0 198
michael@0 199 // Applies the filter to the given sequence of samples.
michael@0 200 // Note : The amount of outputted samples is by value of 'filter length'
michael@0 201 // smaller than the amount of input samples.
michael@0 202 uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
michael@0 203 {
michael@0 204 return pFIR->evaluate(dest, src, numSamples, numChannels);
michael@0 205 }
michael@0 206
michael@0 207
michael@0 208 /// Applies the filter to the given src & dest pipes, so that processed amount of
michael@0 209 /// samples get removed from src, and produced amount added to dest
michael@0 210 /// Note : The amount of outputted samples is by value of 'filter length'
michael@0 211 /// smaller than the amount of input samples.
michael@0 212 uint AAFilter::evaluate(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) const
michael@0 213 {
michael@0 214 SAMPLETYPE *pdest;
michael@0 215 const SAMPLETYPE *psrc;
michael@0 216 uint numSrcSamples;
michael@0 217 uint result;
michael@0 218 int numChannels = src.getChannels();
michael@0 219
michael@0 220 assert(numChannels == dest.getChannels());
michael@0 221
michael@0 222 numSrcSamples = src.numSamples();
michael@0 223 psrc = src.ptrBegin();
michael@0 224 pdest = dest.ptrEnd(numSrcSamples);
michael@0 225 result = pFIR->evaluate(pdest, psrc, numSrcSamples, numChannels);
michael@0 226 src.receiveSamples(result);
michael@0 227 dest.putSamples(result);
michael@0 228
michael@0 229 return result;
michael@0 230 }
michael@0 231
michael@0 232
michael@0 233 uint AAFilter::getLength() const
michael@0 234 {
michael@0 235 return pFIR->getLength();
michael@0 236 }

mercurial