AAFilter.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. ////////////////////////////////////////////////////////////////////////////////
  14. //
  15. // License :
  16. //
  17. // SoundTouch audio processing library
  18. // Copyright (c) Olli Parviainen
  19. //
  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.
  24. //
  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.
  29. //
  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
  33. //
  34. ////////////////////////////////////////////////////////////////////////////////
  35. #include <memory.h>
  36. #include <assert.h>
  37. #include <math.h>
  38. #include <stdlib.h>
  39. #include "AAFilter.h"
  40. #include "FIRFilter.h"
  41. using namespace soundtouch;
  42. #define PI 3.14159265358979323846
  43. #define TWOPI (2 * PI)
  44. // define this to save AA filter coefficients to a file
  45. // #define _DEBUG_SAVE_AAFILTER_COEFFICIENTS 1
  46. #ifdef _DEBUG_SAVE_AAFILTER_COEFFICIENTS
  47. #include <stdio.h>
  48. static void _DEBUG_SAVE_AAFIR_COEFFS(SAMPLETYPE *coeffs, int len)
  49. {
  50. FILE *fptr = fopen("aa_filter_coeffs.txt", "wt");
  51. if (fptr == nullptr) return;
  52. for (int i = 0; i < len; i ++)
  53. {
  54. double temp = coeffs[i];
  55. fprintf(fptr, "%lf\n", temp);
  56. }
  57. fclose(fptr);
  58. }
  59. #else
  60. #define _DEBUG_SAVE_AAFIR_COEFFS(x, y)
  61. #endif
  62. /*****************************************************************************
  63. *
  64. * Implementation of the class 'AAFilter'
  65. *
  66. *****************************************************************************/
  67. AAFilter::AAFilter(uint len)
  68. {
  69. pFIR = FIRFilter::newInstance();
  70. cutoffFreq = 0.5;
  71. setLength(len);
  72. }
  73. AAFilter::~AAFilter()
  74. {
  75. delete pFIR;
  76. }
  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(double newCutoffFreq)
  81. {
  82. cutoffFreq = newCutoffFreq;
  83. calculateCoeffs();
  84. }
  85. // Sets number of FIR filter taps
  86. void AAFilter::setLength(uint newLength)
  87. {
  88. length = newLength;
  89. calculateCoeffs();
  90. }
  91. // Calculates coefficients for a low-pass FIR filter using Hamming window
  92. void AAFilter::calculateCoeffs()
  93. {
  94. uint i;
  95. double cntTemp, temp, tempCoeff,h, w;
  96. double wc;
  97. double scaleCoeff, sum;
  98. double *work;
  99. SAMPLETYPE *coeffs;
  100. assert(length >= 2);
  101. assert(length % 4 == 0);
  102. assert(cutoffFreq >= 0);
  103. assert(cutoffFreq <= 0.5);
  104. work = new double[length];
  105. coeffs = new SAMPLETYPE[length];
  106. wc = 2.0 * PI * cutoffFreq;
  107. tempCoeff = TWOPI / (double)length;
  108. sum = 0;
  109. for (i = 0; i < length; i ++)
  110. {
  111. cntTemp = (double)i - (double)(length / 2);
  112. temp = cntTemp * wc;
  113. if (temp != 0)
  114. {
  115. h = sin(temp) / temp; // sinc function
  116. }
  117. else
  118. {
  119. h = 1.0;
  120. }
  121. w = 0.54 + 0.46 * cos(tempCoeff * cntTemp); // hamming window
  122. temp = w * h;
  123. work[i] = temp;
  124. // calc net sum of coefficients
  125. sum += temp;
  126. }
  127. // ensure the sum of coefficients is larger than zero
  128. assert(sum > 0);
  129. // ensure we've really designed a lowpass filter...
  130. assert(work[length/2] > 0);
  131. assert(work[length/2 + 1] > -1e-6);
  132. assert(work[length/2 - 1] > -1e-6);
  133. // Calculate a scaling coefficient in such a way that the result can be
  134. // divided by 16384
  135. scaleCoeff = 16384.0f / sum;
  136. for (i = 0; i < length; i ++)
  137. {
  138. temp = work[i] * scaleCoeff;
  139. // scale & round to nearest integer
  140. temp += (temp >= 0) ? 0.5 : -0.5;
  141. // ensure no overfloods
  142. assert(temp >= -32768 && temp <= 32767);
  143. coeffs[i] = (SAMPLETYPE)temp;
  144. }
  145. // Set coefficients. Use divide factor 14 => divide result by 2^14 = 16384
  146. pFIR->setCoefficients(coeffs, length, 14);
  147. _DEBUG_SAVE_AAFIR_COEFFS(coeffs, length);
  148. delete[] work;
  149. delete[] coeffs;
  150. }
  151. // Applies the filter to the given sequence of samples.
  152. // Note : The amount of outputted samples is by value of 'filter length'
  153. // smaller than the amount of input samples.
  154. uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
  155. {
  156. return pFIR->evaluate(dest, src, numSamples, numChannels);
  157. }
  158. /// Applies the filter to the given src & dest pipes, so that processed amount of
  159. /// samples get removed from src, and produced amount added to dest
  160. /// Note : The amount of outputted samples is by value of 'filter length'
  161. /// smaller than the amount of input samples.
  162. uint AAFilter::evaluate(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) const
  163. {
  164. SAMPLETYPE *pdest;
  165. const SAMPLETYPE *psrc;
  166. uint numSrcSamples;
  167. uint result;
  168. int numChannels = src.getChannels();
  169. assert(numChannels == dest.getChannels());
  170. numSrcSamples = src.numSamples();
  171. psrc = src.ptrBegin();
  172. pdest = dest.ptrEnd(numSrcSamples);
  173. result = pFIR->evaluate(pdest, psrc, numSrcSamples, numChannels);
  174. src.receiveSamples(result);
  175. dest.putSamples(result);
  176. return result;
  177. }
  178. uint AAFilter::getLength() const
  179. {
  180. return pFIR->getLength();
  181. }