fix bug in find_next_region() when starting frame matches region start
[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 <string.h>
45 #include <stdlib.h>
46 #include <memory.h>
47 #include <limits.h>
48 #include <math.h>
49 #include <assert.h>
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 // Calculates the x having the closest 2^x value for the given value
118 static int _getClosest2Power(double value)
119 {
120     return (int)(log(value) / log(2.0) + 0.5);
121 }
122
123
124
125 // Sets routine control parameters. These control are certain time constants
126 // defining how the sound is stretched to the desired duration.
127 //
128 // 'sampleRate' = sample rate of the sound
129 // 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)
130 // 'seekwindowMS' = seeking window length for scanning the best overlapping 
131 //      position (default = 28 ms)
132 // 'overlapMS' = overlapping length (default = 12 ms)
133
134 void TDStretch::setParameters(uint aSampleRate, uint aSequenceMS, 
135                               uint aSeekWindowMS, uint aOverlapMS)
136 {
137     this->sampleRate = aSampleRate;
138     this->sequenceMs = aSequenceMS;
139     this->seekWindowMs = aSeekWindowMS;
140     this->overlapMs = aOverlapMS;
141
142     seekLength = (sampleRate * seekWindowMs) / 1000;
143     seekWindowLength = (sampleRate * sequenceMs) / 1000;
144
145     maxOffset = seekLength;
146
147     calculateOverlapLength(overlapMs);
148
149     // set tempo to recalculate 'sampleReq'
150     setTempo(tempo);
151
152 }
153
154
155
156 /// Get routine control parameters, see setParameters() function.
157 /// Any of the parameters to this function can be NULL, in such case corresponding parameter
158 /// value isn't returned.
159 void TDStretch::getParameters(uint *pSampleRate, uint *pSequenceMs, uint *pSeekWindowMs, uint *pOverlapMs)
160 {
161     if (pSampleRate)
162     {
163         *pSampleRate = sampleRate;
164     }
165
166     if (pSequenceMs)
167     {
168         *pSequenceMs = sequenceMs;
169     }
170
171     if (pSeekWindowMs)
172     {
173         *pSeekWindowMs = seekWindowMs;
174     }
175
176     if (pOverlapMs)
177     {
178         *pOverlapMs = overlapMs;
179     }
180 }
181
182
183 // Overlaps samples in 'midBuffer' with the samples in 'input'
184 void TDStretch::overlapMono(SAMPLETYPE *output, const SAMPLETYPE *input) const
185 {
186     int i, itemp;
187
188     for (i = 0; i < (int)overlapLength ; i ++) 
189     {
190         itemp = overlapLength - i;
191         output[i] = (input[i] * i + pMidBuffer[i] * itemp ) / overlapLength;    // >> overlapDividerBits;
192     }
193 }
194
195
196
197 void TDStretch::clearMidBuffer()
198 {
199     if (bMidBufferDirty) 
200     {
201         memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
202         bMidBufferDirty = FALSE;
203     }
204 }
205
206
207 void TDStretch::clearInput()
208 {
209     inputBuffer.clear();
210     clearMidBuffer();
211 }
212
213
214 // Clears the sample buffers
215 void TDStretch::clear()
216 {
217     outputBuffer.clear();
218     inputBuffer.clear();
219     clearMidBuffer();
220 }
221
222
223
224 // Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
225 // to enable
226 void TDStretch::enableQuickSeek(BOOL enable)
227 {
228     bQuickseek = enable;
229 }
230
231
232 // Returns nonzero if the quick seeking algorithm is enabled.
233 BOOL TDStretch::isQuickSeekEnabled() const
234 {
235     return bQuickseek;
236 }
237
238
239 // Seeks for the optimal overlap-mixing position.
240 uint TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
241 {
242     if (channels == 2) 
243     {
244         // stereo sound
245         if (bQuickseek) 
246         {
247             return seekBestOverlapPositionStereoQuick(refPos);
248         } 
249         else 
250         {
251             return seekBestOverlapPositionStereo(refPos);
252         }
253     } 
254     else 
255     {
256         // mono sound
257         if (bQuickseek) 
258         {
259             return seekBestOverlapPositionMonoQuick(refPos);
260         } 
261         else 
262         {
263             return seekBestOverlapPositionMono(refPos);
264         }
265     }
266 }
267
268
269
270
271 // Overlaps samples in 'midBuffer' with the samples in 'inputBuffer' at position
272 // of 'ovlPos'.
273 inline void TDStretch::overlap(SAMPLETYPE *output, const SAMPLETYPE *input, uint ovlPos) const
274 {
275     if (channels == 2) 
276     {
277         // stereo sound
278         overlapStereo(output, input + 2 * ovlPos);
279     } else {
280         // mono sound.
281         overlapMono(output, input + ovlPos);
282     }
283 }
284
285
286
287
288 // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
289 // routine
290 //
291 // The best position is determined as the position where the two overlapped
292 // sample sequences are 'most alike', in terms of the highest cross-correlation
293 // value over the overlapping period
294 uint TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos) 
295 {
296     uint bestOffs;
297     LONG_SAMPLETYPE bestCorr, corr;
298     uint i;
299
300     // Slopes the amplitudes of the 'midBuffer' samples
301     precalcCorrReferenceStereo();
302
303     bestCorr = INT_MIN;
304     bestOffs = 0;
305
306     // Scans for the best correlation value by testing each possible position
307     // over the permitted range.
308     for (i = 0; i < seekLength; i ++) 
309     {
310         // Calculates correlation value for the mixing position corresponding
311         // to 'i'
312         corr = calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);
313
314         // Checks for the highest correlation value
315         if (corr > bestCorr) 
316         {
317             bestCorr = corr;
318             bestOffs = i;
319         }
320     }
321     // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
322     clearCrossCorrState();
323
324     return bestOffs;
325 }
326
327
328 // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
329 // routine
330 //
331 // The best position is determined as the position where the two overlapped
332 // sample sequences are 'most alike', in terms of the highest cross-correlation
333 // value over the overlapping period
334 uint TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos) 
335 {
336     uint j;
337     uint bestOffs;
338     LONG_SAMPLETYPE bestCorr, corr;
339     uint scanCount, corrOffset, tempOffset;
340
341     // Slopes the amplitude of the 'midBuffer' samples
342     precalcCorrReferenceStereo();
343
344     bestCorr = INT_MIN;
345     bestOffs = 0;
346     corrOffset = 0;
347     tempOffset = 0;
348
349     // Scans for the best correlation value using four-pass hierarchical search.
350     //
351     // The look-up table 'scans' has hierarchical position adjusting steps.
352     // In first pass the routine searhes for the highest correlation with 
353     // relatively coarse steps, then rescans the neighbourhood of the highest
354     // correlation with better resolution and so on.
355     for (scanCount = 0;scanCount < 4; scanCount ++) 
356     {
357         j = 0;
358         while (scanOffsets[scanCount][j]) 
359         {
360             tempOffset = corrOffset + scanOffsets[scanCount][j];
361             if (tempOffset >= seekLength) break;
362
363             // Calculates correlation value for the mixing position corresponding
364             // to 'tempOffset'
365             corr = calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);
366
367             // Checks for the highest correlation value
368             if (corr > bestCorr) 
369             {
370                 bestCorr = corr;
371                 bestOffs = tempOffset;
372             }
373             j ++;
374         }
375         corrOffset = bestOffs;
376     }
377     // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
378     clearCrossCorrState();
379
380     return bestOffs;
381 }
382
383
384
385 // Seeks for the optimal overlap-mixing position. The 'mono' version of the
386 // routine
387 //
388 // The best position is determined as the position where the two overlapped
389 // sample sequences are 'most alike', in terms of the highest cross-correlation
390 // value over the overlapping period
391 uint TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos) 
392 {
393     uint bestOffs;
394     LONG_SAMPLETYPE bestCorr, corr;
395     uint tempOffset;
396     const SAMPLETYPE *compare;
397
398     // Slopes the amplitude of the 'midBuffer' samples
399     precalcCorrReferenceMono();
400
401     bestCorr = INT_MIN;
402     bestOffs = 0;
403
404     // Scans for the best correlation value by testing each possible position
405     // over the permitted range.
406     for (tempOffset = 0; tempOffset < seekLength; tempOffset ++) 
407     {
408         compare = refPos + tempOffset;
409
410         // Calculates correlation value for the mixing position corresponding
411         // to 'tempOffset'
412         corr = calcCrossCorrMono(pRefMidBuffer, compare);
413
414         // Checks for the highest correlation value
415         if (corr > bestCorr) 
416         {
417             bestCorr = corr;
418             bestOffs = tempOffset;
419         }
420     }
421     // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
422     clearCrossCorrState();
423
424     return bestOffs;
425 }
426
427
428 // Seeks for the optimal overlap-mixing position. The 'mono' version of the
429 // routine
430 //
431 // The best position is determined as the position where the two overlapped
432 // sample sequences are 'most alike', in terms of the highest cross-correlation
433 // value over the overlapping period
434 uint TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos) 
435 {
436     uint j;
437     uint bestOffs;
438     LONG_SAMPLETYPE bestCorr, corr;
439     uint scanCount, corrOffset, tempOffset;
440
441     // Slopes the amplitude of the 'midBuffer' samples
442     precalcCorrReferenceMono();
443
444     bestCorr = INT_MIN;
445     bestOffs = 0;
446     corrOffset = 0;
447     tempOffset = 0;
448
449     // Scans for the best correlation value using four-pass hierarchical search.
450     //
451     // The look-up table 'scans' has hierarchical position adjusting steps.
452     // In first pass the routine searhes for the highest correlation with 
453     // relatively coarse steps, then rescans the neighbourhood of the highest
454     // correlation with better resolution and so on.
455     for (scanCount = 0;scanCount < 4; scanCount ++) 
456     {
457         j = 0;
458         while (scanOffsets[scanCount][j]) 
459         {
460             tempOffset = corrOffset + scanOffsets[scanCount][j];
461             if (tempOffset >= seekLength) break;
462
463             // Calculates correlation value for the mixing position corresponding
464             // to 'tempOffset'
465             corr = calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);
466
467             // Checks for the highest correlation value
468             if (corr > bestCorr) 
469             {
470                 bestCorr = corr;
471                 bestOffs = tempOffset;
472             }
473             j ++;
474         }
475         corrOffset = bestOffs;
476     }
477     // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
478     clearCrossCorrState();
479
480     return bestOffs;
481 }
482
483
484 /// clear cross correlation routine state if necessary 
485 void TDStretch::clearCrossCorrState()
486 {
487     // default implementation is empty.
488 }
489
490
491 // Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower 
492 // tempo, larger faster tempo.
493 void TDStretch::setTempo(float newTempo)
494 {
495     uint intskip;
496
497     tempo = newTempo;
498
499     // Calculate ideal skip length (according to tempo value) 
500     nominalSkip = tempo * (seekWindowLength - overlapLength);
501     skipFract = 0;
502     intskip = (int)(nominalSkip + 0.5f);
503
504     // Calculate how many samples are needed in the 'inputBuffer' to 
505     // process another batch of samples
506     sampleReq = max(intskip + overlapLength, seekWindowLength) + maxOffset;
507 }
508
509
510
511 // Sets the number of channels, 1 = mono, 2 = stereo
512 void TDStretch::setChannels(uint numChannels)
513 {
514     if (channels == numChannels) return;
515     assert(numChannels == 1 || numChannels == 2);
516
517     channels = numChannels;
518     inputBuffer.setChannels(channels);
519     outputBuffer.setChannels(channels);
520 }
521
522
523 // nominal tempo, no need for processing, just pass the samples through
524 // to outputBuffer
525 void TDStretch::processNominalTempo()
526 {
527     assert(tempo == 1.0f);
528
529     if (bMidBufferDirty) 
530     {
531         // If there are samples in pMidBuffer waiting for overlapping,
532         // do a single sliding overlapping with them in order to prevent a 
533         // clicking distortion in the output sound
534         if (inputBuffer.numSamples() < overlapLength) 
535         {
536             // wait until we've got overlapLength input samples
537             return;
538         }
539         // Mix the samples in the beginning of 'inputBuffer' with the 
540         // samples in 'midBuffer' using sliding overlapping 
541         overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0);
542         outputBuffer.putSamples(overlapLength);
543         inputBuffer.receiveSamples(overlapLength);
544         clearMidBuffer();
545         // now we've caught the nominal sample flow and may switch to
546         // bypass mode
547     }
548
549     // Simply bypass samples from input to output
550     outputBuffer.moveSamples(inputBuffer);
551 }
552
553
554 // Processes as many processing frames of the samples 'inputBuffer', store
555 // the result into 'outputBuffer'
556 void TDStretch::processSamples()
557 {
558     uint ovlSkip, offset;
559     int temp;
560
561     if (tempo == 1.0f) 
562     {
563         // tempo not changed from the original, so bypass the processing
564         processNominalTempo();
565         return;
566     }
567
568     if (bMidBufferDirty == FALSE) 
569     {
570         // if midBuffer is empty, move the first samples of the input stream 
571         // into it
572         if (inputBuffer.numSamples() < overlapLength) 
573         {
574             // wait until we've got overlapLength samples
575             return;
576         }
577         memcpy(pMidBuffer, inputBuffer.ptrBegin(), channels * overlapLength * sizeof(SAMPLETYPE));
578         inputBuffer.receiveSamples(overlapLength);
579         bMidBufferDirty = TRUE;
580     }
581
582     // Process samples as long as there are enough samples in 'inputBuffer'
583     // to form a processing frame.
584     while (inputBuffer.numSamples() >= sampleReq) 
585     {
586         // If tempo differs from the normal ('SCALE'), scan for the best overlapping
587         // position
588         offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
589
590         // Mix the samples in the 'inputBuffer' at position of 'offset' with the 
591         // samples in 'midBuffer' using sliding overlapping
592         // ... first partially overlap with the end of the previous sequence
593         // (that's in 'midBuffer')
594         overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), offset);
595         outputBuffer.putSamples(overlapLength);
596
597         // ... then copy sequence samples from 'inputBuffer' to output
598         temp = (seekWindowLength - 2 * overlapLength);// & 0xfffffffe;
599         if (temp > 0)
600         {
601             outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), temp);
602         }
603
604         // Copies the end of the current sequence from 'inputBuffer' to 
605         // 'midBuffer' for being mixed with the beginning of the next 
606         // processing sequence and so on
607         assert(offset + seekWindowLength <= inputBuffer.numSamples());
608         memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + seekWindowLength - overlapLength), 
609             channels * sizeof(SAMPLETYPE) * overlapLength);
610         bMidBufferDirty = TRUE;
611
612         // Remove the processed samples from the input buffer. Update
613         // the difference between integer & nominal skip step to 'skipFract'
614         // in order to prevent the error from accumulating over time.
615         skipFract += nominalSkip;   // real skip size
616         ovlSkip = (int)skipFract;   // rounded to integer skip
617         skipFract -= ovlSkip;       // maintain the fraction part, i.e. real vs. integer skip
618         inputBuffer.receiveSamples(ovlSkip);
619     }
620 }
621
622
623 // Adds 'numsamples' pcs of samples from the 'samples' memory position into
624 // the input of the object.
625 void TDStretch::putSamples(const SAMPLETYPE *samples, uint numSamples)
626 {
627     // Add the samples into the input buffer
628     inputBuffer.putSamples(samples, numSamples);
629     // Process the samples in input buffer
630     processSamples();
631 }
632
633
634
635 /// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
636 void TDStretch::acceptNewOverlapLength(uint newOverlapLength)
637 {
638     uint prevOvl;
639
640     prevOvl = overlapLength;
641     overlapLength = newOverlapLength;
642
643     if (overlapLength > prevOvl)
644     {
645         delete[] pMidBuffer;
646         delete[] pRefMidBufferUnaligned;
647
648         pMidBuffer = new SAMPLETYPE[overlapLength * 2];
649         bMidBufferDirty = TRUE;
650         clearMidBuffer();
651
652         pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];
653         // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency
654         pRefMidBuffer = (SAMPLETYPE *)((((ulong)pRefMidBufferUnaligned) + 15) & -16);
655     }
656 }
657
658 TDStretch * TDStretch::newInstance()
659 {
660     uint uExtensions;
661
662     uExtensions = detectCPUextensions();
663
664     // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
665
666 #ifdef ALLOW_MMX
667     // MMX routines available only with integer sample types
668     if (uExtensions & SUPPORT_MMX)
669     {
670         return ::new TDStretchMMX;
671     }
672     else
673 #endif // ALLOW_MMX
674
675
676 #ifdef ALLOW_SSE
677     if (uExtensions & SUPPORT_SSE)
678     {
679         // SSE support
680         return ::new TDStretchSSE;
681     }
682     else
683 #endif // ALLOW_SSE
684
685
686 #ifdef ALLOW_3DNOW
687     if (uExtensions & SUPPORT_3DNOW)
688     {
689         // 3DNow! support
690         return ::new TDStretch3DNow;
691     }
692     else
693 #endif // ALLOW_3DNOW
694
695     {
696         // ISA optimizations not supported, use plain C version
697         return ::new TDStretch;
698     }
699 }
700
701
702 //////////////////////////////////////////////////////////////////////////////
703 //
704 // Integer arithmetics specific algorithm implementations.
705 //
706 //////////////////////////////////////////////////////////////////////////////
707
708 #ifdef INTEGER_SAMPLES
709
710 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
711 // is faster to calculate
712 void TDStretch::precalcCorrReferenceStereo()
713 {
714     int i, cnt2;
715     int temp, temp2;
716
717     for (i=0 ; i < (int)overlapLength ;i ++) 
718     {
719         temp = i * (overlapLength - i);
720         cnt2 = i * 2;
721
722         temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
723         pRefMidBuffer[cnt2] = (short)(temp2);
724         temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
725         pRefMidBuffer[cnt2 + 1] = (short)(temp2);
726     }
727 }
728
729
730 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
731 // is faster to calculate
732 void TDStretch::precalcCorrReferenceMono()
733 {
734     int i;
735     long temp;
736     long temp2;
737
738     for (i=0 ; i < (int)overlapLength ;i ++) 
739     {
740         temp = i * (overlapLength - i);
741         temp2 = (pMidBuffer[i] * temp) / slopingDivider;
742         pRefMidBuffer[i] = (short)temp2;
743     }
744 }
745
746
747 // Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo' 
748 // version of the routine.
749 void TDStretch::overlapStereo(short *output, const short *input) const
750 {
751     int i;
752     short temp;
753     uint cnt2;
754
755     for (i = 0; i < (int)overlapLength ; i ++) 
756     {
757         temp = (short)(overlapLength - i);
758         cnt2 = 2 * i;
759         output[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp )  / overlapLength;
760         output[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength;
761     }
762 }
763
764
765 /// Calculates overlap period length in samples.
766 /// Integer version rounds overlap length to closest power of 2
767 /// for a divide scaling operation.
768 void TDStretch::calculateOverlapLength(uint overlapMs)
769 {
770     uint newOvl;
771
772     overlapDividerBits = _getClosest2Power((sampleRate * overlapMs) / 1000.0);
773     if (overlapDividerBits > 9) overlapDividerBits = 9;
774     if (overlapDividerBits < 4) overlapDividerBits = 4;
775     newOvl = (uint)pow(2, overlapDividerBits);
776
777     acceptNewOverlapLength(newOvl);
778
779     // calculate sloping divider so that crosscorrelation operation won't 
780     // overflow 32-bit register. Max. sum of the crosscorrelation sum without 
781     // divider would be 2^30*(N^3-N)/3, where N = overlap length
782     slopingDivider = (newOvl * newOvl - 1) / 3;
783 }
784
785
786 long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
787 {
788     long corr;
789     uint i;
790
791     corr = 0;
792     for (i = 1; i < overlapLength; i ++) 
793     {
794         corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
795     }
796
797     return corr;
798 }
799
800
801 long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
802 {
803     long corr;
804     uint i;
805
806     corr = 0;
807     for (i = 2; i < 2 * overlapLength; i += 2) 
808     {
809         corr += (mixingPos[i] * compare[i] +
810                  mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;
811     }
812
813     return corr;
814 }
815
816 #endif // INTEGER_SAMPLES
817
818 //////////////////////////////////////////////////////////////////////////////
819 //
820 // Floating point arithmetics specific algorithm implementations.
821 //
822
823 #ifdef FLOAT_SAMPLES
824
825
826 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
827 // is faster to calculate
828 void TDStretch::precalcCorrReferenceStereo()
829 {
830     int i, cnt2;
831     float temp;
832
833     for (i=0 ; i < (int)overlapLength ;i ++) 
834     {
835         temp = (float)i * (float)(overlapLength - i);
836         cnt2 = i * 2;
837         pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);
838         pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);
839     }
840 }
841
842
843 // Slopes the amplitude of the 'midBuffer' samples so that cross correlation
844 // is faster to calculate
845 void TDStretch::precalcCorrReferenceMono()
846 {
847     int i;
848     float temp;
849
850     for (i=0 ; i < (int)overlapLength ;i ++) 
851     {
852         temp = (float)i * (float)(overlapLength - i);
853         pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
854     }
855 }
856
857
858 // SSE-optimized version of the function overlapStereo
859 void TDStretch::overlapStereo(float *output, const float *input) const
860 {
861     int i;
862     uint cnt2;
863     float fTemp;
864     float fScale;
865     float fi;
866
867     fScale = 1.0f / (float)overlapLength;
868
869     for (i = 0; i < (int)overlapLength ; i ++) 
870     {
871         fTemp = (float)(overlapLength - i) * fScale;
872         fi = (float)i * fScale;
873         cnt2 = 2 * i;
874         output[cnt2 + 0] = input[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;
875         output[cnt2 + 1] = input[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;
876     }
877 }
878
879
880 /// Calculates overlap period length in samples.
881 void TDStretch::calculateOverlapLength(uint overlapMs)
882 {
883     uint newOvl;
884
885     newOvl = (sampleRate * overlapMs) / 1000;
886     if (newOvl < 16) newOvl = 16;
887
888     acceptNewOverlapLength(newOvl);
889 }
890
891
892
893 double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
894 {
895     double corr;
896     uint i;
897
898     corr = 0;
899     for (i = 1; i < overlapLength; i ++) 
900     {
901         corr += mixingPos[i] * compare[i];
902     }
903
904     return corr;
905 }
906
907
908 double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
909 {
910     double corr;
911     uint i;
912
913     corr = 0;
914     for (i = 2; i < 2 * overlapLength; i += 2) 
915     {
916         corr += mixingPos[i] * compare[i] +
917                 mixingPos[i + 1] * compare[i + 1];
918     }
919
920     return corr;
921 }
922
923 #endif // FLOAT_SAMPLES