remove a bunch of explicit uses of '/' as a directory separator; use Glib::build_file...
[ardour2.git] / libs / soundtouch / TDStretch.cpp
blobd08dbc20284825862a98a64277127aeb272e46d0
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 @ iki.fi
12 /// SoundTouch WWW: http://www.iki.fi/oparviai/soundtouch
13 ///
14 ////////////////////////////////////////////////////////////////////////////////
16 // Last changed : $Date$
17 // File revision : $Revision$
19 // $Id$
21 ////////////////////////////////////////////////////////////////////////////////
23 // License :
25 // SoundTouch audio processing library
26 // Copyright (c) Olli Parviainen
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.
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.
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
42 ////////////////////////////////////////////////////////////////////////////////
44 #include <cstring>
45 #include <cstdlib>
46 #include <memory.h>
47 #include <climits>
48 #include <cmath>
49 #include <cassert>
51 #include "STTypes.h"
52 #include "cpu_detect.h"
53 #include "TDStretch.h"
55 using namespace soundtouch;
57 #ifndef min
58 #define min(a,b) ((a > b) ? b : a)
59 #define max(a,b) ((a < b) ? b : a)
60 #endif
64 /*****************************************************************************
66 * Constant definitions
68 *****************************************************************************/
71 #define MAX_SCAN_DELTA 124
73 // Table for the hierarchical mixing position seeking algorithm
74 int scanOffsets[4][24]={
75 { 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806,
76 868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0},
77 {-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0,
78 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
79 { -20, -15, -10, -5, 5, 10, 15, 20, 0, 0, 0, 0,
80 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
81 { -4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
84 /*****************************************************************************
86 * Implementation of the class 'TDStretch'
88 *****************************************************************************/
91 TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
93 bQuickseek = FALSE;
94 channels = 2;
95 bMidBufferDirty = FALSE;
97 pMidBuffer = NULL;
98 pRefMidBufferUnaligned = NULL;
99 overlapLength = 0;
101 setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
103 setTempo(1.0f);
109 TDStretch::~TDStretch()
111 delete[] pMidBuffer;
112 delete[] pRefMidBufferUnaligned;
118 // Sets routine control parameters. These control are certain time constants
119 // defining how the sound is stretched to the desired duration.
121 // 'sampleRate' = sample rate of the sound
122 // 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)
123 // 'seekwindowMS' = seeking window length for scanning the best overlapping
124 // position (default = 28 ms)
125 // 'overlapMS' = overlapping length (default = 12 ms)
127 void TDStretch::setParameters(uint aSampleRate, uint aSequenceMS,
128 uint aSeekWindowMS, uint aOverlapMS)
130 this->sampleRate = aSampleRate;
131 this->sequenceMs = aSequenceMS;
132 this->seekWindowMs = aSeekWindowMS;
133 this->overlapMs = aOverlapMS;
135 seekLength = (sampleRate * seekWindowMs) / 1000;
136 seekWindowLength = (sampleRate * sequenceMs) / 1000;
138 maxOffset = seekLength;
140 calculateOverlapLength(overlapMs);
142 // set tempo to recalculate 'sampleReq'
143 setTempo(tempo);
149 /// Get routine control parameters, see setParameters() function.
150 /// Any of the parameters to this function can be NULL, in such case corresponding parameter
151 /// value isn't returned.
152 void TDStretch::getParameters(uint *pSampleRate, uint *pSequenceMs, uint *pSeekWindowMs, uint *pOverlapMs)
154 if (pSampleRate)
156 *pSampleRate = sampleRate;
159 if (pSequenceMs)
161 *pSequenceMs = sequenceMs;
164 if (pSeekWindowMs)
166 *pSeekWindowMs = seekWindowMs;
169 if (pOverlapMs)
171 *pOverlapMs = overlapMs;
176 // Overlaps samples in 'midBuffer' with the samples in 'input'
177 void TDStretch::overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const
179 int i, itemp;
181 for (i = 0; i < (int)overlapLength ; i ++)
183 itemp = overlapLength - i;
184 output[i] = (input[i] * i + pMidBuffer[i] * itemp ) / overlapLength; // >> overlapDividerBits;
190 void TDStretch::clearMidBuffer()
192 if (bMidBufferDirty)
194 memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
195 bMidBufferDirty = FALSE;
200 void TDStretch::clearInput()
202 inputBuffer.clear();
203 clearMidBuffer();
207 // Clears the sample buffers
208 void TDStretch::clear()
210 outputBuffer.clear();
211 inputBuffer.clear();
212 clearMidBuffer();
217 // Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
218 // to enable
219 void TDStretch::enableQuickSeek(BOOL enable)
221 bQuickseek = enable;
225 // Returns nonzero if the quick seeking algorithm is enabled.
226 BOOL TDStretch::isQuickSeekEnabled() const
228 return bQuickseek;
232 // Seeks for the optimal overlap-mixing position.
233 uint TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
235 if (channels == 2)
237 // stereo sound
238 if (bQuickseek)
240 return seekBestOverlapPositionStereoQuick(refPos);
242 else
244 return seekBestOverlapPositionStereo(refPos);
247 else
249 // mono sound
250 if (bQuickseek)
252 return seekBestOverlapPositionMonoQuick(refPos);
254 else
256 return seekBestOverlapPositionMono(refPos);
264 // Overlaps samples in 'midBuffer' with the samples in 'inputBuffer' at position
265 // of 'ovlPos'.
266 inline void TDStretch::overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const
268 if (channels == 2)
270 // stereo sound
271 overlapStereo(output, input + 2 * ovlPos);
272 } else {
273 // mono sound.
274 overlapMono(output, input + ovlPos);
281 // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
282 // routine
284 // The best position is determined as the position where the two overlapped
285 // sample sequences are 'most alike', in terms of the highest cross-correlation
286 // value over the overlapping period
287 uint TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos)
289 uint bestOffs;
290 LONG_SAMPLETYPE bestCorr, corr;
291 uint i;
293 // Slopes the amplitudes of the 'midBuffer' samples
294 precalcCorrReferenceStereo();
296 bestCorr = INT_MIN;
297 bestOffs = 0;
299 // Scans for the best correlation value by testing each possible position
300 // over the permitted range.
301 for (i = 0; i < seekLength; i ++)
303 // Calculates correlation value for the mixing position corresponding
304 // to 'i'
305 corr = calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);
307 // Checks for the highest correlation value
308 if (corr > bestCorr)
310 bestCorr = corr;
311 bestOffs = i;
314 // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
315 clearCrossCorrState();
317 return bestOffs;
321 // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
322 // routine
324 // The best position is determined as the position where the two overlapped
325 // sample sequences are 'most alike', in terms of the highest cross-correlation
326 // value over the overlapping period
327 uint TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos)
329 uint j;
330 uint bestOffs;
331 LONG_SAMPLETYPE bestCorr, corr;
332 uint scanCount, corrOffset, tempOffset;
334 // Slopes the amplitude of the 'midBuffer' samples
335 precalcCorrReferenceStereo();
337 bestCorr = INT_MIN;
338 bestOffs = 0;
339 corrOffset = 0;
340 tempOffset = 0;
342 // Scans for the best correlation value using four-pass hierarchical search.
344 // The look-up table 'scans' has hierarchical position adjusting steps.
345 // In first pass the routine searhes for the highest correlation with
346 // relatively coarse steps, then rescans the neighbourhood of the highest
347 // correlation with better resolution and so on.
348 for (scanCount = 0;scanCount < 4; scanCount ++)
350 j = 0;
351 while (scanOffsets[scanCount][j])
353 tempOffset = corrOffset + scanOffsets[scanCount][j];
354 if (tempOffset >= seekLength) break;
356 // Calculates correlation value for the mixing position corresponding
357 // to 'tempOffset'
358 corr = calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);
360 // Checks for the highest correlation value
361 if (corr > bestCorr)
363 bestCorr = corr;
364 bestOffs = tempOffset;
366 j ++;
368 corrOffset = bestOffs;
370 // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
371 clearCrossCorrState();
373 return bestOffs;
378 // Seeks for the optimal overlap-mixing position. The 'mono' version of the
379 // routine
381 // The best position is determined as the position where the two overlapped
382 // sample sequences are 'most alike', in terms of the highest cross-correlation
383 // value over the overlapping period
384 uint TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos)
386 uint bestOffs;
387 LONG_SAMPLETYPE bestCorr, corr;
388 uint tempOffset;
389 const SAMPLETYPE *compare;
391 // Slopes the amplitude of the 'midBuffer' samples
392 precalcCorrReferenceMono();
394 bestCorr = INT_MIN;
395 bestOffs = 0;
397 // Scans for the best correlation value by testing each possible position
398 // over the permitted range.
399 for (tempOffset = 0; tempOffset < seekLength; tempOffset ++)
401 compare = refPos + tempOffset;
403 // Calculates correlation value for the mixing position corresponding
404 // to 'tempOffset'
405 corr = calcCrossCorrMono(pRefMidBuffer, compare);
407 // Checks for the highest correlation value
408 if (corr > bestCorr)
410 bestCorr = corr;
411 bestOffs = tempOffset;
414 // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
415 clearCrossCorrState();
417 return bestOffs;
421 // Seeks for the optimal overlap-mixing position. The 'mono' version of the
422 // routine
424 // The best position is determined as the position where the two overlapped
425 // sample sequences are 'most alike', in terms of the highest cross-correlation
426 // value over the overlapping period
427 uint TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos)
429 uint j;
430 uint bestOffs;
431 LONG_SAMPLETYPE bestCorr, corr;
432 uint scanCount, corrOffset, tempOffset;
434 // Slopes the amplitude of the 'midBuffer' samples
435 precalcCorrReferenceMono();
437 bestCorr = INT_MIN;
438 bestOffs = 0;
439 corrOffset = 0;
440 tempOffset = 0;
442 // Scans for the best correlation value using four-pass hierarchical search.
444 // The look-up table 'scans' has hierarchical position adjusting steps.
445 // In first pass the routine searhes for the highest correlation with
446 // relatively coarse steps, then rescans the neighbourhood of the highest
447 // correlation with better resolution and so on.
448 for (scanCount = 0;scanCount < 4; scanCount ++)
450 j = 0;
451 while (scanOffsets[scanCount][j])
453 tempOffset = corrOffset + scanOffsets[scanCount][j];
454 if (tempOffset >= seekLength) break;
456 // Calculates correlation value for the mixing position corresponding
457 // to 'tempOffset'
458 corr = calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);
460 // Checks for the highest correlation value
461 if (corr > bestCorr)
463 bestCorr = corr;
464 bestOffs = tempOffset;
466 j ++;
468 corrOffset = bestOffs;
470 // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
471 clearCrossCorrState();
473 return bestOffs;
477 /// clear cross correlation routine state if necessary
478 void TDStretch::clearCrossCorrState()
480 // default implementation is empty.
484 // Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
485 // tempo, larger faster tempo.
486 void TDStretch::setTempo(float newTempo)
488 uint intskip;
490 tempo = newTempo;
492 // Calculate ideal skip length (according to tempo value)
493 nominalSkip = tempo * (seekWindowLength - overlapLength);
494 skipFract = 0;
495 intskip = (int)(nominalSkip + 0.5f);
497 // Calculate how many samples are needed in the 'inputBuffer' to
498 // process another batch of samples
499 sampleReq = max(intskip + overlapLength, seekWindowLength) + maxOffset;
504 // Sets the number of channels, 1 = mono, 2 = stereo
505 void TDStretch::setChannels(uint numChannels)
507 if (channels == numChannels) return;
508 assert(numChannels == 1 || numChannels == 2);
510 channels = numChannels;
511 inputBuffer.setChannels(channels);
512 outputBuffer.setChannels(channels);
516 // nominal tempo, no need for processing, just pass the samples through
517 // to outputBuffer
518 void TDStretch::processNominalTempo()
520 assert(tempo == 1.0f);
522 if (bMidBufferDirty)
524 // If there are samples in pMidBuffer waiting for overlapping,
525 // do a single sliding overlapping with them in order to prevent a
526 // clicking distortion in the output sound
527 if (inputBuffer.numSamples() < overlapLength)
529 // wait until we've got overlapLength input samples
530 return;
532 // Mix the samples in the beginning of 'inputBuffer' with the
533 // samples in 'midBuffer' using sliding overlapping
534 overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0);
535 outputBuffer.putSamples(overlapLength);
536 inputBuffer.receiveSamples(overlapLength);
537 clearMidBuffer();
538 // now we've caught the nominal sample flow and may switch to
539 // bypass mode
542 // Simply bypass samples from input to output
543 outputBuffer.moveSamples(inputBuffer);
547 // Processes as many processing frames of the samples 'inputBuffer', store
548 // the result into 'outputBuffer'
549 void TDStretch::processSamples()
551 uint ovlSkip, offset;
552 int temp;
554 if (tempo == 1.0f)
556 // tempo not changed from the original, so bypass the processing
557 processNominalTempo();
558 return;
561 if (bMidBufferDirty == FALSE)
563 // if midBuffer is empty, move the first samples of the input stream
564 // into it
565 if (inputBuffer.numSamples() < overlapLength)
567 // wait until we've got overlapLength samples
568 return;
570 memcpy(pMidBuffer, inputBuffer.ptrBegin(), channels * overlapLength * sizeof(SAMPLETYPE));
571 inputBuffer.receiveSamples(overlapLength);
572 bMidBufferDirty = TRUE;
575 // Process samples as long as there are enough samples in 'inputBuffer'
576 // to form a processing frame.
577 while (inputBuffer.numSamples() >= sampleReq)
579 // If tempo differs from the normal ('SCALE'), scan for the best overlapping
580 // position
581 offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
583 // Mix the samples in the 'inputBuffer' at position of 'offset' with the
584 // samples in 'midBuffer' using sliding overlapping
585 // ... first partially overlap with the end of the previous sequence
586 // (that's in 'midBuffer')
587 overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), offset);
588 outputBuffer.putSamples(overlapLength);
590 // ... then copy sequence samples from 'inputBuffer' to output
591 temp = (seekWindowLength - 2 * overlapLength);// & 0xfffffffe;
592 if (temp > 0)
594 outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), temp);
597 // Copies the end of the current sequence from 'inputBuffer' to
598 // 'midBuffer' for being mixed with the beginning of the next
599 // processing sequence and so on
600 assert(offset + seekWindowLength <= inputBuffer.numSamples());
601 memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + seekWindowLength - overlapLength),
602 channels * sizeof(SAMPLETYPE) * overlapLength);
603 bMidBufferDirty = TRUE;
605 // Remove the processed samples from the input buffer. Update
606 // the difference between integer & nominal skip step to 'skipFract'
607 // in order to prevent the error from accumulating over time.
608 skipFract += nominalSkip; // real skip size
609 ovlSkip = (int)skipFract; // rounded to integer skip
610 skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip
611 inputBuffer.receiveSamples(ovlSkip);
616 // Adds 'numsamples' pcs of samples from the 'samples' memory position into
617 // the input of the object.
618 void TDStretch::putSamples(const SAMPLETYPE *samples, uint numSamples)
620 // Add the samples into the input buffer
621 inputBuffer.putSamples(samples, numSamples);
622 // Process the samples in input buffer
623 processSamples();
628 /// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
629 void TDStretch::acceptNewOverlapLength(uint newOverlapLength)
631 uint prevOvl;
633 prevOvl = overlapLength;
634 overlapLength = newOverlapLength;
636 if (overlapLength > prevOvl)
638 delete[] pMidBuffer;
639 delete[] pRefMidBufferUnaligned;
641 pMidBuffer = new SAMPLETYPE[overlapLength * 2];
642 bMidBufferDirty = TRUE;
643 clearMidBuffer();
645 pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];
646 // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency
647 pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & -16);
651 TDStretch * TDStretch::newInstance()
653 uint uExtensions;
655 uExtensions = detectCPUextensions();
657 // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
659 #ifdef ALLOW_MMX
660 // MMX routines available only with integer sample types
661 if (uExtensions & SUPPORT_MMX)
663 return ::new TDStretchMMX;
665 else
666 #endif // ALLOW_MMX
669 #ifdef ALLOW_SSE
670 if (uExtensions & SUPPORT_SSE)
672 // SSE support
673 return ::new TDStretchSSE;
675 else
676 #endif // ALLOW_SSE
679 #ifdef ALLOW_3DNOW
680 if (uExtensions & SUPPORT_3DNOW)
682 // 3DNow! support
683 return ::new TDStretch3DNow;
685 else
686 #endif // ALLOW_3DNOW
689 // ISA optimizations not supported, use plain C version
690 return ::new TDStretch;
695 //////////////////////////////////////////////////////////////////////////////
697 // Integer arithmetics specific algorithm implementations.
699 //////////////////////////////////////////////////////////////////////////////
701 #ifdef INTEGER_SAMPLES
703 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
704 // is faster to calculate
705 void TDStretch::precalcCorrReferenceStereo()
707 int i, cnt2;
708 int temp, temp2;
710 for (i=0 ; i < (int)overlapLength ;i ++)
712 temp = i * (overlapLength - i);
713 cnt2 = i * 2;
715 temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
716 pRefMidBuffer[cnt2] = (short)(temp2);
717 temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
718 pRefMidBuffer[cnt2 + 1] = (short)(temp2);
723 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
724 // is faster to calculate
725 void TDStretch::precalcCorrReferenceMono()
727 int i;
728 long temp;
729 long temp2;
731 for (i=0 ; i < (int)overlapLength ;i ++)
733 temp = i * (overlapLength - i);
734 temp2 = (pMidBuffer[i] * temp) / slopingDivider;
735 pRefMidBuffer[i] = (short)temp2;
740 // Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo'
741 // version of the routine.
742 void TDStretch::overlapStereo(short *output, const short *input) const
744 int i;
745 short temp;
746 uint cnt2;
748 for (i = 0; i < (int)overlapLength ; i ++)
750 temp = (short)(overlapLength - i);
751 cnt2 = 2 * i;
752 output[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp ) / overlapLength;
753 output[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength;
758 /// Calculates overlap period length in samples.
759 /// Integer version rounds overlap length to closest power of 2
760 /// for a divide scaling operation.
761 void TDStretch::calculateOverlapLength(uint overlapMs)
763 uint newOvl;
765 overlapDividerBits = _getClosest2Power((sampleRate * overlapMs) / 1000.0);
766 if (overlapDividerBits > 9) overlapDividerBits = 9;
767 if (overlapDividerBits < 4) overlapDividerBits = 4;
768 newOvl = (uint)pow(2, overlapDividerBits);
770 acceptNewOverlapLength(newOvl);
772 // calculate sloping divider so that crosscorrelation operation won't
773 // overflow 32-bit register. Max. sum of the crosscorrelation sum without
774 // divider would be 2^30*(N^3-N)/3, where N = overlap length
775 slopingDivider = (newOvl * newOvl - 1) / 3;
779 long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
781 long corr;
782 uint i;
784 corr = 0;
785 for (i = 1; i < overlapLength; i ++)
787 corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
790 return corr;
794 long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
796 long corr;
797 uint i;
799 corr = 0;
800 for (i = 2; i < 2 * overlapLength; i += 2)
802 corr += (mixingPos[i] * compare[i] +
803 mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;
806 return corr;
809 #endif // INTEGER_SAMPLES
811 //////////////////////////////////////////////////////////////////////////////
813 // Floating point arithmetics specific algorithm implementations.
816 #ifdef FLOAT_SAMPLES
819 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
820 // is faster to calculate
821 void TDStretch::precalcCorrReferenceStereo()
823 int i, cnt2;
824 float temp;
826 for (i=0 ; i < (int)overlapLength ;i ++)
828 temp = (float)i * (float)(overlapLength - i);
829 cnt2 = i * 2;
830 pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);
831 pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);
836 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
837 // is faster to calculate
838 void TDStretch::precalcCorrReferenceMono()
840 int i;
841 float temp;
843 for (i=0 ; i < (int)overlapLength ;i ++)
845 temp = (float)i * (float)(overlapLength - i);
846 pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
851 // SSE-optimized version of the function overlapStereo
852 void TDStretch::overlapStereo(float *output, const float *input) const
854 int i;
855 uint cnt2;
856 float fTemp;
857 float fScale;
858 float fi;
860 fScale = 1.0f / (float)overlapLength;
862 for (i = 0; i < (int)overlapLength ; i ++)
864 fTemp = (float)(overlapLength - i) * fScale;
865 fi = (float)i * fScale;
866 cnt2 = 2 * i;
867 output[cnt2 + 0] = input[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;
868 output[cnt2 + 1] = input[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;
873 /// Calculates overlap period length in samples.
874 void TDStretch::calculateOverlapLength(uint overlapMs)
876 uint newOvl;
878 newOvl = (sampleRate * overlapMs) / 1000;
879 if (newOvl < 16) newOvl = 16;
881 acceptNewOverlapLength(newOvl);
886 double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
888 double corr;
889 uint i;
891 corr = 0;
892 for (i = 1; i < overlapLength; i ++)
894 corr += mixingPos[i] * compare[i];
897 return corr;
901 double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
903 double corr;
904 uint i;
906 corr = 0;
907 for (i = 2; i < 2 * overlapLength; i += 2)
909 corr += mixingPos[i] * compare[i] +
910 mixingPos[i + 1] * compare[i + 1];
913 return corr;
916 #endif // FLOAT_SAMPLES