~alex.barker/mixxx/mixxx-libs

« back to all changes in this revision

Viewing changes to mixxx/lib/soundtouch-1.6.0/TDStretch.cpp

  • Committer: Alex Barker
  • Date: 2011-07-24 21:06:29 UTC
  • Revision ID: alex@1stleg.com-20110724210629-zyr2khq2o0nv8iru
Updated libsoundtouch and fidlib to latest versions

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
////////////////////////////////////////////////////////////////////////////////
 
2
/// 
 
3
/// Sampled sound tempo changer/time stretch algorithm. Changes the sound tempo 
 
4
/// while maintaining the original pitch by using a time domain WSOLA-like 
 
5
/// method with several performance-increasing tweaks.
 
6
///
 
7
/// Note : MMX optimized functions reside in a separate, platform-specific 
 
8
/// file, e.g. 'mmx_win.cpp' or 'mmx_gcc.cpp'
 
9
///
 
10
/// Author        : Copyright (c) Olli Parviainen
 
11
/// Author e-mail : oparviai 'at' iki.fi
 
12
/// SoundTouch WWW: http://www.surina.net/soundtouch
 
13
///
 
14
////////////////////////////////////////////////////////////////////////////////
 
15
//
 
16
// Last changed  : $Date: 2011-02-13 21:13:57 +0200 (Sun, 13 Feb 2011) $
 
17
// File revision : $Revision: 1.12 $
 
18
//
 
19
// $Id: TDStretch.cpp 104 2011-02-13 19:13:57Z oparviai $
 
20
//
 
21
////////////////////////////////////////////////////////////////////////////////
 
22
//
 
23
// License :
 
24
//
 
25
//  SoundTouch audio processing library
 
26
//  Copyright (c) Olli Parviainen
 
27
//
 
28
//  This library is free software; you can redistribute it and/or
 
29
//  modify it under the terms of the GNU Lesser General Public
 
30
//  License as published by the Free Software Foundation; either
 
31
//  version 2.1 of the License, or (at your option) any later version.
 
32
//
 
33
//  This library is distributed in the hope that it will be useful,
 
34
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
35
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
36
//  Lesser General Public License for more details.
 
37
//
 
38
//  You should have received a copy of the GNU Lesser General Public
 
39
//  License along with this library; if not, write to the Free Software
 
40
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
41
//
 
42
////////////////////////////////////////////////////////////////////////////////
 
43
 
 
44
#include <string.h>
 
45
#include <limits.h>
 
46
#include <assert.h>
 
47
#include <math.h>
 
48
#include <float.h>
 
49
#include <stdexcept>
 
50
 
 
51
#include "STTypes.h"
 
52
#include "cpu_detect.h"
 
53
#include "TDStretch.h"
 
54
 
 
55
#include <stdio.h>
 
56
 
 
57
using namespace soundtouch;
 
58
 
 
59
#define max(x, y) (((x) > (y)) ? (x) : (y))
 
60
 
 
61
 
 
62
/*****************************************************************************
 
63
 *
 
64
 * Constant definitions
 
65
 *
 
66
 *****************************************************************************/
 
67
 
 
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}};
 
80
 
 
81
/*****************************************************************************
 
82
 *
 
83
 * Implementation of the class 'TDStretch'
 
84
 *
 
85
 *****************************************************************************/
 
86
 
 
87
 
 
88
TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
 
89
{
 
90
    bQuickSeek = FALSE;
 
91
    channels = 2;
 
92
 
 
93
    pMidBuffer = NULL;
 
94
    pRefMidBufferUnaligned = NULL;
 
95
    overlapLength = 0;
 
96
 
 
97
    bAutoSeqSetting = TRUE;
 
98
    bAutoSeekSetting = TRUE;
 
99
 
 
100
//    outDebt = 0;
 
101
    skipFract = 0;
 
102
 
 
103
    tempo = 1.0f;
 
104
    setParameters(44100, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
 
105
    setTempo(1.0f);
 
106
 
 
107
    clear();
 
108
}
 
109
 
 
110
 
 
111
 
 
112
TDStretch::~TDStretch()
 
113
{
 
114
    delete[] pMidBuffer;
 
115
    delete[] pRefMidBufferUnaligned;
 
116
}
 
117
 
 
118
 
 
119
 
 
120
// Sets routine control parameters. These control are certain time constants
 
121
// defining how the sound is stretched to the desired duration.
 
122
//
 
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)
 
128
 
 
129
void TDStretch::setParameters(int aSampleRate, int aSequenceMS, 
 
130
                              int aSeekWindowMS, int aOverlapMS)
 
131
{
 
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;
 
135
 
 
136
    if (aSequenceMS > 0)
 
137
    {
 
138
        this->sequenceMs = aSequenceMS;
 
139
        bAutoSeqSetting = FALSE;
 
140
    } 
 
141
    else if (aSequenceMS == 0)
 
142
    {
 
143
        // if zero, use automatic setting
 
144
        bAutoSeqSetting = TRUE;
 
145
    }
 
146
 
 
147
    if (aSeekWindowMS > 0) 
 
148
    {
 
149
        this->seekWindowMs = aSeekWindowMS;
 
150
        bAutoSeekSetting = FALSE;
 
151
    } 
 
152
    else if (aSeekWindowMS == 0) 
 
153
    {
 
154
        // if zero, use automatic setting
 
155
        bAutoSeekSetting = TRUE;
 
156
    }
 
157
 
 
158
    calcSeqParameters();
 
159
 
 
160
    calculateOverlapLength(overlapMs);
 
161
 
 
162
    // set tempo to recalculate 'sampleReq'
 
163
    setTempo(tempo);
 
164
 
 
165
}
 
166
 
 
167
 
 
168
 
 
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
 
173
{
 
174
    if (pSampleRate)
 
175
    {
 
176
        *pSampleRate = sampleRate;
 
177
    }
 
178
 
 
179
    if (pSequenceMs)
 
180
    {
 
181
        *pSequenceMs = (bAutoSeqSetting) ? (USE_AUTO_SEQUENCE_LEN) : sequenceMs;
 
182
    }
 
183
 
 
184
    if (pSeekWindowMs)
 
185
    {
 
186
        *pSeekWindowMs = (bAutoSeekSetting) ? (USE_AUTO_SEEKWINDOW_LEN) : seekWindowMs;
 
187
    }
 
188
 
 
189
    if (pOverlapMs)
 
190
    {
 
191
        *pOverlapMs = overlapMs;
 
192
    }
 
193
}
 
194
 
 
195
 
 
196
// Overlaps samples in 'midBuffer' with the samples in 'pInput'
 
197
void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const
 
198
{
 
199
    int i, itemp;
 
200
 
 
201
    for (i = 0; i < overlapLength ; i ++) 
 
202
    {
 
203
        itemp = overlapLength - i;
 
204
        pOutput[i] = (pInput[i] * i + pMidBuffer[i] * itemp ) / overlapLength;    // >> overlapDividerBits;
 
205
    }
 
206
}
 
207
 
 
208
 
 
209
 
 
210
void TDStretch::clearMidBuffer()
 
211
{
 
212
    memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
 
213
}
 
214
 
 
215
 
 
216
void TDStretch::clearInput()
 
217
{
 
218
    inputBuffer.clear();
 
219
    clearMidBuffer();
 
220
}
 
221
 
 
222
 
 
223
// Clears the sample buffers
 
224
void TDStretch::clear()
 
225
{
 
226
    outputBuffer.clear();
 
227
    clearInput();
 
228
}
 
229
 
 
230
 
 
231
 
 
232
// Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
 
233
// to enable
 
234
void TDStretch::enableQuickSeek(BOOL enable)
 
235
{
 
236
    bQuickSeek = enable;
 
237
}
 
238
 
 
239
 
 
240
// Returns nonzero if the quick seeking algorithm is enabled.
 
241
BOOL TDStretch::isQuickSeekEnabled() const
 
242
{
 
243
    return bQuickSeek;
 
244
}
 
245
 
 
246
 
 
247
// Seeks for the optimal overlap-mixing position.
 
248
int TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
 
249
{
 
250
    if (channels == 2) 
 
251
    {
 
252
        // stereo sound
 
253
        if (bQuickSeek) 
 
254
        {
 
255
            return seekBestOverlapPositionStereoQuick(refPos);
 
256
        } 
 
257
        else 
 
258
        {
 
259
            return seekBestOverlapPositionStereo(refPos);
 
260
        }
 
261
    } 
 
262
    else 
 
263
    {
 
264
        // mono sound
 
265
        if (bQuickSeek) 
 
266
        {
 
267
            return seekBestOverlapPositionMonoQuick(refPos);
 
268
        } 
 
269
        else 
 
270
        {
 
271
            return seekBestOverlapPositionMono(refPos);
 
272
        }
 
273
    }
 
274
}
 
275
 
 
276
 
 
277
 
 
278
 
 
279
// Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position
 
280
// of 'ovlPos'.
 
281
inline void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint ovlPos) const
 
282
{
 
283
    if (channels == 2) 
 
284
    {
 
285
        // stereo sound
 
286
        overlapStereo(pOutput, pInput + 2 * ovlPos);
 
287
    } else {
 
288
        // mono sound.
 
289
        overlapMono(pOutput, pInput + ovlPos);
 
290
    }
 
291
}
 
292
 
 
293
 
 
294
 
 
295
 
 
296
// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
 
297
// routine
 
298
//
 
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) 
 
303
{
 
304
    int bestOffs;
 
305
    double bestCorr, corr;
 
306
    int i;
 
307
 
 
308
    // Slopes the amplitudes of the 'midBuffer' samples
 
309
    precalcCorrReferenceStereo();
 
310
 
 
311
    bestCorr = FLT_MIN;
 
312
    bestOffs = 0;
 
313
 
 
314
    // Scans for the best correlation value by testing each possible position
 
315
    // over the permitted range.
 
316
    for (i = 0; i < seekLength; i ++) 
 
317
    {
 
318
        // Calculates correlation value for the mixing position corresponding
 
319
        // to 'i'
 
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));
 
324
 
 
325
        // Checks for the highest correlation value
 
326
        if (corr > bestCorr) 
 
327
        {
 
328
            bestCorr = corr;
 
329
            bestOffs = i;
 
330
        }
 
331
    }
 
332
    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
 
333
    clearCrossCorrState();
 
334
 
 
335
    return bestOffs;
 
336
}
 
337
 
 
338
 
 
339
// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
 
340
// routine
 
341
//
 
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) 
 
346
{
 
347
    int j;
 
348
    int bestOffs;
 
349
    double bestCorr, corr;
 
350
    int scanCount, corrOffset, tempOffset;
 
351
 
 
352
    // Slopes the amplitude of the 'midBuffer' samples
 
353
    precalcCorrReferenceStereo();
 
354
 
 
355
    bestCorr = FLT_MIN;
 
356
    bestOffs = _scanOffsets[0][0];
 
357
    corrOffset = 0;
 
358
    tempOffset = 0;
 
359
 
 
360
    // Scans for the best correlation value using four-pass hierarchical search.
 
361
    //
 
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 ++) 
 
367
    {
 
368
        j = 0;
 
369
        while (_scanOffsets[scanCount][j]) 
 
370
        {
 
371
            tempOffset = corrOffset + _scanOffsets[scanCount][j];
 
372
            if (tempOffset >= seekLength) break;
 
373
 
 
374
            // Calculates correlation value for the mixing position corresponding
 
375
            // to 'tempOffset'
 
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));
 
380
 
 
381
            // Checks for the highest correlation value
 
382
            if (corr > bestCorr) 
 
383
            {
 
384
                bestCorr = corr;
 
385
                bestOffs = tempOffset;
 
386
            }
 
387
            j ++;
 
388
        }
 
389
        corrOffset = bestOffs;
 
390
    }
 
391
    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
 
392
    clearCrossCorrState();
 
393
 
 
394
    return bestOffs;
 
395
}
 
396
 
 
397
 
 
398
 
 
399
// Seeks for the optimal overlap-mixing position. The 'mono' version of the
 
400
// routine
 
401
//
 
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) 
 
406
{
 
407
    int bestOffs;
 
408
    double bestCorr, corr;
 
409
    int tempOffset;
 
410
    const SAMPLETYPE *compare;
 
411
 
 
412
    // Slopes the amplitude of the 'midBuffer' samples
 
413
    precalcCorrReferenceMono();
 
414
 
 
415
    bestCorr = FLT_MIN;
 
416
    bestOffs = 0;
 
417
 
 
418
    // Scans for the best correlation value by testing each possible position
 
419
    // over the permitted range.
 
420
    for (tempOffset = 0; tempOffset < seekLength; tempOffset ++) 
 
421
    {
 
422
        compare = refPos + tempOffset;
 
423
 
 
424
        // Calculates correlation value for the mixing position corresponding
 
425
        // to 'tempOffset'
 
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));
 
430
 
 
431
        // Checks for the highest correlation value
 
432
        if (corr > bestCorr) 
 
433
        {
 
434
            bestCorr = corr;
 
435
            bestOffs = tempOffset;
 
436
        }
 
437
    }
 
438
    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
 
439
    clearCrossCorrState();
 
440
 
 
441
    return bestOffs;
 
442
}
 
443
 
 
444
 
 
445
// Seeks for the optimal overlap-mixing position. The 'mono' version of the
 
446
// routine
 
447
//
 
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) 
 
452
{
 
453
    int j;
 
454
    int bestOffs;
 
455
    double bestCorr, corr;
 
456
    int scanCount, corrOffset, tempOffset;
 
457
 
 
458
    // Slopes the amplitude of the 'midBuffer' samples
 
459
    precalcCorrReferenceMono();
 
460
 
 
461
    bestCorr = FLT_MIN;
 
462
    bestOffs = _scanOffsets[0][0];
 
463
    corrOffset = 0;
 
464
    tempOffset = 0;
 
465
 
 
466
    // Scans for the best correlation value using four-pass hierarchical search.
 
467
    //
 
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 ++) 
 
473
    {
 
474
        j = 0;
 
475
        while (_scanOffsets[scanCount][j]) 
 
476
        {
 
477
            tempOffset = corrOffset + _scanOffsets[scanCount][j];
 
478
            if (tempOffset >= seekLength) break;
 
479
 
 
480
            // Calculates correlation value for the mixing position corresponding
 
481
            // to 'tempOffset'
 
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));
 
486
 
 
487
            // Checks for the highest correlation value
 
488
            if (corr > bestCorr) 
 
489
            {
 
490
                bestCorr = corr;
 
491
                bestOffs = tempOffset;
 
492
            }
 
493
            j ++;
 
494
        }
 
495
        corrOffset = bestOffs;
 
496
    }
 
497
    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
 
498
    clearCrossCorrState();
 
499
 
 
500
    return bestOffs;
 
501
}
 
502
 
 
503
 
 
504
/// clear cross correlation routine state if necessary 
 
505
void TDStretch::clearCrossCorrState()
 
506
{
 
507
    // default implementation is empty.
 
508
}
 
509
 
 
510
 
 
511
/// Calculates processing sequence length according to tempo setting
 
512
void TDStretch::calcSeqParameters()
 
513
{
 
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%)
 
518
 
 
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))
 
524
 
 
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))
 
530
 
 
531
    #define CHECK_LIMITS(x, mi, ma) (((x) < (mi)) ? (mi) : (((x) > (ma)) ? (ma) : (x)))
 
532
 
 
533
    double seq, seek;
 
534
    
 
535
    if (bAutoSeqSetting)
 
536
    {
 
537
        seq = AUTOSEQ_C + AUTOSEQ_K * tempo;
 
538
        seq = CHECK_LIMITS(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN);
 
539
        sequenceMs = (int)(seq + 0.5);
 
540
    }
 
541
 
 
542
    if (bAutoSeekSetting)
 
543
    {
 
544
        seek = AUTOSEEK_C + AUTOSEEK_K * tempo;
 
545
        seek = CHECK_LIMITS(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN);
 
546
        seekWindowMs = (int)(seek + 0.5);
 
547
    }
 
548
 
 
549
    // Update seek window lengths
 
550
    seekWindowLength = (sampleRate * sequenceMs) / 1000;
 
551
    if (seekWindowLength < 2 * overlapLength) 
 
552
    {
 
553
        seekWindowLength = 2 * overlapLength;
 
554
    }
 
555
    seekLength = (sampleRate * seekWindowMs) / 1000;
 
556
}
 
557
 
 
558
 
 
559
 
 
560
// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower 
 
561
// tempo, larger faster tempo.
 
562
void TDStretch::setTempo(float newTempo)
 
563
{
 
564
    int intskip;
 
565
 
 
566
    tempo = newTempo;
 
567
 
 
568
    // Calculate new sequence duration
 
569
    calcSeqParameters();
 
570
 
 
571
    // Calculate ideal skip length (according to tempo value) 
 
572
    nominalSkip = tempo * (seekWindowLength - overlapLength);
 
573
    intskip = (int)(nominalSkip + 0.5f);
 
574
 
 
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;
 
579
}
 
580
 
 
581
 
 
582
 
 
583
// Sets the number of channels, 1 = mono, 2 = stereo
 
584
void TDStretch::setChannels(int numChannels)
 
585
{
 
586
    assert(numChannels > 0);
 
587
    if (channels == numChannels) return;
 
588
    assert(numChannels == 1 || numChannels == 2);
 
589
 
 
590
    channels = numChannels;
 
591
    inputBuffer.setChannels(channels);
 
592
    outputBuffer.setChannels(channels);
 
593
}
 
594
 
 
595
 
 
596
// nominal tempo, no need for processing, just pass the samples through
 
597
// to outputBuffer
 
598
/*
 
599
void TDStretch::processNominalTempo()
 
600
{
 
601
    assert(tempo == 1.0f);
 
602
 
 
603
    if (bMidBufferDirty) 
 
604
    {
 
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) 
 
609
        {
 
610
            // wait until we've got overlapLength input samples
 
611
            return;
 
612
        }
 
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);
 
618
        clearMidBuffer();
 
619
        // now we've caught the nominal sample flow and may switch to
 
620
        // bypass mode
 
621
    }
 
622
 
 
623
    // Simply bypass samples from input to output
 
624
    outputBuffer.moveSamples(inputBuffer);
 
625
}
 
626
*/
 
627
 
 
628
#include <stdio.h>
 
629
 
 
630
// Processes as many processing frames of the samples 'inputBuffer', store
 
631
// the result into 'outputBuffer'
 
632
void TDStretch::processSamples()
 
633
{
 
634
    int ovlSkip, offset;
 
635
    int temp;
 
636
 
 
637
    /* Removed this small optimization - can introduce a click to sound when tempo setting
 
638
       crosses the nominal value
 
639
    if (tempo == 1.0f) 
 
640
    {
 
641
        // tempo not changed from the original, so bypass the processing
 
642
        processNominalTempo();
 
643
        return;
 
644
    }
 
645
    */
 
646
 
 
647
    // Process samples as long as there are enough samples in 'inputBuffer'
 
648
    // to form a processing frame.
 
649
    while ((int)inputBuffer.numSamples() >= sampleReq) 
 
650
    {
 
651
        // If tempo differs from the normal ('SCALE'), scan for the best overlapping
 
652
        // position
 
653
        offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
 
654
 
 
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);
 
661
 
 
662
        // ... then copy sequence samples from 'inputBuffer' to output:
 
663
 
 
664
        // length of sequence
 
665
        temp = (seekWindowLength - 2 * overlapLength);
 
666
 
 
667
        // crosscheck that we don't have buffer overflow...
 
668
        if ((int)inputBuffer.numSamples() < (offset + temp + overlapLength * 2))
 
669
        {
 
670
            continue;    // just in case, shouldn't really happen
 
671
        }
 
672
 
 
673
        outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), (uint)temp);
 
674
 
 
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);
 
681
 
 
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);
 
689
    }
 
690
}
 
691
 
 
692
 
 
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)
 
696
{
 
697
    // Add the samples into the input buffer
 
698
    inputBuffer.putSamples(samples, nSamples);
 
699
    // Process the samples in input buffer
 
700
    processSamples();
 
701
}
 
702
 
 
703
 
 
704
 
 
705
/// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
 
706
void TDStretch::acceptNewOverlapLength(int newOverlapLength)
 
707
{
 
708
    int prevOvl;
 
709
 
 
710
    assert(newOverlapLength >= 0);
 
711
    prevOvl = overlapLength;
 
712
    overlapLength = newOverlapLength;
 
713
 
 
714
    if (overlapLength > prevOvl)
 
715
    {
 
716
        delete[] pMidBuffer;
 
717
        delete[] pRefMidBufferUnaligned;
 
718
 
 
719
        pMidBuffer = new SAMPLETYPE[overlapLength * 2];
 
720
        clearMidBuffer();
 
721
 
 
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);
 
725
    }
 
726
}
 
727
 
 
728
 
 
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)
 
732
{
 
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!");
 
735
    return NULL;
 
736
}
 
737
 
 
738
 
 
739
TDStretch * TDStretch::newInstance()
 
740
{
 
741
    uint uExtensions;
 
742
 
 
743
    uExtensions = detectCPUextensions();
 
744
 
 
745
    // Check if MMX/SSE instruction set extensions supported by CPU
 
746
 
 
747
#ifdef SOUNDTOUCH_ALLOW_MMX
 
748
    // MMX routines available only with integer sample types
 
749
    if (uExtensions & SUPPORT_MMX)
 
750
    {
 
751
        return ::new TDStretchMMX;
 
752
    }
 
753
    else
 
754
#endif // SOUNDTOUCH_ALLOW_MMX
 
755
 
 
756
 
 
757
#ifdef SOUNDTOUCH_ALLOW_SSE
 
758
    if (uExtensions & SUPPORT_SSE)
 
759
    {
 
760
        // SSE support
 
761
        return ::new TDStretchSSE;
 
762
    }
 
763
    else
 
764
#endif // SOUNDTOUCH_ALLOW_SSE
 
765
 
 
766
    {
 
767
        // ISA optimizations not supported, use plain C version
 
768
        return ::new TDStretch;
 
769
    }
 
770
}
 
771
 
 
772
 
 
773
//////////////////////////////////////////////////////////////////////////////
 
774
//
 
775
// Integer arithmetics specific algorithm implementations.
 
776
//
 
777
//////////////////////////////////////////////////////////////////////////////
 
778
 
 
779
#ifdef SOUNDTOUCH_INTEGER_SAMPLES
 
780
 
 
781
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
 
782
// is faster to calculate
 
783
void TDStretch::precalcCorrReferenceStereo()
 
784
{
 
785
    int i, cnt2;
 
786
    int temp, temp2;
 
787
 
 
788
    for (i=0 ; i < (int)overlapLength ;i ++) 
 
789
    {
 
790
        temp = i * (overlapLength - i);
 
791
        cnt2 = i * 2;
 
792
 
 
793
        temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
 
794
        pRefMidBuffer[cnt2] = (short)(temp2);
 
795
        temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
 
796
        pRefMidBuffer[cnt2 + 1] = (short)(temp2);
 
797
    }
 
798
}
 
799
 
 
800
 
 
801
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
 
802
// is faster to calculate
 
803
void TDStretch::precalcCorrReferenceMono()
 
804
{
 
805
    int i;
 
806
    long temp;
 
807
    long temp2;
 
808
 
 
809
    for (i=0 ; i < (int)overlapLength ;i ++) 
 
810
    {
 
811
        temp = i * (overlapLength - i);
 
812
        temp2 = (pMidBuffer[i] * temp) / slopingDivider;
 
813
        pRefMidBuffer[i] = (short)temp2;
 
814
    }
 
815
}
 
816
 
 
817
 
 
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
 
821
{
 
822
    int i;
 
823
    short temp;
 
824
    int cnt2;
 
825
 
 
826
    for (i = 0; i < overlapLength ; i ++) 
 
827
    {
 
828
        temp = (short)(overlapLength - i);
 
829
        cnt2 = 2 * i;
 
830
        poutput[cnt2] = (input[cnt2] * i + pMidBuffer[cnt2] * temp )  / overlapLength;
 
831
        poutput[cnt2 + 1] = (input[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength;
 
832
    }
 
833
}
 
834
 
 
835
// Calculates the x having the closest 2^x value for the given value
 
836
static int _getClosest2Power(double value)
 
837
{
 
838
    return (int)(log(value) / log(2.0) + 0.5);
 
839
}
 
840
 
 
841
 
 
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)
 
846
{
 
847
    int newOvl;
 
848
 
 
849
    assert(aoverlapMs >= 0);
 
850
 
 
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
 
858
 
 
859
    acceptNewOverlapLength(newOvl);
 
860
 
 
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;
 
865
}
 
866
 
 
867
 
 
868
long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
 
869
{
 
870
    long corr;
 
871
    long norm;
 
872
    int i;
 
873
 
 
874
    corr = norm = 0;
 
875
    for (i = 1; i < overlapLength; i ++) 
 
876
    {
 
877
        corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
 
878
        norm += (mixingPos[i] * mixingPos[i]) >> overlapDividerBits;
 
879
    }
 
880
 
 
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));
 
885
}
 
886
 
 
887
 
 
888
long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
 
889
{
 
890
    long corr;
 
891
    long norm;
 
892
    int i;
 
893
 
 
894
    corr = norm = 0;
 
895
    for (i = 2; i < 2 * overlapLength; i += 2) 
 
896
    {
 
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;
 
900
    }
 
901
 
 
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));
 
906
}
 
907
 
 
908
#endif // SOUNDTOUCH_INTEGER_SAMPLES
 
909
 
 
910
//////////////////////////////////////////////////////////////////////////////
 
911
//
 
912
// Floating point arithmetics specific algorithm implementations.
 
913
//
 
914
 
 
915
#ifdef SOUNDTOUCH_FLOAT_SAMPLES
 
916
 
 
917
 
 
918
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
 
919
// is faster to calculate
 
920
void TDStretch::precalcCorrReferenceStereo()
 
921
{
 
922
    int i, cnt2;
 
923
    float temp;
 
924
 
 
925
    for (i=0 ; i < (int)overlapLength ;i ++) 
 
926
    {
 
927
        temp = (float)i * (float)(overlapLength - i);
 
928
        cnt2 = i * 2;
 
929
        pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);
 
930
        pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);
 
931
    }
 
932
}
 
933
 
 
934
 
 
935
// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
 
936
// is faster to calculate
 
937
void TDStretch::precalcCorrReferenceMono()
 
938
{
 
939
    int i;
 
940
    float temp;
 
941
 
 
942
    for (i=0 ; i < (int)overlapLength ;i ++) 
 
943
    {
 
944
        temp = (float)i * (float)(overlapLength - i);
 
945
        pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
 
946
    }
 
947
}
 
948
 
 
949
 
 
950
// Overlaps samples in 'midBuffer' with the samples in 'pInput'
 
951
void TDStretch::overlapStereo(float *pOutput, const float *pInput) const
 
952
{
 
953
    int i;
 
954
    int cnt2;
 
955
    float fTemp;
 
956
    float fScale;
 
957
    float fi;
 
958
 
 
959
    fScale = 1.0f / (float)overlapLength;
 
960
 
 
961
    for (i = 0; i < (int)overlapLength ; i ++) 
 
962
    {
 
963
        fTemp = (float)(overlapLength - i) * fScale;
 
964
        fi = (float)i * fScale;
 
965
        cnt2 = 2 * i;
 
966
        pOutput[cnt2 + 0] = pInput[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;
 
967
        pOutput[cnt2 + 1] = pInput[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;
 
968
    }
 
969
}
 
970
 
 
971
 
 
972
/// Calculates overlapInMsec period length in samples.
 
973
void TDStretch::calculateOverlapLength(int overlapInMsec)
 
974
{
 
975
    int newOvl;
 
976
 
 
977
    assert(overlapInMsec >= 0);
 
978
    newOvl = (sampleRate * overlapInMsec) / 1000;
 
979
    if (newOvl < 16) newOvl = 16;
 
980
 
 
981
    // must be divisible by 8
 
982
    newOvl -= newOvl % 8;
 
983
 
 
984
    acceptNewOverlapLength(newOvl);
 
985
}
 
986
 
 
987
 
 
988
 
 
989
double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
 
990
{
 
991
    double corr;
 
992
    double norm;
 
993
    int i;
 
994
 
 
995
    corr = norm = 0;
 
996
    for (i = 1; i < overlapLength; i ++) 
 
997
    {
 
998
        corr += mixingPos[i] * compare[i];
 
999
        norm += mixingPos[i] * mixingPos[i];
 
1000
    }
 
1001
 
 
1002
    if (norm < 1e-9) norm = 1.0;    // to avoid div by zero
 
1003
    return corr / sqrt(norm);
 
1004
}
 
1005
 
 
1006
 
 
1007
double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
 
1008
{
 
1009
    double corr;
 
1010
    double norm;
 
1011
    int i;
 
1012
 
 
1013
    corr = norm = 0;
 
1014
    for (i = 2; i < 2 * overlapLength; i += 2) 
 
1015
    {
 
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];
 
1020
    }
 
1021
 
 
1022
    if (norm < 1e-9) norm = 1.0;    // to avoid div by zero
 
1023
    return corr / sqrt(norm);
 
1024
}
 
1025
 
 
1026
#endif // SOUNDTOUCH_FLOAT_SAMPLES