FIRFilter.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. ////////////////////////////////////////////////////////////////////////////////
  2. ///
  3. /// General FIR digital filter routines with MMX optimization.
  4. ///
  5. /// Note : MMX optimized functions reside in a separate, platform-specific file,
  6. /// e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
  7. ///
  8. /// Author : Copyright (c) Olli Parviainen
  9. /// Author e-mail : oparviai 'at' iki.fi
  10. /// SoundTouch WWW: http://www.surina.net/soundtouch
  11. ///
  12. ////////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Last changed : $Date: 2013-06-12 15:24:44 +0000 (Wed, 12 Jun 2013) $
  15. // File revision : $Revision: 4 $
  16. //
  17. // $Id: FIRFilter.cpp 171 2013-06-12 15:24:44Z oparviai $
  18. //
  19. ////////////////////////////////////////////////////////////////////////////////
  20. //
  21. // License :
  22. //
  23. // SoundTouch audio processing library
  24. // Copyright (c) Olli Parviainen
  25. //
  26. // This library is free software; you can redistribute it and/or
  27. // modify it under the terms of the GNU Lesser General Public
  28. // License as published by the Free Software Foundation; either
  29. // version 2.1 of the License, or (at your option) any later version.
  30. //
  31. // This library is distributed in the hope that it will be useful,
  32. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  33. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  34. // Lesser General Public License for more details.
  35. //
  36. // You should have received a copy of the GNU Lesser General Public
  37. // License along with this library; if not, write to the Free Software
  38. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  39. //
  40. ////////////////////////////////////////////////////////////////////////////////
  41. #include <memory.h>
  42. #include <assert.h>
  43. #include <math.h>
  44. #include <stdlib.h>
  45. #include "FIRFilter.h"
  46. #include "cpu_detect.h"
  47. using namespace soundtouch;
  48. /*****************************************************************************
  49. *
  50. * Implementation of the class 'FIRFilter'
  51. *
  52. *****************************************************************************/
  53. FIRFilter::FIRFilter()
  54. {
  55. resultDivFactor = 0;
  56. resultDivider = 0;
  57. length = 0;
  58. lengthDiv8 = 0;
  59. filterCoeffs = NULL;
  60. }
  61. FIRFilter::~FIRFilter()
  62. {
  63. delete[] filterCoeffs;
  64. }
  65. // Usual C-version of the filter routine for stereo sound
  66. uint FIRFilter::evaluateFilterStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
  67. {
  68. uint i, j, end;
  69. LONG_SAMPLETYPE suml, sumr;
  70. #ifdef SOUNDTOUCH_FLOAT_SAMPLES
  71. // when using floating point samples, use a scaler instead of a divider
  72. // because division is much slower operation than multiplying.
  73. double dScaler = 1.0 / (double)resultDivider;
  74. #endif
  75. assert(length != 0);
  76. assert(src != NULL);
  77. assert(dest != NULL);
  78. assert(filterCoeffs != NULL);
  79. end = 2 * (numSamples - length);
  80. for (j = 0; j < end; j += 2)
  81. {
  82. const SAMPLETYPE *ptr;
  83. suml = sumr = 0;
  84. ptr = src + j;
  85. for (i = 0; i < length; i += 4)
  86. {
  87. // loop is unrolled by factor of 4 here for efficiency
  88. suml += ptr[2 * i + 0] * filterCoeffs[i + 0] +
  89. ptr[2 * i + 2] * filterCoeffs[i + 1] +
  90. ptr[2 * i + 4] * filterCoeffs[i + 2] +
  91. ptr[2 * i + 6] * filterCoeffs[i + 3];
  92. sumr += ptr[2 * i + 1] * filterCoeffs[i + 0] +
  93. ptr[2 * i + 3] * filterCoeffs[i + 1] +
  94. ptr[2 * i + 5] * filterCoeffs[i + 2] +
  95. ptr[2 * i + 7] * filterCoeffs[i + 3];
  96. }
  97. #ifdef SOUNDTOUCH_INTEGER_SAMPLES
  98. suml >>= resultDivFactor;
  99. sumr >>= resultDivFactor;
  100. // saturate to 16 bit integer limits
  101. suml = (suml < -32768) ? -32768 : (suml > 32767) ? 32767 : suml;
  102. // saturate to 16 bit integer limits
  103. sumr = (sumr < -32768) ? -32768 : (sumr > 32767) ? 32767 : sumr;
  104. #else
  105. suml *= dScaler;
  106. sumr *= dScaler;
  107. #endif // SOUNDTOUCH_INTEGER_SAMPLES
  108. dest[j] = (SAMPLETYPE)suml;
  109. dest[j + 1] = (SAMPLETYPE)sumr;
  110. }
  111. return numSamples - length;
  112. }
  113. // Usual C-version of the filter routine for mono sound
  114. uint FIRFilter::evaluateFilterMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples) const
  115. {
  116. uint i, j, end;
  117. LONG_SAMPLETYPE sum;
  118. #ifdef SOUNDTOUCH_FLOAT_SAMPLES
  119. // when using floating point samples, use a scaler instead of a divider
  120. // because division is much slower operation than multiplying.
  121. double dScaler = 1.0 / (double)resultDivider;
  122. #endif
  123. assert(length != 0);
  124. end = numSamples - length;
  125. for (j = 0; j < end; j ++)
  126. {
  127. sum = 0;
  128. for (i = 0; i < length; i += 4)
  129. {
  130. // loop is unrolled by factor of 4 here for efficiency
  131. sum += src[i + 0] * filterCoeffs[i + 0] +
  132. src[i + 1] * filterCoeffs[i + 1] +
  133. src[i + 2] * filterCoeffs[i + 2] +
  134. src[i + 3] * filterCoeffs[i + 3];
  135. }
  136. #ifdef SOUNDTOUCH_INTEGER_SAMPLES
  137. sum >>= resultDivFactor;
  138. // saturate to 16 bit integer limits
  139. sum = (sum < -32768) ? -32768 : (sum > 32767) ? 32767 : sum;
  140. #else
  141. sum *= dScaler;
  142. #endif // SOUNDTOUCH_INTEGER_SAMPLES
  143. dest[j] = (SAMPLETYPE)sum;
  144. src ++;
  145. }
  146. return end;
  147. }
  148. uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
  149. {
  150. uint i, j, end, c;
  151. LONG_SAMPLETYPE *sum=(LONG_SAMPLETYPE*)malloc(numChannels*sizeof(*sum));
  152. #ifdef SOUNDTOUCH_FLOAT_SAMPLES
  153. // when using floating point samples, use a scaler instead of a divider
  154. // because division is much slower operation than multiplying.
  155. double dScaler = 1.0 / (double)resultDivider;
  156. #endif
  157. assert(length != 0);
  158. assert(src != NULL);
  159. assert(dest != NULL);
  160. assert(filterCoeffs != NULL);
  161. end = numChannels * (numSamples - length);
  162. for (c = 0; c < numChannels; c ++)
  163. {
  164. sum[c] = 0;
  165. }
  166. for (j = 0; j < end; j += numChannels)
  167. {
  168. const SAMPLETYPE *ptr;
  169. ptr = src + j;
  170. for (i = 0; i < length; i ++)
  171. {
  172. SAMPLETYPE coef=filterCoeffs[i];
  173. for (c = 0; c < numChannels; c ++)
  174. {
  175. sum[c] += ptr[0] * coef;
  176. ptr ++;
  177. }
  178. }
  179. for (c = 0; c < numChannels; c ++)
  180. {
  181. #ifdef SOUNDTOUCH_INTEGER_SAMPLES
  182. sum[c] >>= resultDivFactor;
  183. #else
  184. sum[c] *= dScaler;
  185. #endif // SOUNDTOUCH_INTEGER_SAMPLES
  186. *dest = (SAMPLETYPE)sum[c];
  187. dest++;
  188. sum[c] = 0;
  189. }
  190. }
  191. free(sum);
  192. return numSamples - length;
  193. }
  194. // Set filter coeffiecients and length.
  195. //
  196. // Throws an exception if filter length isn't divisible by 8
  197. void FIRFilter::setCoefficients(const SAMPLETYPE *coeffs, uint newLength, uint uResultDivFactor)
  198. {
  199. assert(newLength > 0);
  200. if (newLength % 8) ST_THROW_RT_ERROR("FIR filter length not divisible by 8");
  201. lengthDiv8 = newLength / 8;
  202. length = lengthDiv8 * 8;
  203. assert(length == newLength);
  204. resultDivFactor = uResultDivFactor;
  205. resultDivider = (SAMPLETYPE)::pow(2.0, (int)resultDivFactor);
  206. delete[] filterCoeffs;
  207. filterCoeffs = new SAMPLETYPE[length];
  208. memcpy(filterCoeffs, coeffs, length * sizeof(SAMPLETYPE));
  209. }
  210. uint FIRFilter::getLength() const
  211. {
  212. return length;
  213. }
  214. // Applies the filter to the given sequence of samples.
  215. //
  216. // Note : The amount of outputted samples is by value of 'filter_length'
  217. // smaller than the amount of input samples.
  218. uint FIRFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples, uint numChannels) const
  219. {
  220. assert(length > 0);
  221. assert(lengthDiv8 * 8 == length);
  222. if (numSamples < length) return 0;
  223. #ifndef USE_MULTICH_ALWAYS
  224. if (numChannels == 1)
  225. {
  226. return evaluateFilterMono(dest, src, numSamples);
  227. }
  228. else if (numChannels == 2)
  229. {
  230. return evaluateFilterStereo(dest, src, numSamples);
  231. }
  232. else
  233. #endif // USE_MULTICH_ALWAYS
  234. {
  235. assert(numChannels > 0);
  236. return evaluateFilterMulti(dest, src, numSamples, numChannels);
  237. }
  238. }
  239. // Operator 'new' is overloaded so that it automatically creates a suitable instance
  240. // depending on if we've a MMX-capable CPU available or not.
  241. void * FIRFilter::operator new(size_t s)
  242. {
  243. // Notice! don't use "new FIRFilter" directly, use "newInstance" to create a new instance instead!
  244. ST_THROW_RT_ERROR("Error in FIRFilter::new: Don't use 'new FIRFilter', use 'newInstance' member instead!");
  245. return newInstance();
  246. }
  247. FIRFilter * FIRFilter::newInstance()
  248. {
  249. uint uExtensions;
  250. uExtensions = detectCPUextensions();
  251. // Check if MMX/SSE instruction set extensions supported by CPU
  252. #ifdef SOUNDTOUCH_ALLOW_MMX
  253. // MMX routines available only with integer sample types
  254. if (uExtensions & SUPPORT_MMX)
  255. {
  256. return ::new FIRFilterMMX;
  257. }
  258. else
  259. #endif // SOUNDTOUCH_ALLOW_MMX
  260. #ifdef SOUNDTOUCH_ALLOW_SSE
  261. if (uExtensions & SUPPORT_SSE)
  262. {
  263. // SSE support
  264. return ::new FIRFilterSSE;
  265. }
  266. else
  267. #endif // SOUNDTOUCH_ALLOW_SSE
  268. {
  269. // ISA optimizations not supported, use plain C version
  270. return ::new FIRFilter;
  271. }
  272. }