Merged revisions 6293,6296-6306,6308 via svnmerge from
[ardour.git] / libs / soundtouch / TDStretch.cpp
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 ////////////////////////////////////////////////////////////////////////////////
15 //
16 // Last changed  : $Date$
17 // File revision : $Revision$
18 //
19 // $Id$
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
44 #include <cstring>
45 #include <cstdlib>
46 #include <memory.h>
47 #include <climits>
48 #include <cmath>
49 #include <cassert>
50
51 #include "STTypes.h"
52 #include "cpu_detect.h"
53 #include "TDStretch.h"
54
55 using namespace soundtouch;
56
57 #ifndef min
58 #define min(a,b) ((a > b) ? b : a)
59 #define max(a,b) ((a < b) ? b : a)
60 #endif
61
62
63
64 /*****************************************************************************
65  *
66  * Constant definitions
67  *
68  *****************************************************************************/
69
70
71 #define MAX_SCAN_DELTA      124
72
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}};
83
84 /*****************************************************************************
85  *
86  * Implementation of the class 'TDStretch'
87  *
88  *****************************************************************************/
89
90
91 TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
92 {
93     bQuickseek = FALSE;
94     channels = 2;
95     bMidBufferDirty = FALSE;
96
97     pMidBuffer = NULL;
98     pRefMidBufferUnaligned = NULL;
99     overlapLength = 0;
100
101     setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
102
103     setTempo(1.0f);
104 }
105
106
107
108
109 TDStretch::~TDStretch()
110 {
111     delete[] pMidBuffer;
112     delete[] pRefMidBufferUnaligned;
113 }
114
115
116     
117
118 // Sets routine control parameters. These control are certain time constants
119 // defining how the sound is stretched to the desired duration.
120 //
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)
126
127 void TDStretch::setParameters(uint aSampleRate, uint aSequenceMS, 
128                               uint aSeekWindowMS, uint aOverlapMS)
129 {
130     this->sampleRate = aSampleRate;
131     this->sequenceMs = aSequenceMS;
132     this->seekWindowMs = aSeekWindowMS;
133     this->overlapMs = aOverlapMS;
134
135     seekLength = (sampleRate * seekWindowMs) / 1000;
136     seekWindowLength = (sampleRate * sequenceMs) / 1000;
137
138     maxOffset = seekLength;
139
140     calculateOverlapLength(overlapMs);
141
142     // set tempo to recalculate 'sampleReq'
143     setTempo(tempo);
144
145 }
146
147
148
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)
153 {
154     if (pSampleRate)
155     {
156         *pSampleRate = sampleRate;
157     }
158
159     if (pSequenceMs)
160     {
161         *pSequenceMs = sequenceMs;
162     }
163
164     if (pSeekWindowMs)
165     {
166         *pSeekWindowMs = seekWindowMs;
167     }
168
169     if (pOverlapMs)
170     {
171         *pOverlapMs = overlapMs;
172     }
173 }
174
175
176 // Overlaps samples in 'midBuffer' with the samples in 'input'
177 void TDStretch::overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const
178 {
179     int i, itemp;
180
181     for (i = 0; i < (int)overlapLength ; i ++) 
182     {
183         itemp = overlapLength - i;
184         output[i] = (input[i] * i + pMidBuffer[i] * itemp ) / overlapLength;    // >> overlapDividerBits;
185     }
186 }
187
188
189
190 void TDStretch::clearMidBuffer()
191 {
192     if (bMidBufferDirty) 
193     {
194         memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
195         bMidBufferDirty = FALSE;
196     }
197 }
198
199
200 void TDStretch::clearInput()
201 {
202     inputBuffer.clear();
203     clearMidBuffer();
204 }
205
206
207 // Clears the sample buffers
208 void TDStretch::clear()
209 {
210     outputBuffer.clear();
211     inputBuffer.clear();
212     clearMidBuffer();
213 }
214
215
216
217 // Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
218 // to enable
219 void TDStretch::enableQuickSeek(BOOL enable)
220 {
221     bQuickseek = enable;
222 }
223
224
225 // Returns nonzero if the quick seeking algorithm is enabled.
226 BOOL TDStretch::isQuickSeekEnabled() const
227 {
228     return bQuickseek;
229 }
230
231
232 // Seeks for the optimal overlap-mixing position.
233 uint TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
234 {
235     if (channels == 2) 
236     {
237         // stereo sound
238         if (bQuickseek) 
239         {
240             return seekBestOverlapPositionStereoQuick(refPos);
241         } 
242         else 
243         {
244             return seekBestOverlapPositionStereo(refPos);
245         }
246     } 
247     else 
248     {
249         // mono sound
250         if (bQuickseek) 
251         {
252             return seekBestOverlapPositionMonoQuick(refPos);
253         } 
254         else 
255         {
256             return seekBestOverlapPositionMono(refPos);
257         }
258     }
259 }
260
261
262
263
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
267 {
268     if (channels == 2) 
269     {
270         // stereo sound
271         overlapStereo(output, input + 2 * ovlPos);
272     } else {
273         // mono sound.
274         overlapMono(output, input + ovlPos);
275     }
276 }
277
278
279
280
281 // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
282 // routine
283 //
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) 
288 {
289     uint bestOffs;
290     LONG_SAMPLETYPE bestCorr, corr;
291     uint i;
292
293     // Slopes the amplitudes of the 'midBuffer' samples
294     precalcCorrReferenceStereo();
295
296     bestCorr = INT_MIN;
297     bestOffs = 0;
298
299     // Scans for the best correlation value by testing each possible position
300     // over the permitted range.
301     for (i = 0; i < seekLength; i ++) 
302     {
303         // Calculates correlation value for the mixing position corresponding
304         // to 'i'
305         corr = calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);
306
307         // Checks for the highest correlation value
308         if (corr > bestCorr) 
309         {
310             bestCorr = corr;
311             bestOffs = i;
312         }
313     }
314     // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
315     clearCrossCorrState();
316
317     return bestOffs;
318 }
319
320
321 // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
322 // routine
323 //
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) 
328 {
329     uint j;
330     uint bestOffs;
331     LONG_SAMPLETYPE bestCorr, corr;
332     uint scanCount, corrOffset, tempOffset;
333
334     // Slopes the amplitude of the 'midBuffer' samples
335     precalcCorrReferenceStereo();
336
337     bestCorr = INT_MIN;
338     bestOffs = 0;
339     corrOffset = 0;
340     tempOffset = 0;
341
342     // Scans for the best correlation value using four-pass hierarchical search.
343     //
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 ++) 
349     {
350         j = 0;
351         while (scanOffsets[scanCount][j]) 
352         {
353             tempOffset = corrOffset + scanOffsets[scanCount][j];
354             if (tempOffset >= seekLength) break;
355
356             // Calculates correlation value for the mixing position corresponding
357             // to 'tempOffset'
358             corr = calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);
359
360             // Checks for the highest correlation value
361             if (corr > bestCorr) 
362             {
363                 bestCorr = corr;
364                 bestOffs = tempOffset;
365             }
366             j ++;
367         }
368         corrOffset = bestOffs;
369     }
370     // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
371     clearCrossCorrState();
372
373     return bestOffs;
374 }
375
376
377
378 // Seeks for the optimal overlap-mixing position. The 'mono' version of the
379 // routine
380 //
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) 
385 {
386     uint bestOffs;
387     LONG_SAMPLETYPE bestCorr, corr;
388     uint tempOffset;
389     const SAMPLETYPE *compare;
390
391     // Slopes the amplitude of the 'midBuffer' samples
392     precalcCorrReferenceMono();
393
394     bestCorr = INT_MIN;
395     bestOffs = 0;
396
397     // Scans for the best correlation value by testing each possible position
398     // over the permitted range.
399     for (tempOffset = 0; tempOffset < seekLength; tempOffset ++) 
400     {
401         compare = refPos + tempOffset;
402
403         // Calculates correlation value for the mixing position corresponding
404         // to 'tempOffset'
405         corr = calcCrossCorrMono(pRefMidBuffer, compare);
406
407         // Checks for the highest correlation value
408         if (corr > bestCorr) 
409         {
410             bestCorr = corr;
411             bestOffs = tempOffset;
412         }
413     }
414     // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
415     clearCrossCorrState();
416
417     return bestOffs;
418 }
419
420
421 // Seeks for the optimal overlap-mixing position. The 'mono' version of the
422 // routine
423 //
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) 
428 {
429     uint j;
430     uint bestOffs;
431     LONG_SAMPLETYPE bestCorr, corr;
432     uint scanCount, corrOffset, tempOffset;
433
434     // Slopes the amplitude of the 'midBuffer' samples
435     precalcCorrReferenceMono();
436
437     bestCorr = INT_MIN;
438     bestOffs = 0;
439     corrOffset = 0;
440     tempOffset = 0;
441
442     // Scans for the best correlation value using four-pass hierarchical search.
443     //
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 ++) 
449     {
450         j = 0;
451         while (scanOffsets[scanCount][j]) 
452         {
453             tempOffset = corrOffset + scanOffsets[scanCount][j];
454             if (tempOffset >= seekLength) break;
455
456             // Calculates correlation value for the mixing position corresponding
457             // to 'tempOffset'
458             corr = calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);
459
460             // Checks for the highest correlation value
461             if (corr > bestCorr) 
462             {
463                 bestCorr = corr;
464                 bestOffs = tempOffset;
465             }
466             j ++;
467         }
468         corrOffset = bestOffs;
469     }
470     // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
471     clearCrossCorrState();
472
473     return bestOffs;
474 }
475
476
477 /// clear cross correlation routine state if necessary 
478 void TDStretch::clearCrossCorrState()
479 {
480     // default implementation is empty.
481 }
482
483
484 // Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower 
485 // tempo, larger faster tempo.
486 void TDStretch::setTempo(float newTempo)
487 {
488     uint intskip;
489
490     tempo = newTempo;
491
492     // Calculate ideal skip length (according to tempo value) 
493     nominalSkip = tempo * (seekWindowLength - overlapLength);
494     skipFract = 0;
495     intskip = (int)(nominalSkip + 0.5f);
496
497     // Calculate how many samples are needed in the 'inputBuffer' to 
498     // process another batch of samples
499     sampleReq = max(intskip + overlapLength, seekWindowLength) + maxOffset;
500 }
501
502
503
504 // Sets the number of channels, 1 = mono, 2 = stereo
505 void TDStretch::setChannels(uint numChannels)
506 {
507     if (channels == numChannels) return;
508     assert(numChannels == 1 || numChannels == 2);
509
510     channels = numChannels;
511     inputBuffer.setChannels(channels);
512     outputBuffer.setChannels(channels);
513 }
514
515
516 // nominal tempo, no need for processing, just pass the samples through
517 // to outputBuffer
518 void TDStretch::processNominalTempo()
519 {
520     assert(tempo == 1.0f);
521
522     if (bMidBufferDirty) 
523     {
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) 
528         {
529             // wait until we've got overlapLength input samples
530             return;
531         }
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
540     }
541
542     // Simply bypass samples from input to output
543     outputBuffer.moveSamples(inputBuffer);
544 }
545
546
547 // Processes as many processing frames of the samples 'inputBuffer', store
548 // the result into 'outputBuffer'
549 void TDStretch::processSamples()
550 {
551     uint ovlSkip, offset;
552     int temp;
553
554     if (tempo == 1.0f) 
555     {
556         // tempo not changed from the original, so bypass the processing
557         processNominalTempo();
558         return;
559     }
560
561     if (bMidBufferDirty == FALSE) 
562     {
563         // if midBuffer is empty, move the first samples of the input stream 
564         // into it
565         if (inputBuffer.numSamples() < overlapLength) 
566         {
567             // wait until we've got overlapLength samples
568             return;
569         }
570         memcpy(pMidBuffer, inputBuffer.ptrBegin(), channels * overlapLength * sizeof(SAMPLETYPE));
571         inputBuffer.receiveSamples(overlapLength);
572         bMidBufferDirty = TRUE;
573     }
574
575     // Process samples as long as there are enough samples in 'inputBuffer'
576     // to form a processing frame.
577     while (inputBuffer.numSamples() >= sampleReq) 
578     {
579         // If tempo differs from the normal ('SCALE'), scan for the best overlapping
580         // position
581         offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
582
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);
589
590         // ... then copy sequence samples from 'inputBuffer' to output
591         temp = (seekWindowLength - 2 * overlapLength);// & 0xfffffffe;
592         if (temp > 0)
593         {
594             outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), temp);
595         }
596
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;
604
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);
612     }
613 }
614
615
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)
619 {
620     // Add the samples into the input buffer
621     inputBuffer.putSamples(samples, numSamples);
622     // Process the samples in input buffer
623     processSamples();
624 }
625
626
627
628 /// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
629 void TDStretch::acceptNewOverlapLength(uint newOverlapLength)
630 {
631     uint prevOvl;
632
633     prevOvl = overlapLength;
634     overlapLength = newOverlapLength;
635
636     if (overlapLength > prevOvl)
637     {
638         delete[] pMidBuffer;
639         delete[] pRefMidBufferUnaligned;
640
641         pMidBuffer = new SAMPLETYPE[overlapLength * 2];
642         bMidBufferDirty = TRUE;
643         clearMidBuffer();
644
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);
648     }
649 }
650
651 TDStretch * TDStretch::newInstance()
652 {
653     uint uExtensions;
654
655     uExtensions = detectCPUextensions();
656
657     // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
658
659 #ifdef ALLOW_MMX
660     // MMX routines available only with integer sample types
661     if (uExtensions & SUPPORT_MMX)
662     {
663         return ::new TDStretchMMX;
664     }
665     else
666 #endif // ALLOW_MMX
667
668
669 #ifdef ALLOW_SSE
670     if (uExtensions & SUPPORT_SSE)
671     {
672         // SSE support
673         return ::new TDStretchSSE;
674     }
675     else
676 #endif // ALLOW_SSE
677
678
679 #ifdef ALLOW_3DNOW
680     if (uExtensions & SUPPORT_3DNOW)
681     {
682         // 3DNow! support
683         return ::new TDStretch3DNow;
684     }
685     else
686 #endif // ALLOW_3DNOW
687
688     {
689         // ISA optimizations not supported, use plain C version
690         return ::new TDStretch;
691     }
692 }
693
694
695 //////////////////////////////////////////////////////////////////////////////
696 //
697 // Integer arithmetics specific algorithm implementations.
698 //
699 //////////////////////////////////////////////////////////////////////////////
700
701 #ifdef INTEGER_SAMPLES
702
703 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
704 // is faster to calculate
705 void TDStretch::precalcCorrReferenceStereo()
706 {
707     int i, cnt2;
708     int temp, temp2;
709
710     for (i=0 ; i < (int)overlapLength ;i ++) 
711     {
712         temp = i * (overlapLength - i);
713         cnt2 = i * 2;
714
715         temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
716         pRefMidBuffer[cnt2] = (short)(temp2);
717         temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
718         pRefMidBuffer[cnt2 + 1] = (short)(temp2);
719     }
720 }
721
722
723 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
724 // is faster to calculate
725 void TDStretch::precalcCorrReferenceMono()
726 {
727     int i;
728     long temp;
729     long temp2;
730
731     for (i=0 ; i < (int)overlapLength ;i ++) 
732     {
733         temp = i * (overlapLength - i);
734         temp2 = (pMidBuffer[i] * temp) / slopingDivider;
735         pRefMidBuffer[i] = (short)temp2;
736     }
737 }
738
739
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
743 {
744     int i;
745     short temp;
746     uint cnt2;
747
748     for (i = 0; i < (int)overlapLength ; i ++) 
749     {
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;
754     }
755 }
756
757
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)
762 {
763     uint newOvl;
764
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);
769
770     acceptNewOverlapLength(newOvl);
771
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;
776 }
777
778
779 long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
780 {
781     long corr;
782     uint i;
783
784     corr = 0;
785     for (i = 1; i < overlapLength; i ++) 
786     {
787         corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
788     }
789
790     return corr;
791 }
792
793
794 long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
795 {
796     long corr;
797     uint i;
798
799     corr = 0;
800     for (i = 2; i < 2 * overlapLength; i += 2) 
801     {
802         corr += (mixingPos[i] * compare[i] +
803                  mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;
804     }
805
806     return corr;
807 }
808
809 #endif // INTEGER_SAMPLES
810
811 //////////////////////////////////////////////////////////////////////////////
812 //
813 // Floating point arithmetics specific algorithm implementations.
814 //
815
816 #ifdef FLOAT_SAMPLES
817
818
819 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
820 // is faster to calculate
821 void TDStretch::precalcCorrReferenceStereo()
822 {
823     int i, cnt2;
824     float temp;
825
826     for (i=0 ; i < (int)overlapLength ;i ++) 
827     {
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);
832     }
833 }
834
835
836 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
837 // is faster to calculate
838 void TDStretch::precalcCorrReferenceMono()
839 {
840     int i;
841     float temp;
842
843     for (i=0 ; i < (int)overlapLength ;i ++) 
844     {
845         temp = (float)i * (float)(overlapLength - i);
846         pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
847     }
848 }
849
850
851 // SSE-optimized version of the function overlapStereo
852 void TDStretch::overlapStereo(float *output, const float *input) const
853 {
854     int i;
855     uint cnt2;
856     float fTemp;
857     float fScale;
858     float fi;
859
860     fScale = 1.0f / (float)overlapLength;
861
862     for (i = 0; i < (int)overlapLength ; i ++) 
863     {
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;
869     }
870 }
871
872
873 /// Calculates overlap period length in samples.
874 void TDStretch::calculateOverlapLength(uint overlapMs)
875 {
876     uint newOvl;
877
878     newOvl = (sampleRate * overlapMs) / 1000;
879     if (newOvl < 16) newOvl = 16;
880
881     acceptNewOverlapLength(newOvl);
882 }
883
884
885
886 double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
887 {
888     double corr;
889     uint i;
890
891     corr = 0;
892     for (i = 1; i < overlapLength; i ++) 
893     {
894         corr += mixingPos[i] * compare[i];
895     }
896
897     return corr;
898 }
899
900
901 double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
902 {
903     double corr;
904     uint i;
905
906     corr = 0;
907     for (i = 2; i < 2 * overlapLength; i += 2) 
908     {
909         corr += mixingPos[i] * compare[i] +
910                 mixingPos[i + 1] * compare[i + 1];
911     }
912
913     return corr;
914 }
915
916 #endif // FLOAT_SAMPLES