TDStretch.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. ////////////////////////////////////////////////////////////////////////////////
  2. ///
  3. /// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo
  4. /// while maintaining the original pitch by using a time domain WSOLA-like method
  5. /// with several performance-increasing tweaks.
  6. ///
  7. /// Note : MMX/SSE optimized functions reside in separate, platform-specific files
  8. /// 'mmx_optimized.cpp' and 'sse_optimized.cpp'
  9. ///
  10. /// Author : Copyright (c) Olli Parviainen
  11. /// Author e-mail : oparviai 'at' iki.fi
  12. /// SoundTouch WWW: http://www.surina.net/soundtouch
  13. ///
  14. ////////////////////////////////////////////////////////////////////////////////
  15. //
  16. // License :
  17. //
  18. // SoundTouch audio processing library
  19. // Copyright (c) Olli Parviainen
  20. //
  21. // This library is free software; you can redistribute it and/or
  22. // modify it under the terms of the GNU Lesser General Public
  23. // License as published by the Free Software Foundation; either
  24. // version 2.1 of the License, or (at your option) any later version.
  25. //
  26. // This library is distributed in the hope that it will be useful,
  27. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  29. // Lesser General Public License for more details.
  30. //
  31. // You should have received a copy of the GNU Lesser General Public
  32. // License along with this library; if not, write to the Free Software
  33. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  34. //
  35. ////////////////////////////////////////////////////////////////////////////////
  36. #ifndef TDStretch_H
  37. #define TDStretch_H
  38. #include <stddef.h>
  39. #include "STTypes.h"
  40. #include "RateTransposer.h"
  41. #include "FIFOSamplePipe.h"
  42. namespace soundtouch
  43. {
  44. /// Default values for sound processing parameters:
  45. /// Notice that the default parameters are tuned for contemporary popular music
  46. /// processing. For speech processing applications these parameters suit better:
  47. /// #define DEFAULT_SEQUENCE_MS 40
  48. /// #define DEFAULT_SEEKWINDOW_MS 15
  49. /// #define DEFAULT_OVERLAP_MS 8
  50. ///
  51. /// Default length of a single processing sequence, in milliseconds. This determines to how
  52. /// long sequences the original sound is chopped in the time-stretch algorithm.
  53. ///
  54. /// The larger this value is, the lesser sequences are used in processing. In principle
  55. /// a bigger value sounds better when slowing down tempo, but worse when increasing tempo
  56. /// and vice versa.
  57. ///
  58. /// Increasing this value reduces computational burden & vice versa.
  59. //#define DEFAULT_SEQUENCE_MS 40
  60. #define DEFAULT_SEQUENCE_MS USE_AUTO_SEQUENCE_LEN
  61. /// Giving this value for the sequence length sets automatic parameter value
  62. /// according to tempo setting (recommended)
  63. #define USE_AUTO_SEQUENCE_LEN 0
  64. /// Seeking window default length in milliseconds for algorithm that finds the best possible
  65. /// overlapping location. This determines from how wide window the algorithm may look for an
  66. /// optimal joining location when mixing the sound sequences back together.
  67. ///
  68. /// The bigger this window setting is, the higher the possibility to find a better mixing
  69. /// position will become, but at the same time large values may cause a "drifting" artifact
  70. /// because consequent sequences will be taken at more uneven intervals.
  71. ///
  72. /// If there's a disturbing artifact that sounds as if a constant frequency was drifting
  73. /// around, try reducing this setting.
  74. ///
  75. /// Increasing this value increases computational burden & vice versa.
  76. //#define DEFAULT_SEEKWINDOW_MS 15
  77. #define DEFAULT_SEEKWINDOW_MS USE_AUTO_SEEKWINDOW_LEN
  78. /// Giving this value for the seek window length sets automatic parameter value
  79. /// according to tempo setting (recommended)
  80. #define USE_AUTO_SEEKWINDOW_LEN 0
  81. /// Overlap length in milliseconds. When the chopped sound sequences are mixed back together,
  82. /// to form a continuous sound stream, this parameter defines over how long period the two
  83. /// consecutive sequences are let to overlap each other.
  84. ///
  85. /// This shouldn't be that critical parameter. If you reduce the DEFAULT_SEQUENCE_MS setting
  86. /// by a large amount, you might wish to try a smaller value on this.
  87. ///
  88. /// Increasing this value increases computational burden & vice versa.
  89. #define DEFAULT_OVERLAP_MS 8
  90. /// Class that does the time-stretch (tempo change) effect for the processed
  91. /// sound.
  92. class TDStretch : public FIFOProcessor
  93. {
  94. protected:
  95. int channels;
  96. int sampleReq;
  97. int overlapLength;
  98. int seekLength;
  99. int seekWindowLength;
  100. int overlapDividerBitsNorm;
  101. int overlapDividerBitsPure;
  102. int slopingDivider;
  103. int sampleRate;
  104. int sequenceMs;
  105. int seekWindowMs;
  106. int overlapMs;
  107. unsigned long maxnorm;
  108. float maxnormf;
  109. double tempo;
  110. double nominalSkip;
  111. double skipFract;
  112. bool bQuickSeek;
  113. bool bAutoSeqSetting;
  114. bool bAutoSeekSetting;
  115. bool isBeginning;
  116. SAMPLETYPE *pMidBuffer;
  117. SAMPLETYPE *pMidBufferUnaligned;
  118. FIFOSampleBuffer outputBuffer;
  119. FIFOSampleBuffer inputBuffer;
  120. void acceptNewOverlapLength(int newOverlapLength);
  121. virtual void clearCrossCorrState();
  122. void calculateOverlapLength(int overlapMs);
  123. virtual double calcCrossCorr(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare, double &norm);
  124. virtual double calcCrossCorrAccumulate(const SAMPLETYPE *mixingPos, const SAMPLETYPE *compare, double &norm);
  125. virtual int seekBestOverlapPositionFull(const SAMPLETYPE *refPos);
  126. virtual int seekBestOverlapPositionQuick(const SAMPLETYPE *refPos);
  127. virtual int seekBestOverlapPosition(const SAMPLETYPE *refPos);
  128. virtual void overlapStereo(SAMPLETYPE *output, const SAMPLETYPE *input) const;
  129. virtual void overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const;
  130. virtual void overlapMulti(SAMPLETYPE *output, const SAMPLETYPE *input) const;
  131. void clearMidBuffer();
  132. void overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const;
  133. void calcSeqParameters();
  134. void adaptNormalizer();
  135. /// Changes the tempo of the given sound samples.
  136. /// Returns amount of samples returned in the "output" buffer.
  137. /// The maximum amount of samples that can be returned at a time is set by
  138. /// the 'set_returnBuffer_size' function.
  139. void processSamples();
  140. public:
  141. TDStretch();
  142. virtual ~TDStretch();
  143. /// Operator 'new' is overloaded so that it automatically creates a suitable instance
  144. /// depending on if we've a MMX/SSE/etc-capable CPU available or not.
  145. static void *operator new(size_t s);
  146. /// Use this function instead of "new" operator to create a new instance of this class.
  147. /// This function automatically chooses a correct feature set depending on if the CPU
  148. /// supports MMX/SSE/etc extensions.
  149. static TDStretch *newInstance();
  150. /// Returns the output buffer object
  151. FIFOSamplePipe *getOutput() { return &outputBuffer; };
  152. /// Returns the input buffer object
  153. FIFOSamplePipe *getInput() { return &inputBuffer; };
  154. /// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
  155. /// tempo, larger faster tempo.
  156. void setTempo(double newTempo);
  157. /// Returns nonzero if there aren't any samples available for outputting.
  158. virtual void clear();
  159. /// Clears the input buffer
  160. void clearInput();
  161. /// Sets the number of channels, 1 = mono, 2 = stereo
  162. void setChannels(int numChannels);
  163. /// Enables/disables the quick position seeking algorithm. Zero to disable,
  164. /// nonzero to enable
  165. void enableQuickSeek(bool enable);
  166. /// Returns nonzero if the quick seeking algorithm is enabled.
  167. bool isQuickSeekEnabled() const;
  168. /// Sets routine control parameters. These control are certain time constants
  169. /// defining how the sound is stretched to the desired duration.
  170. //
  171. /// 'sampleRate' = sample rate of the sound
  172. /// 'sequenceMS' = one processing sequence length in milliseconds
  173. /// 'seekwindowMS' = seeking window length for scanning the best overlapping
  174. /// position
  175. /// 'overlapMS' = overlapping length
  176. void setParameters(int sampleRate, ///< Samplerate of sound being processed (Hz)
  177. int sequenceMS = -1, ///< Single processing sequence length (ms)
  178. int seekwindowMS = -1, ///< Offset seeking window length (ms)
  179. int overlapMS = -1 ///< Sequence overlapping length (ms)
  180. );
  181. /// Get routine control parameters, see setParameters() function.
  182. /// Any of the parameters to this function can be NULL, in such case corresponding parameter
  183. /// value isn't returned.
  184. void getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const;
  185. /// Adds 'numsamples' pcs of samples from the 'samples' memory position into
  186. /// the input of the object.
  187. virtual void putSamples(
  188. const SAMPLETYPE *samples, ///< Input sample data
  189. uint numSamples ///< Number of samples in 'samples' so that one sample
  190. ///< contains both channels if stereo
  191. );
  192. /// return nominal input sample requirement for triggering a processing batch
  193. int getInputSampleReq() const
  194. {
  195. return (int)(nominalSkip + 0.5);
  196. }
  197. /// return nominal output sample amount when running a processing batch
  198. int getOutputBatchSize() const
  199. {
  200. return seekWindowLength - overlapLength;
  201. }
  202. /// return approximate initial input-output latency
  203. int getLatency() const
  204. {
  205. return sampleReq;
  206. }
  207. };
  208. // Implementation-specific class declarations:
  209. #ifdef SOUNDTOUCH_ALLOW_MMX
  210. /// Class that implements MMX optimized routines for 16bit integer samples type.
  211. class TDStretchMMX : public TDStretch
  212. {
  213. protected:
  214. double calcCrossCorr(const short *mixingPos, const short *compare, double &norm);
  215. double calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm);
  216. virtual void overlapStereo(short *output, const short *input) const;
  217. virtual void clearCrossCorrState();
  218. };
  219. #endif /// SOUNDTOUCH_ALLOW_MMX
  220. #ifdef SOUNDTOUCH_ALLOW_SSE
  221. /// Class that implements SSE optimized routines for floating point samples type.
  222. class TDStretchSSE : public TDStretch
  223. {
  224. protected:
  225. double calcCrossCorr(const float *mixingPos, const float *compare, double &norm);
  226. double calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm);
  227. };
  228. #endif /// SOUNDTOUCH_ALLOW_SSE
  229. }
  230. #endif /// TDStretch_H