1
////////////////////////////////////////////////////////////////////////////////
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.
7
/// Note : MMX optimized functions reside in a separate, platform-specific
8
/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
10
/// Author : Copyright (c) Olli Parviainen
11
/// Author e-mail : oparviai 'at' iki.fi
12
/// SoundTouch WWW: http://www.surina.net/soundtouch
14
////////////////////////////////////////////////////////////////////////////////
16
// Last changed : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $
17
// File revision : $Revision: 1.12 $
19
// $Id: TDStretch.cpp 104 2011-02-13 19:13:57Z oparviai $
21
////////////////////////////////////////////////////////////////////////////////
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
////////////////////////////////////////////////////////////////////////////////
52
#include "cpu_detect.h"
53
#include "TDStretch.h"
57
using namespace soundtouch;
59
#define max(x, y) (((x) > (y)) ? (x) : (y))
62
/*****************************************************************************
64
* Constant definitions
66
*****************************************************************************/
68
// Table for the hierarchical mixing position seeking algorithm
69
static const short _scanOffsets[5][24]={
70
{ 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806,
71
868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0},
72
{-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0,
73
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
74
{ -20, -15, -10, -5, 5, 10, 15, 20, 0, 0, 0, 0,
75
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
76
{ -4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0,
77
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
78
{ 121, 114, 97, 114, 98, 105, 108, 32, 104, 99, 117, 111,
79
116, 100, 110, 117, 111, 115, 0, 0, 0, 0, 0, 0}};
81
/*****************************************************************************
83
* Implementation of the class 'TDStretch'
85
*****************************************************************************/
88
TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
94
pRefMidBufferUnaligned = NULL;
97
bAutoSeqSetting = TRUE;
98
bAutoSeekSetting = TRUE;
104
setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
112
TDStretch::~TDStretch()
115
delete[] pRefMidBufferUnaligned;
120
// Sets routine control parameters. These control are certain time constants
121
// defining how the sound is stretched to the desired duration.
123
// 'sampleRate' = sample rate of the sound
124
// 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)
125
// 'seekwindowMS' = seeking window length for scanning the best overlapping
126
// position (default = 28 ms)
127
// 'overlapMS' = overlapping length (default = 12 ms)
129
void TDStretch::setParameters(int aSampleRate, int aSequenceMS,
130
int aSeekWindowMS, int aOverlapMS)
132
// accept only positive parameter values - if zero or negative, use old values instead
133
if (aSampleRate > 0) this->sampleRate = aSampleRate;
134
if (aOverlapMS > 0) this->overlapMs = aOverlapMS;
138
this->sequenceMs = aSequenceMS;
139
bAutoSeqSetting = FALSE;
141
else if (aSequenceMS == 0)
143
// if zero, use automatic setting
144
bAutoSeqSetting = TRUE;
147
if (aSeekWindowMS > 0)
149
this->seekWindowMs = aSeekWindowMS;
150
bAutoSeekSetting = FALSE;
152
else if (aSeekWindowMS == 0)
154
// if zero, use automatic setting
155
bAutoSeekSetting = TRUE;
160
calculateOverlapLength(overlapMs);
162
// set tempo to recalculate 'sampleReq'
169
/// Get routine control parameters, see setParameters() function.
170
/// Any of the parameters to this function can be NULL, in such case corresponding parameter
171
/// value isn't returned.
172
void TDStretch::getParameters(int *pSampleRate, int *pSequenceMs, int *pSeekWindowMs, int *pOverlapMs) const
176
*pSampleRate = sampleRate;
181
*pSequenceMs = (bAutoSeqSetting) ? (USE_AUTO_SEQUENCE_LEN) : sequenceMs;
186
*pSeekWindowMs = (bAutoSeekSetting) ? (USE_AUTO_SEEKWINDOW_LEN) : seekWindowMs;
191
*pOverlapMs = overlapMs;
196
// Overlaps samples in 'midBuffer' with the samples in 'pInput'
197
void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const
201
for (i = 0; i < overlapLength ; i ++)
203
itemp = overlapLength - i;
204
pOutput[i] = (pInput[i] * i + pMidBuffer[i] * itemp ) / overlapLength; // >> overlapDividerBits;
210
void TDStretch::clearMidBuffer()
212
memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
216
void TDStretch::clearInput()
223
// Clears the sample buffers
224
void TDStretch::clear()
226
outputBuffer.clear();
232
// Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
234
void TDStretch::enableQuickSeek(BOOL enable)
240
// Returns nonzero if the quick seeking algorithm is enabled.
241
BOOL TDStretch::isQuickSeekEnabled() const
247
// Seeks for the optimal overlap-mixing position.
248
int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
255
return seekBestOverlapPositionStereoQuick(refPos);
259
return seekBestOverlapPositionStereo(refPos);
267
return seekBestOverlapPositionMonoQuick(refPos);
271
return seekBestOverlapPositionMono(refPos);
279
// Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position
281
inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint ovlPos) const
286
overlapStereo(pOutput, pInput + 2 * ovlPos);
289
overlapMono(pOutput, pInput + ovlPos);
296
// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
299
// The best position is determined as the position where the two overlapped
300
// sample sequences are 'most alike', in terms of the highest cross-correlation
301
// value over the overlapping period
302
int TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos)
305
double bestCorr, corr;
308
// Slopes the amplitudes of the 'midBuffer' samples
309
precalcCorrReferenceStereo();
314
// Scans for the best correlation value by testing each possible position
315
// over the permitted range.
316
for (i = 0; i < seekLength; i ++)
318
// Calculates correlation value for the mixing position corresponding
320
corr = (double)calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);
321
// heuristic rule to slightly favour values close to mid of the range
322
double tmp = (double)(2 * i - seekLength) / (double)seekLength;
323
corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
325
// Checks for the highest correlation value
332
// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
333
clearCrossCorrState();
339
// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
342
// The best position is determined as the position where the two overlapped
343
// sample sequences are 'most alike', in terms of the highest cross-correlation
344
// value over the overlapping period
345
int TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos)
349
double bestCorr, corr;
350
int scanCount, corrOffset, tempOffset;
352
// Slopes the amplitude of the 'midBuffer' samples
353
precalcCorrReferenceStereo();
356
bestOffs = _scanOffsets[0][0];
360
// Scans for the best correlation value using four-pass hierarchical search.
362
// The look-up table 'scans' has hierarchical position adjusting steps.
363
// In first pass the routine searhes for the highest correlation with
364
// relatively coarse steps, then rescans the neighbourhood of the highest
365
// correlation with better resolution and so on.
366
for (scanCount = 0;scanCount < 4; scanCount ++)
369
while (_scanOffsets[scanCount][j])
371
tempOffset = corrOffset + _scanOffsets[scanCount][j];
372
if (tempOffset >= seekLength) break;
374
// Calculates correlation value for the mixing position corresponding
376
corr = (double)calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);
377
// heuristic rule to slightly favour values close to mid of the range
378
double tmp = (double)(2 * tempOffset - seekLength) / seekLength;
379
corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
381
// Checks for the highest correlation value
385
bestOffs = tempOffset;
389
corrOffset = bestOffs;
391
// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
392
clearCrossCorrState();
399
// Seeks for the optimal overlap-mixing position. The 'mono' version of the
402
// The best position is determined as the position where the two overlapped
403
// sample sequences are 'most alike', in terms of the highest cross-correlation
404
// value over the overlapping period
405
int TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos)
408
double bestCorr, corr;
410
const SAMPLETYPE *compare;
412
// Slopes the amplitude of the 'midBuffer' samples
413
precalcCorrReferenceMono();
418
// Scans for the best correlation value by testing each possible position
419
// over the permitted range.
420
for (tempOffset = 0; tempOffset < seekLength; tempOffset ++)
422
compare = refPos + tempOffset;
424
// Calculates correlation value for the mixing position corresponding
426
corr = (double)calcCrossCorrMono(pRefMidBuffer, compare);
427
// heuristic rule to slightly favour values close to mid of the range
428
double tmp = (double)(2 * tempOffset - seekLength) / seekLength;
429
corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
431
// Checks for the highest correlation value
435
bestOffs = tempOffset;
438
// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
439
clearCrossCorrState();
445
// Seeks for the optimal overlap-mixing position. The 'mono' version of the
448
// The best position is determined as the position where the two overlapped
449
// sample sequences are 'most alike', in terms of the highest cross-correlation
450
// value over the overlapping period
451
int TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos)
455
double bestCorr, corr;
456
int scanCount, corrOffset, tempOffset;
458
// Slopes the amplitude of the 'midBuffer' samples
459
precalcCorrReferenceMono();
462
bestOffs = _scanOffsets[0][0];
466
// Scans for the best correlation value using four-pass hierarchical search.
468
// The look-up table 'scans' has hierarchical position adjusting steps.
469
// In first pass the routine searhes for the highest correlation with
470
// relatively coarse steps, then rescans the neighbourhood of the highest
471
// correlation with better resolution and so on.
472
for (scanCount = 0;scanCount < 4; scanCount ++)
475
while (_scanOffsets[scanCount][j])
477
tempOffset = corrOffset + _scanOffsets[scanCount][j];
478
if (tempOffset >= seekLength) break;
480
// Calculates correlation value for the mixing position corresponding
482
corr = (double)calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);
483
// heuristic rule to slightly favour values close to mid of the range
484
double tmp = (double)(2 * tempOffset - seekLength) / seekLength;
485
corr = ((corr + 0.1) * (1.0 - 0.25 * tmp * tmp));
487
// Checks for the highest correlation value
491
bestOffs = tempOffset;
495
corrOffset = bestOffs;
497
// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
498
clearCrossCorrState();
504
/// clear cross correlation routine state if necessary
505
void TDStretch::clearCrossCorrState()
507
// default implementation is empty.
511
/// Calculates processing sequence length according to tempo setting
512
void TDStretch::calcSeqParameters()
514
// Adjust tempo param according to tempo, so that variating processing sequence length is used
515
// at varius tempo settings, between the given low...top limits
516
#define AUTOSEQ_TEMPO_LOW 0.5 // auto setting low tempo range (-50%)
517
#define AUTOSEQ_TEMPO_TOP 2.0 // auto setting top tempo range (+100%)
519
// sequence-ms setting values at above low & top tempo
520
#define AUTOSEQ_AT_MIN 125.0
521
#define AUTOSEQ_AT_MAX 50.0
522
#define AUTOSEQ_K ((AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
523
#define AUTOSEQ_C (AUTOSEQ_AT_MIN - (AUTOSEQ_K) * (AUTOSEQ_TEMPO_LOW))
525
// seek-window-ms setting values at above low & top tempo
526
#define AUTOSEEK_AT_MIN 25.0
527
#define AUTOSEEK_AT_MAX 15.0
528
#define AUTOSEEK_K ((AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW))
529
#define AUTOSEEK_C (AUTOSEEK_AT_MIN - (AUTOSEEK_K) * (AUTOSEQ_TEMPO_LOW))
531
#define CHECK_LIMITS(x, mi, ma) (((x) < (mi)) ? (mi) : (((x) > (ma)) ? (ma) : (x)))
537
seq = AUTOSEQ_C + AUTOSEQ_K * tempo;
538
seq = CHECK_LIMITS(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN);
539
sequenceMs = (int)(seq + 0.5);
542
if (bAutoSeekSetting)
544
seek = AUTOSEEK_C + AUTOSEEK_K * tempo;
545
seek = CHECK_LIMITS(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN);
546
seekWindowMs = (int)(seek + 0.5);
549
// Update seek window lengths
550
seekWindowLength = (sampleRate * sequenceMs) / 1000;
551
if (seekWindowLength < 2 * overlapLength)
553
seekWindowLength = 2 * overlapLength;
555
seekLength = (sampleRate * seekWindowMs) / 1000;
560
// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
561
// tempo, larger faster tempo.
562
void TDStretch::setTempo(float newTempo)
568
// Calculate new sequence duration
571
// Calculate ideal skip length (according to tempo value)
572
nominalSkip = tempo * (seekWindowLength - overlapLength);
573
intskip = (int)(nominalSkip + 0.5f);
575
// Calculate how many samples are needed in the 'inputBuffer' to
576
// process another batch of samples
577
//sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength / 2;
578
sampleReq = max(intskip + overlapLength, seekWindowLength) + seekLength;
583
// Sets the number of channels, 1 = mono, 2 = stereo
584
void TDStretch::setChannels(int numChannels)
586
assert(numChannels > 0);
587
if (channels == numChannels) return;
588
assert(numChannels == 1 || numChannels == 2);
590
channels = numChannels;
591
inputBuffer.setChannels(channels);
592
outputBuffer.setChannels(channels);
596
// nominal tempo, no need for processing, just pass the samples through
599
void TDStretch::processNominalTempo()
601
assert(tempo == 1.0f);
605
// If there are samples in pMidBuffer waiting for overlapping,
606
// do a single sliding overlapping with them in order to prevent a
607
// clicking distortion in the output sound
608
if (inputBuffer.numSamples() < overlapLength)
610
// wait until we've got overlapLength input samples
613
// Mix the samples in the beginning of 'inputBuffer' with the
614
// samples in 'midBuffer' using sliding overlapping
615
overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0);
616
outputBuffer.putSamples(overlapLength);
617
inputBuffer.receiveSamples(overlapLength);
619
// now we've caught the nominal sample flow and may switch to
623
// Simply bypass samples from input to output
624
outputBuffer.moveSamples(inputBuffer);
630
// Processes as many processing frames of the samples 'inputBuffer', store
631
// the result into 'outputBuffer'
632
void TDStretch::processSamples()
637
/* Removed this small optimization - can introduce a click to sound when tempo setting
638
crosses the nominal value
641
// tempo not changed from the original, so bypass the processing
642
processNominalTempo();
647
// Process samples as long as there are enough samples in 'inputBuffer'
648
// to form a processing frame.
649
while ((int)inputBuffer.numSamples() >= sampleReq)
651
// If tempo differs from the normal ('SCALE'), scan for the best overlapping
653
offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
655
// Mix the samples in the 'inputBuffer' at position of 'offset' with the
656
// samples in 'midBuffer' using sliding overlapping
657
// ... first partially overlap with the end of the previous sequence
658
// (that's in 'midBuffer')
659
overlap(outputBuffer.ptrEnd((uint)overlapLength), inputBuffer.ptrBegin(), (uint)offset);
660
outputBuffer.putSamples((uint)overlapLength);
662
// ... then copy sequence samples from 'inputBuffer' to output:
664
// length of sequence
665
temp = (seekWindowLength - 2 * overlapLength);
667
// crosscheck that we don't have buffer overflow...
668
if ((int)inputBuffer.numSamples() < (offset + temp + overlapLength * 2))
670
continue; // just in case, shouldn't really happen
673
outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp);
675
// Copies the end of the current sequence from 'inputBuffer' to
676
// 'midBuffer' for being mixed with the beginning of the next
677
// processing sequence and so on
678
assert((offset + temp + overlapLength * 2) <= (int)inputBuffer.numSamples());
679
memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + temp + overlapLength),
680
channels * sizeof(SAMPLETYPE) * overlapLength);
682
// Remove the processed samples from the input buffer. Update
683
// the difference between integer & nominal skip step to 'skipFract'
684
// in order to prevent the error from accumulating over time.
685
skipFract += nominalSkip; // real skip size
686
ovlSkip = (int)skipFract; // rounded to integer skip
687
skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip
688
inputBuffer.receiveSamples((uint)ovlSkip);
693
// Adds 'numsamples' pcs of samples from the 'samples' memory position into
694
// the input of the object.
695
void TDStretch::putSamples(const SAMPLETYPE *samples, uint nSamples)
697
// Add the samples into the input buffer
698
inputBuffer.putSamples(samples, nSamples);
699
// Process the samples in input buffer
705
/// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
706
void TDStretch::acceptNewOverlapLength(int newOverlapLength)
710
assert(newOverlapLength >= 0);
711
prevOvl = overlapLength;
712
overlapLength = newOverlapLength;
714
if (overlapLength > prevOvl)
717
delete[] pRefMidBufferUnaligned;
719
pMidBuffer = new SAMPLETYPE[overlapLength * 2];
722
pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];
723
// ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency
724
pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & (ulong)-16);
729
// Operator 'new' is overloaded so that it automatically creates a suitable instance
730
// depending on if we've a MMX/SSE/etc-capable CPU available or not.
731
void * TDStretch::operator new(size_t s)
733
// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
734
throw std::runtime_error("Error in TDStretch::new: Don't use 'new TDStretch' directly, use 'newInstance' member instead!");
739
TDStretch * TDStretch::newInstance()
743
uExtensions = detectCPUextensions();
745
// Check if MMX/SSE instruction set extensions supported by CPU
747
#ifdef SOUNDTOUCH_ALLOW_MMX
748
// MMX routines available only with integer sample types
749
if (uExtensions & SUPPORT_MMX)
751
return ::new TDStretchMMX;
754
#endif // SOUNDTOUCH_ALLOW_MMX
757
#ifdef SOUNDTOUCH_ALLOW_SSE
758
if (uExtensions & SUPPORT_SSE)
761
return ::new TDStretchSSE;
764
#endif // SOUNDTOUCH_ALLOW_SSE
767
// ISA optimizations not supported, use plain C version
768
return ::new TDStretch;
773
//////////////////////////////////////////////////////////////////////////////
775
// Integer arithmetics specific algorithm implementations.
777
//////////////////////////////////////////////////////////////////////////////
779
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
781
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
782
// is faster to calculate
783
void TDStretch::precalcCorrReferenceStereo()
788
for (i=0 ; i < (int)overlapLength ;i ++)
790
temp = i * (overlapLength - i);
793
temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
794
pRefMidBuffer[cnt2] = (short)(temp2);
795
temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
796
pRefMidBuffer[cnt2 + 1] = (short)(temp2);
801
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
802
// is faster to calculate
803
void TDStretch::precalcCorrReferenceMono()
809
for (i=0 ; i < (int)overlapLength ;i ++)
811
temp = i * (overlapLength - i);
812
temp2 = (pMidBuffer[i] * temp) / slopingDivider;
813
pRefMidBuffer[i] = (short)temp2;
818
// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo'
819
// version of the routine.
820
void TDStretch::overlapStereo(short *poutput, const short *input) const
826
for (i = 0; i < overlapLength ; i ++)
828
temp = (short)(overlapLength - i);
830
poutput[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp ) / overlapLength;
831
poutput[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength;
835
// Calculates the x having the closest 2^x value for the given value
836
static int _getClosest2Power(double value)
838
return (int)(log(value) / log(2.0) + 0.5);
842
/// Calculates overlap period length in samples.
843
/// Integer version rounds overlap length to closest power of 2
844
/// for a divide scaling operation.
845
void TDStretch::calculateOverlapLength(int aoverlapMs)
849
assert(aoverlapMs >= 0);
851
// calculate overlap length so that it's power of 2 - thus it's easy to do
852
// integer division by right-shifting. Term "-1" at end is to account for
853
// the extra most significatnt bit left unused in result by signed multiplication
854
overlapDividerBits = _getClosest2Power((sampleRate * aoverlapMs) / 1000.0) - 1;
855
if (overlapDividerBits > 9) overlapDividerBits = 9;
856
if (overlapDividerBits < 3) overlapDividerBits = 3;
857
newOvl = (int)pow(2.0, (int)overlapDividerBits + 1); // +1 => account for -1 above
859
acceptNewOverlapLength(newOvl);
861
// calculate sloping divider so that crosscorrelation operation won't
862
// overflow 32-bit register. Max. sum of the crosscorrelation sum without
863
// divider would be 2^30*(N^3-N)/3, where N = overlap length
864
slopingDivider = (newOvl * newOvl - 1) / 3;
868
long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
875
for (i = 1; i < overlapLength; i ++)
877
corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
878
norm += (mixingPos[i] * mixingPos[i]) >> overlapDividerBits;
881
// Normalize result by dividing by sqrt(norm) - this step is easiest
882
// done using floating point operation
883
if (norm == 0) norm = 1; // to avoid div by zero
884
return (long)((double)corr * SHRT_MAX / sqrt((double)norm));
888
long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
895
for (i = 2; i < 2 * overlapLength; i += 2)
897
corr += (mixingPos[i] * compare[i] +
898
mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;
899
norm += (mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1]) >> overlapDividerBits;
902
// Normalize result by dividing by sqrt(norm) - this step is easiest
903
// done using floating point operation
904
if (norm == 0) norm = 1; // to avoid div by zero
905
return (long)((double)corr * SHRT_MAX / sqrt((double)norm));
908
#endif // SOUNDTOUCH_INTEGER_SAMPLES
910
//////////////////////////////////////////////////////////////////////////////
912
// Floating point arithmetics specific algorithm implementations.
915
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
918
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
919
// is faster to calculate
920
void TDStretch::precalcCorrReferenceStereo()
925
for (i=0 ; i < (int)overlapLength ;i ++)
927
temp = (float)i * (float)(overlapLength - i);
929
pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);
930
pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);
935
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
936
// is faster to calculate
937
void TDStretch::precalcCorrReferenceMono()
942
for (i=0 ; i < (int)overlapLength ;i ++)
944
temp = (float)i * (float)(overlapLength - i);
945
pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
950
// Overlaps samples in 'midBuffer' with the samples in 'pInput'
951
void TDStretch::overlapStereo(float *pOutput, const float *pInput) const
959
fScale = 1.0f / (float)overlapLength;
961
for (i = 0; i < (int)overlapLength ; i ++)
963
fTemp = (float)(overlapLength - i) * fScale;
964
fi = (float)i * fScale;
966
pOutput[cnt2 + 0] = pInput[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;
967
pOutput[cnt2 + 1] = pInput[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;
972
/// Calculates overlapInMsec period length in samples.
973
void TDStretch::calculateOverlapLength(int overlapInMsec)
977
assert(overlapInMsec >= 0);
978
newOvl = (sampleRate * overlapInMsec) / 1000;
979
if (newOvl < 16) newOvl = 16;
981
// must be divisible by 8
982
newOvl -= newOvl % 8;
984
acceptNewOverlapLength(newOvl);
989
double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
996
for (i = 1; i < overlapLength; i ++)
998
corr += mixingPos[i] * compare[i];
999
norm += mixingPos[i] * mixingPos[i];
1002
if (norm < 1e-9) norm = 1.0; // to avoid div by zero
1003
return corr / sqrt(norm);
1007
double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
1014
for (i = 2; i < 2 * overlapLength; i += 2)
1016
corr += mixingPos[i] * compare[i] +
1017
mixingPos[i + 1] * compare[i + 1];
1018
norm += mixingPos[i] * mixingPos[i] +
1019
mixingPos[i + 1] * mixingPos[i + 1];
1022
if (norm < 1e-9) norm = 1.0; // to avoid div by zero
1023
return corr / sqrt(norm);
1026
#endif // SOUNDTOUCH_FLOAT_SAMPLES