summaryrefslogtreecommitdiffstats
path: root/media/libsoundtouch/src/AAFilter.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /media/libsoundtouch/src/AAFilter.cpp
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'media/libsoundtouch/src/AAFilter.cpp')
-rw-r--r--media/libsoundtouch/src/AAFilter.cpp222
1 files changed, 222 insertions, 0 deletions
diff --git a/media/libsoundtouch/src/AAFilter.cpp b/media/libsoundtouch/src/AAFilter.cpp
new file mode 100644
index 0000000000..3fd4e9fe6d
--- /dev/null
+++ b/media/libsoundtouch/src/AAFilter.cpp
@@ -0,0 +1,222 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// FIR low-pass (anti-alias) filter with filter coefficient design routine and
+/// MMX optimization.
+///
+/// Anti-alias filter is used to prevent folding of high frequencies when
+/// transposing the sample rate with interpolation.
+///
+/// Author : Copyright (c) Olli Parviainen
+/// Author e-mail : oparviai 'at' iki.fi
+/// SoundTouch WWW: http://www.surina.net/soundtouch
+///
+////////////////////////////////////////////////////////////////////////////////
+//
+// License :
+//
+// SoundTouch audio processing library
+// Copyright (c) Olli Parviainen
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include <memory.h>
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include "AAFilter.h"
+#include "FIRFilter.h"
+
+using namespace soundtouch;
+
+#define PI M_PI
+#define TWOPI (2 * PI)
+
+// define this to save AA filter coefficients to a file
+// #define _DEBUG_SAVE_AAFILTER_COEFFICIENTS 1
+
+#ifdef _DEBUG_SAVE_AAFILTER_COEFFICIENTS
+ #include <stdio.h>
+
+ static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len)
+ {
+ FILE *fptr = fopen("aa_filter_coeffs.txt", "wt");
+ if (fptr == NULL) return;
+
+ for (int i = 0; i < len; i ++)
+ {
+ double temp = coeffs[i];
+ fprintf(fptr, "%lf\n", temp);
+ }
+ fclose(fptr);
+ }
+
+#else
+ #define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
+#endif
+
+/*****************************************************************************
+ *
+ * Implementation of the class 'AAFilter'
+ *
+ *****************************************************************************/
+
+AAFilter::AAFilter(uint len)
+{
+ pFIR = FIRFilter::newInstance();
+ cutoffFreq = 0.5;
+ setLength(len);
+}
+
+
+AAFilter::~AAFilter()
+{
+ delete pFIR;
+}
+
+
+// Sets new anti-alias filter cut-off edge frequency, scaled to
+// sampling frequency (nyquist frequency = 0.5).
+// The filter will cut frequencies higher than the given frequency.
+void AAFilter::setCutoffFreq(double newCutoffFreq)
+{
+ cutoffFreq = newCutoffFreq;
+ calculateCoeffs();
+}
+
+
+// Sets number of FIR filter taps
+void AAFilter::setLength(uint newLength)
+{
+ length = newLength;
+ calculateCoeffs();
+}
+
+
+// Calculates coefficients for a low-pass FIR filter using Hamming window
+void AAFilter::calculateCoeffs()
+{
+ uint i;
+ double cntTemp, temp, tempCoeff,h, w;
+ double wc;
+ double scaleCoeff, sum;
+ double *work;
+ SAMPLETYPE *coeffs;
+
+ assert(length >= 2);
+ assert(length % 4 == 0);
+ assert(cutoffFreq >= 0);
+ assert(cutoffFreq <= 0.5);
+
+ work = new double[length];
+ coeffs = new SAMPLETYPE[length];
+
+ wc = 2.0 * PI * cutoffFreq;
+ tempCoeff = TWOPI / (double)length;
+
+ sum = 0;
+ for (i = 0; i < length; i ++)
+ {
+ cntTemp = (double)i - (double)(length / 2);
+
+ temp = cntTemp * wc;
+ if (temp != 0)
+ {
+ h = sin(temp) / temp; // sinc function
+ }
+ else
+ {
+ h = 1.0;
+ }
+ w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
+
+ temp = w * h;
+ work[i] = temp;
+
+ // calc net sum of coefficients
+ sum += temp;
+ }
+
+ // ensure the sum of coefficients is larger than zero
+ assert(sum > 0);
+
+ // ensure we've really designed a lowpass filter...
+ assert(work[length/2] > 0);
+ assert(work[length/2 + 1] > -1e-6);
+ assert(work[length/2 - 1] > -1e-6);
+
+ // Calculate a scaling coefficient in such a way that the result can be
+ // divided by 16384
+ scaleCoeff = 16384.0f / sum;
+
+ for (i = 0; i < length; i ++)
+ {
+ temp = work[i] * scaleCoeff;
+ // scale & round to nearest integer
+ temp += (temp >= 0) ? 0.5 : -0.5;
+ // ensure no overfloods
+ assert(temp >= -32768 && temp <= 32767);
+ coeffs[i] = (SAMPLETYPE)temp;
+ }
+
+ // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
+ pFIR->setCoefficients(coeffs, length, 14);
+
+ _DEBUG_SAVE_AAFIR_COEFFS(coeffs, length);
+
+ delete[] work;
+ delete[] coeffs;
+}
+
+
+// Applies the filter to the given sequence of samples.
+// Note : The amount of outputted samples is by value of 'filter length'
+// smaller than the amount of input samples.
+uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
+{
+ return pFIR->evaluate(dest, src, numSamples, numChannels);
+}
+
+
+/// Applies the filter to the given src & dest pipes, so that processed amount of
+/// samples get removed from src, and produced amount added to dest
+/// Note : The amount of outputted samples is by value of 'filter length'
+/// smaller than the amount of input samples.
+uint AAFilter::evaluate(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) const
+{
+ SAMPLETYPE *pdest;
+ const SAMPLETYPE *psrc;
+ uint numSrcSamples;
+ uint result;
+ int numChannels = src.getChannels();
+
+ assert(numChannels == dest.getChannels());
+
+ numSrcSamples = src.numSamples();
+ psrc = src.ptrBegin();
+ pdest = dest.ptrEnd(numSrcSamples);
+ result = pFIR->evaluate(pdest, psrc, numSrcSamples, numChannels);
+ src.receiveSamples(result);
+ dest.putSamples(result);
+
+ return result;
+}
+
+
+uint AAFilter::getLength() const
+{
+ return pFIR->getLength();
+}