RateTransposer.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. ////////////////////////////////////////////////////////////////////////////////
  2. ///
  3. /// Sample rate transposer. Changes sample rate by using linear interpolation
  4. /// together with anti-alias filtering (first order interpolation with anti-
  5. /// alias filtering should be quite adequate for this application)
  6. ///
  7. /// Author : Copyright (c) Olli Parviainen
  8. /// Author e-mail : oparviai 'at' iki.fi
  9. /// SoundTouch WWW: http://www.surina.net/soundtouch
  10. ///
  11. ////////////////////////////////////////////////////////////////////////////////
  12. //
  13. // License :
  14. //
  15. // SoundTouch audio processing library
  16. // Copyright (c) Olli Parviainen
  17. //
  18. // This library is free software; you can redistribute it and/or
  19. // modify it under the terms of the GNU Lesser General Public
  20. // License as published by the Free Software Foundation; either
  21. // version 2.1 of the License, or (at your option) any later version.
  22. //
  23. // This library is distributed in the hope that it will be useful,
  24. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  26. // Lesser General Public License for more details.
  27. //
  28. // You should have received a copy of the GNU Lesser General Public
  29. // License along with this library; if not, write to the Free Software
  30. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  31. //
  32. ////////////////////////////////////////////////////////////////////////////////
  33. #include <memory.h>
  34. #include <assert.h>
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include "RateTransposer.h"
  38. #include "InterpolateLinear.h"
  39. #include "InterpolateCubic.h"
  40. #include "InterpolateShannon.h"
  41. #include "AAFilter.h"
  42. using namespace soundtouch;
  43. // Define default interpolation algorithm here
  44. TransposerBase::ALGORITHM TransposerBase::algorithm = TransposerBase::CUBIC;
  45. // Constructor
  46. RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
  47. {
  48. bUseAAFilter =
  49. #ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
  50. true;
  51. #else
  52. // Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
  53. false;
  54. #endif
  55. // Instantiates the anti-alias filter
  56. pAAFilter = new AAFilter(64);
  57. pTransposer = TransposerBase::newInstance();
  58. clear();
  59. }
  60. RateTransposer::~RateTransposer()
  61. {
  62. delete pAAFilter;
  63. delete pTransposer;
  64. }
  65. /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
  66. void RateTransposer::enableAAFilter(bool newMode)
  67. {
  68. #ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
  69. // Disable Anti-alias filter if desirable to avoid click at rate change zero value crossover
  70. bUseAAFilter = newMode;
  71. clear();
  72. #endif
  73. }
  74. /// Returns nonzero if anti-alias filter is enabled.
  75. bool RateTransposer::isAAFilterEnabled() const
  76. {
  77. return bUseAAFilter;
  78. }
  79. AAFilter *RateTransposer::getAAFilter()
  80. {
  81. return pAAFilter;
  82. }
  83. // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
  84. // iRate, larger faster iRates.
  85. void RateTransposer::setRate(double newRate)
  86. {
  87. double fCutoff;
  88. pTransposer->setRate(newRate);
  89. // design a new anti-alias filter
  90. if (newRate > 1.0)
  91. {
  92. fCutoff = 0.5 / newRate;
  93. }
  94. else
  95. {
  96. fCutoff = 0.5 * newRate;
  97. }
  98. pAAFilter->setCutoffFreq(fCutoff);
  99. }
  100. // Adds 'nSamples' pcs of samples from the 'samples' memory position into
  101. // the input of the object.
  102. void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
  103. {
  104. processSamples(samples, nSamples);
  105. }
  106. // Transposes sample rate by applying anti-alias filter to prevent folding.
  107. // Returns amount of samples returned in the "dest" buffer.
  108. // The maximum amount of samples that can be returned at a time is set by
  109. // the 'set_returnBuffer_size' function.
  110. void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
  111. {
  112. uint count;
  113. if (nSamples == 0) return;
  114. // Store samples to input buffer
  115. inputBuffer.putSamples(src, nSamples);
  116. // If anti-alias filter is turned off, simply transpose without applying
  117. // the filter
  118. if (bUseAAFilter == false)
  119. {
  120. count = pTransposer->transpose(outputBuffer, inputBuffer);
  121. return;
  122. }
  123. assert(pAAFilter);
  124. // Transpose with anti-alias filter
  125. if (pTransposer->rate < 1.0f)
  126. {
  127. // If the parameter 'Rate' value is smaller than 1, first transpose
  128. // the samples and then apply the anti-alias filter to remove aliasing.
  129. // Transpose the samples, store the result to end of "midBuffer"
  130. pTransposer->transpose(midBuffer, inputBuffer);
  131. // Apply the anti-alias filter for transposed samples in midBuffer
  132. pAAFilter->evaluate(outputBuffer, midBuffer);
  133. }
  134. else
  135. {
  136. // If the parameter 'Rate' value is larger than 1, first apply the
  137. // anti-alias filter to remove high frequencies (prevent them from folding
  138. // over the lover frequencies), then transpose.
  139. // Apply the anti-alias filter for samples in inputBuffer
  140. pAAFilter->evaluate(midBuffer, inputBuffer);
  141. // Transpose the AA-filtered samples in "midBuffer"
  142. pTransposer->transpose(outputBuffer, midBuffer);
  143. }
  144. }
  145. // Sets the number of channels, 1 = mono, 2 = stereo
  146. void RateTransposer::setChannels(int nChannels)
  147. {
  148. if (!verifyNumberOfChannels(nChannels) ||
  149. (pTransposer->numChannels == nChannels)) return;
  150. pTransposer->setChannels(nChannels);
  151. inputBuffer.setChannels(nChannels);
  152. midBuffer.setChannels(nChannels);
  153. outputBuffer.setChannels(nChannels);
  154. }
  155. // Clears all the samples in the object
  156. void RateTransposer::clear()
  157. {
  158. outputBuffer.clear();
  159. midBuffer.clear();
  160. inputBuffer.clear();
  161. pTransposer->resetRegisters();
  162. // prefill buffer to avoid losing first samples at beginning of stream
  163. int prefill = getLatency();
  164. inputBuffer.addSilent(prefill);
  165. }
  166. // Returns nonzero if there aren't any samples available for outputting.
  167. int RateTransposer::isEmpty() const
  168. {
  169. int res;
  170. res = FIFOProcessor::isEmpty();
  171. if (res == 0) return 0;
  172. return inputBuffer.isEmpty();
  173. }
  174. /// Return approximate initial input-output latency
  175. int RateTransposer::getLatency() const
  176. {
  177. return pTransposer->getLatency() +
  178. ((bUseAAFilter) ? (pAAFilter->getLength() / 2) : 0);
  179. }
  180. //////////////////////////////////////////////////////////////////////////////
  181. //
  182. // TransposerBase - Base class for interpolation
  183. //
  184. // static function to set interpolation algorithm
  185. void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a)
  186. {
  187. TransposerBase::algorithm = a;
  188. }
  189. // Transposes the sample rate of the given samples using linear interpolation.
  190. // Returns the number of samples returned in the "dest" buffer
  191. int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
  192. {
  193. int numSrcSamples = src.numSamples();
  194. int sizeDemand = (int)((double)numSrcSamples / rate) + 8;
  195. int numOutput;
  196. SAMPLETYPE *psrc = src.ptrBegin();
  197. SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
  198. #ifndef USE_MULTICH_ALWAYS
  199. if (numChannels == 1)
  200. {
  201. numOutput = transposeMono(pdest, psrc, numSrcSamples);
  202. }
  203. else if (numChannels == 2)
  204. {
  205. numOutput = transposeStereo(pdest, psrc, numSrcSamples);
  206. }
  207. else
  208. #endif // USE_MULTICH_ALWAYS
  209. {
  210. assert(numChannels > 0);
  211. numOutput = transposeMulti(pdest, psrc, numSrcSamples);
  212. }
  213. dest.putSamples(numOutput);
  214. src.receiveSamples(numSrcSamples);
  215. return numOutput;
  216. }
  217. TransposerBase::TransposerBase()
  218. {
  219. numChannels = 0;
  220. rate = 1.0f;
  221. }
  222. TransposerBase::~TransposerBase()
  223. {
  224. }
  225. void TransposerBase::setChannels(int channels)
  226. {
  227. numChannels = channels;
  228. resetRegisters();
  229. }
  230. void TransposerBase::setRate(double newRate)
  231. {
  232. rate = newRate;
  233. }
  234. // static factory function
  235. TransposerBase *TransposerBase::newInstance()
  236. {
  237. #ifdef SOUNDTOUCH_INTEGER_SAMPLES
  238. // Notice: For integer arithmetic support only linear algorithm (due to simplest calculus)
  239. return ::new InterpolateLinearInteger;
  240. #else
  241. switch (algorithm)
  242. {
  243. case LINEAR:
  244. return new InterpolateLinearFloat;
  245. case CUBIC:
  246. return new InterpolateCubic;
  247. case SHANNON:
  248. return new InterpolateShannon;
  249. default:
  250. assert(false);
  251. return NULL;
  252. }
  253. #endif
  254. }