/external/pysoundtouch14/libsoundtouch/TDStretch.cpp

http://echo-nest-remix.googlecode.com/ · C++ · 1004 lines · 549 code · 196 blank · 259 comment · 63 complexity · 5ee20678f4a246afe0dd697c180d7f21 MD5 · raw file

  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
  5. /// method with several performance-increasing tweaks.
  6. ///
  7. /// Note : MMX optimized functions reside in a separate, platform-specific
  8. /// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.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. // Last changed : $Date: 2009-01-25 15:43:54 +0200 (Sun, 25 Jan 2009) $
  17. // File revision : $Revision: 1.12 $
  18. //
  19. // $Id: TDStretch.cpp 49 2009-01-25 13:43:54Z oparviai $
  20. //
  21. ////////////////////////////////////////////////////////////////////////////////
  22. //
  23. // License :
  24. //
  25. // SoundTouch audio processing library
  26. // Copyright (c) Olli Parviainen
  27. //
  28. // This library is free software; you can redistribute it and/or
  29. // modify it under the terms of the GNU Lesser General Public
  30. // License as published by the Free Software Foundation; either
  31. // version 2.1 of the License, or (at your option) any later version.
  32. //
  33. // This library is distributed in the hope that it will be useful,
  34. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  35. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  36. // Lesser General Public License for more details.
  37. //
  38. // You should have received a copy of the GNU Lesser General Public
  39. // License along with this library; if not, write to the Free Software
  40. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  41. //
  42. ////////////////////////////////////////////////////////////////////////////////
  43. #include <string.h>
  44. #include <limits.h>
  45. #include <assert.h>
  46. #include <math.h>
  47. #include <stdexcept>
  48. #include "STTypes.h"
  49. #include "cpu_detect.h"
  50. #include "TDStretch.h"
  51. using namespace soundtouch;
  52. #ifndef min
  53. //#define min(a,b) (((a) > (b)) ? (b) : (a))
  54. #define max(a,b) (((a) < (b)) ? (b) : (a))
  55. #endif
  56. /*****************************************************************************
  57. *
  58. * Constant definitions
  59. *
  60. *****************************************************************************/
  61. // Table for the hierarchical mixing position seeking algorithm
  62. static const int _scanOffsets[4][24]={
  63. { 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806,
  64. 868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0},
  65. {-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0,
  66. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  67. { -20, -15, -10, -5, 5, 10, 15, 20, 0, 0, 0, 0,
  68. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  69. { -4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0,
  70. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
  71. /*****************************************************************************
  72. *
  73. * Implementation of the class 'TDStretch'
  74. *
  75. *****************************************************************************/
  76. TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
  77. {
  78. bQuickSeek = FALSE;
  79. channels = 2;
  80. bMidBufferDirty = FALSE;
  81. pMidBuffer = NULL;
  82. pRefMidBufferUnaligned = NULL;
  83. overlapLength = 0;
  84. bAutoSeqSetting = TRUE;
  85. bAutoSeekSetting = TRUE;
  86. tempo = 1.0f;
  87. setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
  88. setTempo(1.0f);
  89. }
  90. TDStretch::~TDStretch()
  91. {
  92. delete[] pMidBuffer;
  93. delete[] pRefMidBufferUnaligned;
  94. }
  95. // Sets routine control parameters. These control are certain time constants
  96. // defining how the sound is stretched to the desired duration.
  97. //
  98. // 'sampleRate' = sample rate of the sound
  99. // 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)
  100. // 'seekwindowMS' = seeking window length for scanning the best overlapping
  101. // position (default = 28 ms)
  102. // 'overlapMS' = overlapping length (default = 12 ms)
  103. void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
  104. int aSeekWindowMS, int aOverlapMS)
  105. {
  106. // accept only positive parameter values - if zero or negative, use old values instead
  107. if (aSampleRate > 0) this->sampleRate = aSampleRate;
  108. if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
  109. if (aSequenceMS > 0)
  110. {
  111. this->sequenceMs = aSequenceMS;
  112. bAutoSeqSetting = FALSE;
  113. } else {
  114. // zero or below, use automatic setting
  115. bAutoSeqSetting = TRUE;
  116. }
  117. if (aSeekWindowMS > 0)
  118. {
  119. this->seekWindowMs = aSeekWindowMS;
  120. bAutoSeekSetting = FALSE;
  121. } else {
  122. // zero or below, use automatic setting
  123. bAutoSeekSetting = TRUE;
  124. }
  125. calcSeqParameters();
  126. calculateOverlapLength(overlapMs);
  127. // set tempo to recalculate 'sampleReq'
  128. setTempo(tempo);
  129. }
  130. /// Get routine control parameters, see setParameters() function.
  131. /// Any of the parameters to this function can be NULL, in such case corresponding parameter
  132. /// value isn't returned.
  133. void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const
  134. {
  135. if (pSampleRate)
  136. {
  137. *pSampleRate = sampleRate;
  138. }
  139. if (pSequenceMs)
  140. {
  141. *pSequenceMs = (bAutoSeqSetting) ? (USE_AUTO_SEQUENCE_LEN) : sequenceMs;
  142. }
  143. if (pSeekWindowMs)
  144. {
  145. *pSeekWindowMs = (bAutoSeekSetting) ? (USE_AUTO_SEEKWINDOW_LEN) : seekWindowMs;
  146. }
  147. if (pOverlapMs)
  148. {
  149. *pOverlapMs = overlapMs;
  150. }
  151. }
  152. // Overlaps samples in 'midBuffer' with the samples in 'pInput'
  153. void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const
  154. {
  155. int i, itemp;
  156. for (i = 0; i < overlapLength ; i ++)
  157. {
  158. itemp = overlapLength - i;
  159. pOutput[i] = (pInput[i] * i + pMidBuffer[i] * itemp ) / overlapLength; // >> overlapDividerBits;
  160. }
  161. }
  162. void TDStretch::clearMidBuffer()
  163. {
  164. if (bMidBufferDirty)
  165. {
  166. memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
  167. bMidBufferDirty = FALSE;
  168. }
  169. }
  170. void TDStretch::clearInput()
  171. {
  172. inputBuffer.clear();
  173. clearMidBuffer();
  174. }
  175. // Clears the sample buffers
  176. void TDStretch::clear()
  177. {
  178. outputBuffer.clear();
  179. inputBuffer.clear();
  180. clearMidBuffer();
  181. }
  182. // Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
  183. // to enable
  184. void TDStretch::enableQuickSeek(BOOL enable)
  185. {
  186. bQuickSeek = enable;
  187. }
  188. // Returns nonzero if the quick seeking algorithm is enabled.
  189. BOOL TDStretch::isQuickSeekEnabled() const
  190. {
  191. return bQuickSeek;
  192. }
  193. // Seeks for the optimal overlap-mixing position.
  194. int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
  195. {
  196. if (channels == 2)
  197. {
  198. // stereo sound
  199. if (bQuickSeek)
  200. {
  201. return seekBestOverlapPositionStereoQuick(refPos);
  202. }
  203. else
  204. {
  205. return seekBestOverlapPositionStereo(refPos);
  206. }
  207. }
  208. else
  209. {
  210. // mono sound
  211. if (bQuickSeek)
  212. {
  213. return seekBestOverlapPositionMonoQuick(refPos);
  214. }
  215. else
  216. {
  217. return seekBestOverlapPositionMono(refPos);
  218. }
  219. }
  220. }
  221. // Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position
  222. // of 'ovlPos'.
  223. inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint ovlPos) const
  224. {
  225. if (channels == 2)
  226. {
  227. // stereo sound
  228. overlapStereo(pOutput, pInput + 2 * ovlPos);
  229. } else {
  230. // mono sound.
  231. overlapMono(pOutput, pInput + ovlPos);
  232. }
  233. }
  234. // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
  235. // routine
  236. //
  237. // The best position is determined as the position where the two overlapped
  238. // sample sequences are 'most alike', in terms of the highest cross-correlation
  239. // value over the overlapping period
  240. int TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos)
  241. {
  242. int bestOffs;
  243. LONG_SAMPLETYPE bestCorr, corr;
  244. int i;
  245. // Slopes the amplitudes of the 'midBuffer' samples
  246. precalcCorrReferenceStereo();
  247. bestCorr = INT_MIN;
  248. bestOffs = 0;
  249. // Scans for the best correlation value by testing each possible position
  250. // over the permitted range.
  251. for (i = 0; i < seekLength; i ++)
  252. {
  253. // Calculates correlation value for the mixing position corresponding
  254. // to 'i'
  255. corr = calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);
  256. // Checks for the highest correlation value
  257. if (corr > bestCorr)
  258. {
  259. bestCorr = corr;
  260. bestOffs = i;
  261. }
  262. }
  263. // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
  264. clearCrossCorrState();
  265. return bestOffs;
  266. }
  267. // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
  268. // routine
  269. //
  270. // The best position is determined as the position where the two overlapped
  271. // sample sequences are 'most alike', in terms of the highest cross-correlation
  272. // value over the overlapping period
  273. int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos)
  274. {
  275. int j;
  276. int bestOffs;
  277. LONG_SAMPLETYPE bestCorr, corr;
  278. int scanCount, corrOffset, tempOffset;
  279. // Slopes the amplitude of the 'midBuffer' samples
  280. precalcCorrReferenceStereo();
  281. bestCorr = INT_MIN;
  282. bestOffs = 0;
  283. corrOffset = 0;
  284. tempOffset = 0;
  285. // Scans for the best correlation value using four-pass hierarchical search.
  286. //
  287. // The look-up table 'scans' has hierarchical position adjusting steps.
  288. // In first pass the routine searhes for the highest correlation with
  289. // relatively coarse steps, then rescans the neighbourhood of the highest
  290. // correlation with better resolution and so on.
  291. for (scanCount = 0;scanCount < 4; scanCount ++)
  292. {
  293. j = 0;
  294. while (_scanOffsets[scanCount][j])
  295. {
  296. tempOffset = corrOffset + _scanOffsets[scanCount][j];
  297. if (tempOffset >= seekLength) break;
  298. // Calculates correlation value for the mixing position corresponding
  299. // to 'tempOffset'
  300. corr = calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);
  301. // Checks for the highest correlation value
  302. if (corr > bestCorr)
  303. {
  304. bestCorr = corr;
  305. bestOffs = tempOffset;
  306. }
  307. j ++;
  308. }
  309. corrOffset = bestOffs;
  310. }
  311. // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
  312. clearCrossCorrState();
  313. return bestOffs;
  314. }
  315. // Seeks for the optimal overlap-mixing position. The 'mono' version of the
  316. // routine
  317. //
  318. // The best position is determined as the position where the two overlapped
  319. // sample sequences are 'most alike', in terms of the highest cross-correlation
  320. // value over the overlapping period
  321. int TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos)
  322. {
  323. int bestOffs;
  324. LONG_SAMPLETYPE bestCorr, corr;
  325. int tempOffset;
  326. const SAMPLETYPE *compare;
  327. // Slopes the amplitude of the 'midBuffer' samples
  328. precalcCorrReferenceMono();
  329. bestCorr = INT_MIN;
  330. bestOffs = 0;
  331. // Scans for the best correlation value by testing each possible position
  332. // over the permitted range.
  333. for (tempOffset = 0; tempOffset < seekLength; tempOffset ++)
  334. {
  335. compare = refPos + tempOffset;
  336. // Calculates correlation value for the mixing position corresponding
  337. // to 'tempOffset'
  338. corr = calcCrossCorrMono(pRefMidBuffer, compare);
  339. // Checks for the highest correlation value
  340. if (corr > bestCorr)
  341. {
  342. bestCorr = corr;
  343. bestOffs = tempOffset;
  344. }
  345. }
  346. // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
  347. clearCrossCorrState();
  348. return bestOffs;
  349. }
  350. // Seeks for the optimal overlap-mixing position. The 'mono' version of the
  351. // routine
  352. //
  353. // The best position is determined as the position where the two overlapped
  354. // sample sequences are 'most alike', in terms of the highest cross-correlation
  355. // value over the overlapping period
  356. int TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos)
  357. {
  358. int j;
  359. int bestOffs;
  360. LONG_SAMPLETYPE bestCorr, corr;
  361. int scanCount, corrOffset, tempOffset;
  362. // Slopes the amplitude of the 'midBuffer' samples
  363. precalcCorrReferenceMono();
  364. bestCorr = INT_MIN;
  365. bestOffs = 0;
  366. corrOffset = 0;
  367. tempOffset = 0;
  368. // Scans for the best correlation value using four-pass hierarchical search.
  369. //
  370. // The look-up table 'scans' has hierarchical position adjusting steps.
  371. // In first pass the routine searhes for the highest correlation with
  372. // relatively coarse steps, then rescans the neighbourhood of the highest
  373. // correlation with better resolution and so on.
  374. for (scanCount = 0;scanCount < 4; scanCount ++)
  375. {
  376. j = 0;
  377. while (_scanOffsets[scanCount][j])
  378. {
  379. tempOffset = corrOffset + _scanOffsets[scanCount][j];
  380. if (tempOffset >= seekLength) break;
  381. // Calculates correlation value for the mixing position corresponding
  382. // to 'tempOffset'
  383. corr = calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);
  384. // Checks for the highest correlation value
  385. if (corr > bestCorr)
  386. {
  387. bestCorr = corr;
  388. bestOffs = tempOffset;
  389. }
  390. j ++;
  391. }
  392. corrOffset = bestOffs;
  393. }
  394. // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
  395. clearCrossCorrState();
  396. return bestOffs;
  397. }
  398. /// clear cross correlation routine state if necessary
  399. void TDStretch::clearCrossCorrState()
  400. {
  401. // default implementation is empty.
  402. }
  403. /// Calculates processing sequence length according to tempo setting
  404. void TDStretch::calcSeqParameters()
  405. {
  406. // Adjust tempo param according to tempo, so that variating processing sequence length is used
  407. // at varius tempo settings, between the given low...top limits
  408. #define AUTOSEQ_TEMPO_LOW 0.5 // auto setting low tempo range (-50%)
  409. #define AUTOSEQ_TEMPO_TOP 2.0 // auto setting top tempo range (+100%)
  410. // sequence-ms setting values at above low & top tempo
  411. #define AUTOSEQ_AT_MIN 125.0
  412. #define AUTOSEQ_AT_MAX 50.0
  413. #define AUTOSEQ_K ((AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
  414. #define AUTOSEQ_C (AUTOSEQ_AT_MIN - (AUTOSEQ_K) * (AUTOSEQ_TEMPO_LOW))
  415. // seek-window-ms setting values at above low & top tempo
  416. #define AUTOSEEK_AT_MIN 25.0
  417. #define AUTOSEEK_AT_MAX 15.0
  418. #define AUTOSEEK_K ((AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
  419. #define AUTOSEEK_C (AUTOSEEK_AT_MIN - (AUTOSEEK_K) * (AUTOSEQ_TEMPO_LOW))
  420. #define CHECK_LIMITS(x, mi, ma) ((x) < (mi)) ? (mi) : (((x) > (ma)) ? (ma) : (x))
  421. double seq, seek;
  422. if (bAutoSeqSetting)
  423. {
  424. seq = AUTOSEQ_C + AUTOSEQ_K * tempo;
  425. seq = CHECK_LIMITS(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN);
  426. sequenceMs = (int)(seq + 0.5);
  427. }
  428. if (bAutoSeekSetting)
  429. {
  430. seek = AUTOSEEK_C + AUTOSEEK_K * tempo;
  431. seek = CHECK_LIMITS(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN);
  432. seekWindowMs = (int)(seek + 0.5);
  433. }
  434. // Update seek window lengths
  435. seekWindowLength = (sampleRate * sequenceMs) / 1000;
  436. seekLength = (sampleRate * seekWindowMs) / 1000;
  437. }
  438. // Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
  439. // tempo, larger faster tempo.
  440. void TDStretch::setTempo(float newTempo)
  441. {
  442. int intskip;
  443. tempo = newTempo;
  444. // Calculate new sequence duration
  445. calcSeqParameters();
  446. // Calculate ideal skip length (according to tempo value)
  447. nominalSkip = tempo * (seekWindowLength - overlapLength);
  448. skipFract = 0;
  449. intskip = (int)(nominalSkip + 0.5f);
  450. // Calculate how many samples are needed in the 'inputBuffer' to
  451. // process another batch of samples
  452. sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength;
  453. }
  454. // Sets the number of channels, 1 = mono, 2 = stereo
  455. void TDStretch::setChannels(int numChannels)
  456. {
  457. assert(numChannels > 0);
  458. if (channels == numChannels) return;
  459. assert(numChannels == 1 || numChannels == 2);
  460. channels = numChannels;
  461. inputBuffer.setChannels(channels);
  462. outputBuffer.setChannels(channels);
  463. }
  464. // nominal tempo, no need for processing, just pass the samples through
  465. // to outputBuffer
  466. /*
  467. void TDStretch::processNominalTempo()
  468. {
  469. assert(tempo == 1.0f);
  470. if (bMidBufferDirty)
  471. {
  472. // If there are samples in pMidBuffer waiting for overlapping,
  473. // do a single sliding overlapping with them in order to prevent a
  474. // clicking distortion in the output sound
  475. if (inputBuffer.numSamples() < overlapLength)
  476. {
  477. // wait until we've got overlapLength input samples
  478. return;
  479. }
  480. // Mix the samples in the beginning of 'inputBuffer' with the
  481. // samples in 'midBuffer' using sliding overlapping
  482. overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0);
  483. outputBuffer.putSamples(overlapLength);
  484. inputBuffer.receiveSamples(overlapLength);
  485. clearMidBuffer();
  486. // now we've caught the nominal sample flow and may switch to
  487. // bypass mode
  488. }
  489. // Simply bypass samples from input to output
  490. outputBuffer.moveSamples(inputBuffer);
  491. }
  492. */
  493. // Processes as many processing frames of the samples 'inputBuffer', store
  494. // the result into 'outputBuffer'
  495. void TDStretch::processSamples()
  496. {
  497. int ovlSkip, offset;
  498. int temp;
  499. /* Removed this small optimization - can introduce a click to sound when tempo setting
  500. crosses the nominal value
  501. if (tempo == 1.0f)
  502. {
  503. // tempo not changed from the original, so bypass the processing
  504. processNominalTempo();
  505. return;
  506. }
  507. */
  508. if (bMidBufferDirty == FALSE)
  509. {
  510. // if midBuffer is empty, move the first samples of the input stream
  511. // into it
  512. if ((int)inputBuffer.numSamples() < overlapLength)
  513. {
  514. // wait until we've got overlapLength samples
  515. return;
  516. }
  517. memcpy(pMidBuffer, inputBuffer.ptrBegin(), channels * overlapLength * sizeof(SAMPLETYPE));
  518. inputBuffer.receiveSamples((uint)overlapLength);
  519. bMidBufferDirty = TRUE;
  520. }
  521. // Process samples as long as there are enough samples in 'inputBuffer'
  522. // to form a processing frame.
  523. while ((int)inputBuffer.numSamples() >= sampleReq)
  524. {
  525. // If tempo differs from the normal ('SCALE'), scan for the best overlapping
  526. // position
  527. offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
  528. // Mix the samples in the 'inputBuffer' at position of 'offset' with the
  529. // samples in 'midBuffer' using sliding overlapping
  530. // ... first partially overlap with the end of the previous sequence
  531. // (that's in 'midBuffer')
  532. overlap(outputBuffer.ptrEnd((uint)overlapLength), inputBuffer.ptrBegin(), (uint)offset);
  533. outputBuffer.putSamples((uint)overlapLength);
  534. // ... then copy sequence samples from 'inputBuffer' to output
  535. temp = (seekWindowLength - 2 * overlapLength);// & 0xfffffffe;
  536. if (temp > 0)
  537. {
  538. outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp);
  539. }
  540. // Copies the end of the current sequence from 'inputBuffer' to
  541. // 'midBuffer' for being mixed with the beginning of the next
  542. // processing sequence and so on
  543. assert(offset + seekWindowLength <= (int)inputBuffer.numSamples());
  544. memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + seekWindowLength - overlapLength),
  545. channels * sizeof(SAMPLETYPE) * overlapLength);
  546. bMidBufferDirty = TRUE;
  547. // Remove the processed samples from the input buffer. Update
  548. // the difference between integer & nominal skip step to 'skipFract'
  549. // in order to prevent the error from accumulating over time.
  550. skipFract += nominalSkip; // real skip size
  551. ovlSkip = (int)skipFract; // rounded to integer skip
  552. skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip
  553. inputBuffer.receiveSamples((uint)ovlSkip);
  554. }
  555. }
  556. // Adds 'numsamples' pcs of samples from the 'samples' memory position into
  557. // the input of the object.
  558. void TDStretch::putSamples(const SAMPLETYPE *samples, uint nSamples)
  559. {
  560. // Add the samples into the input buffer
  561. inputBuffer.putSamples(samples, nSamples);
  562. // Process the samples in input buffer
  563. processSamples();
  564. }
  565. /// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
  566. void TDStretch::acceptNewOverlapLength(int newOverlapLength)
  567. {
  568. int prevOvl;
  569. assert(newOverlapLength >= 0);
  570. prevOvl = overlapLength;
  571. overlapLength = newOverlapLength;
  572. if (overlapLength > prevOvl)
  573. {
  574. delete[] pMidBuffer;
  575. delete[] pRefMidBufferUnaligned;
  576. pMidBuffer = new SAMPLETYPE[overlapLength * 2];
  577. bMidBufferDirty = TRUE;
  578. clearMidBuffer();
  579. pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];
  580. // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency
  581. pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & (ulong)-16);
  582. }
  583. }
  584. // Operator 'new' is overloaded so that it automatically creates a suitable instance
  585. // depending on if we've a MMX/SSE/etc-capable CPU available or not.
  586. void * TDStretch::operator new(size_t s)
  587. {
  588. // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
  589. throw std::runtime_error("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!");
  590. return NULL;
  591. }
  592. TDStretch * TDStretch::newInstance()
  593. {
  594. uint uExtensions;
  595. uExtensions = detectCPUextensions();
  596. // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
  597. #ifdef ALLOW_MMX
  598. // MMX routines available only with integer sample types
  599. if (uExtensions & SUPPORT_MMX)
  600. {
  601. return ::new TDStretchMMX;
  602. }
  603. else
  604. #endif // ALLOW_MMX
  605. #ifdef ALLOW_SSE
  606. if (uExtensions & SUPPORT_SSE)
  607. {
  608. // SSE support
  609. return ::new TDStretchSSE;
  610. }
  611. else
  612. #endif // ALLOW_SSE
  613. #ifdef ALLOW_3DNOW
  614. if (uExtensions & SUPPORT_3DNOW)
  615. {
  616. // 3DNow! support
  617. return ::new TDStretch3DNow;
  618. }
  619. else
  620. #endif // ALLOW_3DNOW
  621. {
  622. // ISA optimizations not supported, use plain C version
  623. return ::new TDStretch;
  624. }
  625. }
  626. //////////////////////////////////////////////////////////////////////////////
  627. //
  628. // Integer arithmetics specific algorithm implementations.
  629. //
  630. //////////////////////////////////////////////////////////////////////////////
  631. #ifdef INTEGER_SAMPLES
  632. // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
  633. // is faster to calculate
  634. void TDStretch::precalcCorrReferenceStereo()
  635. {
  636. int i, cnt2;
  637. int temp, temp2;
  638. for (i=0 ; i < (int)overlapLength ;i ++)
  639. {
  640. temp = i * (overlapLength - i);
  641. cnt2 = i * 2;
  642. temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
  643. pRefMidBuffer[cnt2] = (short)(temp2);
  644. temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
  645. pRefMidBuffer[cnt2 + 1] = (short)(temp2);
  646. }
  647. }
  648. // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
  649. // is faster to calculate
  650. void TDStretch::precalcCorrReferenceMono()
  651. {
  652. int i;
  653. long temp;
  654. long temp2;
  655. for (i=0 ; i < (int)overlapLength ;i ++)
  656. {
  657. temp = i * (overlapLength - i);
  658. temp2 = (pMidBuffer[i] * temp) / slopingDivider;
  659. pRefMidBuffer[i] = (short)temp2;
  660. }
  661. }
  662. // Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo'
  663. // version of the routine.
  664. void TDStretch::overlapStereo(short *output, const short *input) const
  665. {
  666. int i;
  667. short temp;
  668. uint cnt2;
  669. for (i = 0; i < (int)overlapLength ; i ++)
  670. {
  671. temp = (short)(overlapLength - i);
  672. cnt2 = 2 * i;
  673. output[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp ) / overlapLength;
  674. output[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength;
  675. }
  676. }
  677. // Calculates the x having the closest 2^x value for the given value
  678. static int _getClosest2Power(double value)
  679. {
  680. return (int)(log(value) / log(2.0) + 0.5);
  681. }
  682. /// Calculates overlap period length in samples.
  683. /// Integer version rounds overlap length to closest power of 2
  684. /// for a divide scaling operation.
  685. void TDStretch::calculateOverlapLength(int overlapMs)
  686. {
  687. int newOvl;
  688. assert(overlapMs >= 0);
  689. overlapDividerBits = _getClosest2Power((sampleRate * overlapMs) / 1000.0);
  690. if (overlapDividerBits > 9) overlapDividerBits = 9;
  691. if (overlapDividerBits < 4) overlapDividerBits = 4;
  692. newOvl = (int)pow(2, (double) overlapDividerBits);
  693. acceptNewOverlapLength(newOvl);
  694. // calculate sloping divider so that crosscorrelation operation won't
  695. // overflow 32-bit register. Max. sum of the crosscorrelation sum without
  696. // divider would be 2^30*(N^3-N)/3, where N = overlap length
  697. slopingDivider = (newOvl * newOvl - 1) / 3;
  698. }
  699. long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
  700. {
  701. long corr;
  702. int i;
  703. corr = 0;
  704. for (i = 1; i < overlapLength; i ++)
  705. {
  706. corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
  707. }
  708. return corr;
  709. }
  710. long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
  711. {
  712. long corr;
  713. int i;
  714. corr = 0;
  715. for (i = 2; i < 2 * overlapLength; i += 2)
  716. {
  717. corr += (mixingPos[i] * compare[i] +
  718. mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;
  719. }
  720. return corr;
  721. }
  722. #endif // INTEGER_SAMPLES
  723. //////////////////////////////////////////////////////////////////////////////
  724. //
  725. // Floating point arithmetics specific algorithm implementations.
  726. //
  727. #ifdef FLOAT_SAMPLES
  728. // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
  729. // is faster to calculate
  730. void TDStretch::precalcCorrReferenceStereo()
  731. {
  732. int i, cnt2;
  733. float temp;
  734. for (i=0 ; i < (int)overlapLength ;i ++)
  735. {
  736. temp = (float)i * (float)(overlapLength - i);
  737. cnt2 = i * 2;
  738. pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);
  739. pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);
  740. }
  741. }
  742. // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
  743. // is faster to calculate
  744. void TDStretch::precalcCorrReferenceMono()
  745. {
  746. int i;
  747. float temp;
  748. for (i=0 ; i < (int)overlapLength ;i ++)
  749. {
  750. temp = (float)i * (float)(overlapLength - i);
  751. pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
  752. }
  753. }
  754. // Overlaps samples in 'midBuffer' with the samples in 'pInput'
  755. void TDStretch::overlapStereo(float *pOutput, const float *pInput) const
  756. {
  757. int i;
  758. int cnt2;
  759. float fTemp;
  760. float fScale;
  761. float fi;
  762. fScale = 1.0f / (float)overlapLength;
  763. for (i = 0; i < (int)overlapLength ; i ++)
  764. {
  765. fTemp = (float)(overlapLength - i) * fScale;
  766. fi = (float)i * fScale;
  767. cnt2 = 2 * i;
  768. pOutput[cnt2 + 0] = pInput[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;
  769. pOutput[cnt2 + 1] = pInput[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;
  770. }
  771. }
  772. /// Calculates overlapInMsec period length in samples.
  773. void TDStretch::calculateOverlapLength(int overlapInMsec)
  774. {
  775. int newOvl;
  776. assert(overlapInMsec >= 0);
  777. newOvl = (sampleRate * overlapInMsec) / 1000;
  778. if (newOvl < 16) newOvl = 16;
  779. // must be divisible by 8
  780. newOvl -= newOvl % 8;
  781. acceptNewOverlapLength(newOvl);
  782. }
  783. double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
  784. {
  785. double corr;
  786. int i;
  787. corr = 0;
  788. for (i = 1; i < overlapLength; i ++)
  789. {
  790. corr += mixingPos[i] * compare[i];
  791. }
  792. return corr;
  793. }
  794. double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
  795. {
  796. double corr;
  797. int i;
  798. corr = 0;
  799. for (i = 2; i < 2 * overlapLength; i += 2)
  800. {
  801. corr += mixingPos[i] * compare[i] +
  802. mixingPos[i + 1] * compare[i + 1];
  803. }
  804. return corr;
  805. }
  806. #endif // FLOAT_SAMPLES