Browse code

update for C++17 compliance, update to latest 2sf, add WINE cross-compile makefiles

Adam Higerd authored on 2021/02/11 15:36:17
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,638 +0,0 @@
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: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $
17
-// File revision : $Revision: 1.12 $
18
-//
19
-// $Id: TDStretch.cpp 160 2012-11-08 18:53:01Z 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 "XSFCommon.h"
45
-
46
-#include <stdexcept>
47
-#include <limits>
48
-#include <cstring>
49
-#include <cstdlib>
50
-#include <cassert>
51
-#include "STTypes.h"
52
-#include "cpu_detect.h"
53
-#include "TDStretch.h"
54
-
55
-using namespace soundtouch;
56
-
57
-/*****************************************************************************
58
- *
59
- * Constant definitions
60
- *
61
- *****************************************************************************/
62
-
63
-// Table for the hierarchical mixing position seeking algorithm
64
-static const short _scanOffsets[][24] =
65
-{
66
-	{ 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806, 868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0 },
67
-	{-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
68
-	{ -20, -15, -10,  -5, 5, 10, 15, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
69
-	{ -4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
70
-	{ 121, 114, 97, 114, 98, 105, 108, 32, 104, 99, 117, 111, 116, 100, 110, 117, 111, 115, 0, 0, 0, 0, 0, 0 }
71
-};
72
-
73
-/*****************************************************************************
74
- *
75
- * Implementation of the class 'TDStretch'
76
- *
77
- *****************************************************************************/
78
-
79
-
80
-TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
81
-{
82
-	this->bQuickSeek = false;
83
-	this->channels = 2;
84
-
85
-	this->pMidBuffer = nullptr;
86
-	this->pMidBufferUnaligned.reset();
87
-	this->overlapLength = 0;
88
-
89
-	this->bAutoSeqSetting = true;
90
-	this->bAutoSeekSetting = true;
91
-
92
-	//this->outDebt = 0;
93
-	this->skipFract = 0;
94
-
95
-	this->tempo = 1.0f;
96
-	this->setParameters(48000, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
97
-	this->setTempo(1.0f);
98
-
99
-	this->clear();
100
-}
101
-
102
-TDStretch::~TDStretch()
103
-{
104
-}
105
-
106
-// Sets routine control parameters. These control are certain time constants
107
-// defining how the sound is stretched to the desired duration.
108
-//
109
-// 'sampleRate' = sample rate of the sound
110
-// 'sequenceMS' = one processing sequence length in milliseconds (default = 82 ms)
111
-// 'seekwindowMS' = seeking window length for scanning the best overlapping
112
-//      position (default = 28 ms)
113
-// 'overlapMS' = overlapping length (default = 12 ms)
114
-
115
-void TDStretch::setParameters(int32_t aSampleRate, int32_t aSequenceMS, int32_t aSeekWindowMS, int32_t aOverlapMS)
116
-{
117
-	// accept only positive parameter values - if zero or negative, use old values instead
118
-	if (aSampleRate > 0)
119
-		this->sampleRate = aSampleRate;
120
-	if (aOverlapMS > 0)
121
-		this->overlapMs = aOverlapMS;
122
-
123
-	if (aSequenceMS > 0)
124
-	{
125
-		this->sequenceMs = aSequenceMS;
126
-		this->bAutoSeqSetting = false;
127
-	}
128
-	else if (!aSequenceMS)
129
-		// if zero, use automatic setting
130
-		this->bAutoSeqSetting = true;
131
-
132
-	if (aSeekWindowMS > 0)
133
-	{
134
-		this->seekWindowMs = aSeekWindowMS;
135
-		this->bAutoSeekSetting = false;
136
-	}
137
-	else if (!aSeekWindowMS)
138
-		// if zero, use automatic setting
139
-		this->bAutoSeekSetting = true;
140
-
141
-	this->calcSeqParameters();
142
-
143
-	this->calculateOverlapLength(this->overlapMs);
144
-
145
-	// set tempo to recalculate 'sampleReq'
146
-	this->setTempo(this->tempo);
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(int32_t *pSampleRate, int32_t *pSequenceMs, int32_t *pSeekWindowMs, int32_t *pOverlapMs)
153
-{
154
-	if (pSampleRate)
155
-		*pSampleRate = this->sampleRate;
156
-
157
-	if (pSequenceMs)
158
-		*pSequenceMs = this->bAutoSeqSetting ? USE_AUTO_SEQUENCE_LEN : sequenceMs;
159
-
160
-	if (pSeekWindowMs)
161
-		*pSeekWindowMs = this->bAutoSeekSetting ? USE_AUTO_SEEKWINDOW_LEN : seekWindowMs;
162
-
163
-	if (pOverlapMs)
164
-		*pOverlapMs = this->overlapMs;
165
-}
166
-
167
-// Overlaps samples in 'midBuffer' with the samples in 'pInput'
168
-void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const
169
-{
170
-	SAMPLETYPE m1 = 0;
171
-	SAMPLETYPE m2 = static_cast<SAMPLETYPE>(this->overlapLength);
172
-
173
-	for (int32_t i = 0; i < this->overlapLength; ++i)
174
-	{
175
-		pOutput[i] = (pInput[i] * m1 + this->pMidBuffer[i] * m2) / this->overlapLength;
176
-		++m1;
177
-		--m2;
178
-	}
179
-}
180
-
181
-void TDStretch::clearMidBuffer()
182
-{
183
-	memset(this->pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * this->overlapLength);
184
-}
185
-
186
-void TDStretch::clearInput()
187
-{
188
-	this->inputBuffer.clear();
189
-	this->clearMidBuffer();
190
-}
191
-
192
-// Clears the sample buffers
193
-void TDStretch::clear()
194
-{
195
-	this->outputBuffer.clear();
196
-	this->clearInput();
197
-}
198
-
199
-// Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
200
-// to enable
201
-void TDStretch::enableQuickSeek(bool enable)
202
-{
203
-	this->bQuickSeek = enable;
204
-}
205
-
206
-// Seeks for the optimal overlap-mixing position.
207
-int32_t TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
208
-{
209
-	if (this->bQuickSeek)
210
-		return this->seekBestOverlapPositionQuick(refPos);
211
-	else
212
-		return this->seekBestOverlapPositionFull(refPos);
213
-}
214
-
215
-// Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position
216
-// of 'ovlPos'.
217
-void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint32_t ovlPos) const
218
-{
219
-	if (this->channels == 2)
220
-		// stereo sound
221
-		this->overlapStereo(pOutput, pInput + 2 * ovlPos);
222
-	else
223
-		// mono sound.
224
-		this->overlapMono(pOutput, pInput + ovlPos);
225
-}
226
-
227
-// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
228
-// routine
229
-//
230
-// The best position is determined as the position where the two overlapped
231
-// sample sequences are 'most alike', in terms of the highest cross-correlation
232
-// value over the overlapping period
233
-int32_t TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
234
-{
235
-	double bestCorr = std::numeric_limits<float>::min();
236
-	int32_t bestOffs = 0;
237
-
238
-	// Scans for the best correlation value by testing each possible position
239
-	// over the permitted range.
240
-	for (int32_t i = 0; i < this->seekLength; ++i)
241
-	{
242
-		// Calculates correlation value for the mixing position corresponding
243
-		// to 'i'
244
-		double corr = this->calcCrossCorr(refPos + this->channels * i, this->pMidBuffer);
245
-		// heuristic rule to slightly favour values close to mid of the range
246
-		double tmp = (2.0 * i - this->seekLength) / this->seekLength;
247
-		corr = (corr + 0.1) * (1.0 - 0.25 * tmp * tmp);
248
-
249
-		// Checks for the highest correlation value
250
-		if (corr > bestCorr)
251
-		{
252
-			bestCorr = corr;
253
-			bestOffs = i;
254
-		}
255
-	}
256
-	// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
257
-	this->clearCrossCorrState();
258
-
259
-	return bestOffs;
260
-}
261
-
262
-// Seeks for the optimal overlap-mixing position. The 'stereo' version of the
263
-// routine
264
-//
265
-// The best position is determined as the position where the two overlapped
266
-// sample sequences are 'most alike', in terms of the highest cross-correlation
267
-// value over the overlapping period
268
-int32_t TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
269
-{
270
-	double bestCorr = std::numeric_limits<float>::min();
271
-	int32_t bestOffs = _scanOffsets[0][0], corrOffset = 0;
272
-
273
-	// Scans for the best correlation value using four-pass hierarchical search.
274
-	//
275
-	// The look-up table 'scans' has hierarchical position adjusting steps.
276
-	// In first pass the routine searhes for the highest correlation with
277
-	// relatively coarse steps, then rescans the neighbourhood of the highest
278
-	// correlation with better resolution and so on.
279
-	for (uint32_t scanCount = 0; scanCount < 4; ++scanCount)
280
-	{
281
-		int32_t j = 0;
282
-		while (_scanOffsets[scanCount][j])
283
-		{
284
-			int32_t tempOffset = corrOffset + _scanOffsets[scanCount][j];
285
-			if (tempOffset >= this->seekLength)
286
-				break;
287
-
288
-			// Calculates correlation value for the mixing position corresponding
289
-			// to 'tempOffset'
290
-			double corr = this->calcCrossCorr(refPos + this->channels * tempOffset, this->pMidBuffer);
291
-			// heuristic rule to slightly favour values close to mid of the range
292
-			double tmp = (2.0 * tempOffset - this->seekLength) / seekLength;
293
-			corr = (corr + 0.1) * (1.0 - 0.25 * tmp * tmp);
294
-
295
-			// Checks for the highest correlation value
296
-			if (corr > bestCorr)
297
-			{
298
-				bestCorr = corr;
299
-				bestOffs = tempOffset;
300
-			}
301
-			++j;
302
-		}
303
-		corrOffset = bestOffs;
304
-	}
305
-	// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
306
-	this->clearCrossCorrState();
307
-
308
-	return bestOffs;
309
-}
310
-
311
-/// clear cross correlation routine state if necessary
312
-void TDStretch::clearCrossCorrState()
313
-{
314
-	// default implementation is empty.
315
-}
316
-
317
-/// Calculates processing sequence length according to tempo setting
318
-void TDStretch::calcSeqParameters()
319
-{
320
-	// Adjust tempo param according to tempo, so that variating processing sequence length is used
321
-	// at varius tempo settings, between the given low...top limits
322
-	static const double AUTOSEQ_TEMPO_LOW = 0.5; // auto setting low tempo range (-50%)
323
-	static const double AUTOSEQ_TEMPO_TOP = 2.0; // auto setting top tempo range (+100%)
324
-
325
-	// sequence-ms setting values at above low & top tempo
326
-	static const double AUTOSEQ_AT_MIN = 125.0;
327
-	static const double AUTOSEQ_AT_MAX = 50.0;
328
-	static const double AUTOSEQ_K = (AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW);
329
-	static const double AUTOSEQ_C = AUTOSEQ_AT_MIN - AUTOSEQ_K * AUTOSEQ_TEMPO_LOW;
330
-
331
-	// seek-window-ms setting values at above low & top tempo
332
-	static const double AUTOSEEK_AT_MIN = 25.0;
333
-	static const double AUTOSEEK_AT_MAX = 15.0;
334
-	static const double AUTOSEEK_K = (AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW);
335
-	static const double AUTOSEEK_C = AUTOSEEK_AT_MIN - AUTOSEEK_K * AUTOSEQ_TEMPO_LOW;
336
-
337
-	auto CHECK_LIMITS = [](double x, double mi, double ma) { return x < mi ? mi : (x > ma ? ma : x); };
338
-
339
-	if (this->bAutoSeqSetting)
340
-	{
341
-		double seq = AUTOSEQ_C + AUTOSEQ_K * this->tempo;
342
-		seq = CHECK_LIMITS(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN);
343
-		this->sequenceMs = static_cast<int>(seq + 0.5);
344
-	}
345
-
346
-	if (this->bAutoSeekSetting)
347
-	{
348
-		double seek = AUTOSEEK_C + AUTOSEEK_K * this->tempo;
349
-		seek = CHECK_LIMITS(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN);
350
-		this->seekWindowMs = static_cast<int>(seek + 0.5);
351
-    }
352
-
353
-	// Update seek window lengths
354
-	this->seekWindowLength = (this->sampleRate * this->sequenceMs) / 1000;
355
-	if (this->seekWindowLength < 2 * this->overlapLength)
356
-		this->seekWindowLength = 2 * this->overlapLength;
357
-	this->seekLength = (this->sampleRate * this->seekWindowMs) / 1000;
358
-}
359
-
360
-// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
361
-// tempo, larger faster tempo.
362
-void TDStretch::setTempo(float newTempo)
363
-{
364
-	this->tempo = newTempo;
365
-
366
-	// Calculate new sequence duration
367
-	this->calcSeqParameters();
368
-
369
-	// Calculate ideal skip length (according to tempo value)
370
-	this->nominalSkip = this->tempo * (this->seekWindowLength - this->overlapLength);
371
-	int intskip = static_cast<int>(nominalSkip + 0.5f);
372
-
373
-	// Calculate how many samples are needed in the 'inputBuffer' to
374
-	// process another batch of samples
375
-	this->sampleReq = std::max(intskip + this->overlapLength, this->seekWindowLength) + this->seekLength;
376
-}
377
-
378
-// Sets the number of channels, 1 = mono, 2 = stereo
379
-void TDStretch::setChannels(int32_t numChannels)
380
-{
381
-	assert(numChannels > 0);
382
-	if (this->channels == numChannels)
383
-		return;
384
-	assert(numChannels == 1 || numChannels == 2);
385
-
386
-	this->channels = numChannels;
387
-	this->inputBuffer.setChannels(channels);
388
-	this->outputBuffer.setChannels(channels);
389
-}
390
-
391
-// Processes as many processing frames of the samples 'inputBuffer', store
392
-// the result into 'outputBuffer'
393
-void TDStretch::processSamples()
394
-{
395
-	/* Removed this small optimization - can introduce a click to sound when tempo setting
396
-	   crosses the nominal value
397
-	if (this->tempo == 1.0f)
398
-	{
399
-		// tempo not changed from the original, so bypass the processing
400
-		this->processNominalTempo();
401
-		return;
402
-	}*/
403
-
404
-	// Process samples as long as there are enough samples in 'inputBuffer'
405
-	// to form a processing frame.
406
-	while (static_cast<int32_t>(this->inputBuffer.numSamples()) >= this->sampleReq)
407
-	{
408
-		// If tempo differs from the normal ('SCALE'), scan for the best overlapping
409
-		// position
410
-		int32_t offset = this->seekBestOverlapPosition(this->inputBuffer.ptrBegin());
411
-
412
-		// Mix the samples in the 'inputBuffer' at position of 'offset' with the
413
-		// samples in 'midBuffer' using sliding overlapping
414
-		// ... first partially overlap with the end of the previous sequence
415
-		// (that's in 'midBuffer')
416
-		this->overlap(this->outputBuffer.ptrEnd(this->overlapLength), this->inputBuffer.ptrBegin(), offset);
417
-		this->outputBuffer.putSamples(this->overlapLength);
418
-
419
-		// ... then copy sequence samples from 'inputBuffer' to output:
420
-
421
-		// length of sequence
422
-		int temp = this->seekWindowLength - 2 * this->overlapLength;
423
-
424
-		// crosscheck that we don't have buffer overflow...
425
-		if (static_cast<int32_t>(inputBuffer.numSamples()) < offset + temp + this->overlapLength * 2)
426
-			continue; // just in case, shouldn't really happen
427
-
428
-		this->outputBuffer.putSamples(this->inputBuffer.ptrBegin() + this->channels * (offset + this->overlapLength), temp);
429
-
430
-		// Copies the end of the current sequence from 'inputBuffer' to
431
-		// 'midBuffer' for being mixed with the beginning of the next
432
-		// processing sequence and so on
433
-		assert(offset + temp + this->overlapLength * 2 <= static_cast<int32_t>(this->inputBuffer.numSamples()));
434
-		memcpy(this->pMidBuffer, this->inputBuffer.ptrBegin() + this->channels * (offset + this->seekWindowLength - this->overlapLength), this->channels * sizeof(SAMPLETYPE) * this->overlapLength);
435
-
436
-		// Remove the processed samples from the input buffer. Update
437
-		// the difference between integer & nominal skip step to 'skipFract'
438
-		// in order to prevent the error from accumulating over time.
439
-		this->skipFract += this->nominalSkip; // real skip size
440
-		int ovlSkip = static_cast<int>(skipFract); // rounded to integer skip
441
-		this->skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip
442
-		this->inputBuffer.receiveSamples(ovlSkip);
443
-	}
444
-}
445
-
446
-// Adds 'numsamples' pcs of samples from the 'samples' memory position into
447
-// the input of the object.
448
-void TDStretch::putSamples(const SAMPLETYPE *samples, uint32_t nSamples)
449
-{
450
-	// Add the samples into the input buffer
451
-	this->inputBuffer.putSamples(samples, nSamples);
452
-	// Process the samples in input buffer
453
-	this->processSamples();
454
-}
455
-
456
-/// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
457
-void TDStretch::acceptNewOverlapLength(int32_t newOverlapLength)
458
-{
459
-	assert(newOverlapLength >= 0);
460
-	int32_t prevOvl = this->overlapLength;
461
-	this->overlapLength = newOverlapLength;
462
-
463
-	if (this->overlapLength > prevOvl)
464
-	{
465
-		this->pMidBufferUnaligned.reset(new SAMPLETYPE[this->overlapLength * 2 + 16 / sizeof(SAMPLETYPE)]);
466
-		// ensure that 'pMidBuffer' is aligned to 16 byte boundary for efficiency
467
-		this->pMidBuffer = reinterpret_cast<SAMPLETYPE *>(SOUNDTOUCH_ALIGN_POINTER_16(this->pMidBufferUnaligned.get()));
468
-
469
-		this->clearMidBuffer();
470
-	}
471
-}
472
-
473
-// Operator 'new' is overloaded so that it automatically creates a suitable instance
474
-// depending on if we've a MMX/SSE/etc-capable CPU available or not.
475
-void *TDStretch::operator new(size_t /*s*/)
476
-{
477
-	// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
478
-	//assert(false);
479
-	//return NULL;
480
-	throw std::runtime_error("Don't use 'new TDStretch', use 'newInstance' member instead!");
481
-}
482
-
483
-TDStretch *TDStretch::newInstance()
484
-{
485
-	uint32_t uExtensions = detectCPUextensions();
486
-
487
-	// Check if MMX/SSE instruction set extensions supported by CPU
488
-
489
-#ifdef SOUNDTOUCH_ALLOW_MMX
490
-	// MMX routines available only with integer sample types
491
-	if (uExtensions & SUPPORT_MMX)
492
-		return ::new TDStretchMMX;
493
-	else
494
-#endif // SOUNDTOUCH_ALLOW_MMX
495
-#ifdef SOUNDTOUCH_ALLOW_SSE
496
-	if (uExtensions & SUPPORT_SSE)
497
-		// SSE support
498
-		return ::new TDStretchSSE;
499
-	else
500
-#endif //  SOUNDTOUCH_ALLOW_SSE
501
-		// ISA optimizations not supported, use plain C version
502
-		return ::new TDStretch;
503
-}
504
-
505
-//////////////////////////////////////////////////////////////////////////////
506
-//
507
-// Integer arithmetics specific algorithm implementations.
508
-//
509
-//////////////////////////////////////////////////////////////////////////////
510
-
511
-#ifdef SOUNDTOUCH_INTEGER_SAMPLES
512
-
513
-// Overlaps samples in 'midBuffer' with the samples in 'pinput'. The 'Stereo'
514
-// version of the routine.
515
-void TDStretch::overlapStereo(short *poutput, const short *pinput) const
516
-{
517
-	for (int32_t i = 0; i < this->overlapLength; ++i)
518
-	{
519
-		short temp = this->overlapLength - i;
520
-		int32_t cnt2 = 2 * i;
521
-		poutput[cnt2] = (pinput[cnt2] * i + this->pMidBuffer[cnt2] * temp) / this->overlapLength;
522
-		poutput[cnt2 + 1] = (pinput[cnt2 + 1] * i + this->pMidBuffer[cnt2 + 1] * temp) / this->overlapLength;
523
-	}
524
-}
525
-
526
-// Calculates the x having the closest 2^x value for the given value
527
-static int _getClosest2Power(double value)
528
-{
529
-	return static_cast<int>(std::log(value) / std::log(2.0) + 0.5);
530
-}
531
-
532
-/// Calculates overlap period length in samples.
533
-/// Integer version rounds overlap length to closest power of 2
534
-/// for a divide scaling operation.
535
-void TDStretch::calculateOverlapLength(int32_t aoverlapMs)
536
-{
537
-	assert(aoverlapMs >= 0);
538
-
539
-	// calculate overlap length so that it's power of 2 - thus it's easy to do
540
-	// integer division by right-shifting. Term "-1" at end is to account for
541
-	// the extra most significatnt bit left unused in result by signed multiplication
542
-	this->overlapDividerBits = _getClosest2Power((this->sampleRate * aoverlapMs) / 1000.0) - 1;
543
-	if (this->overlapDividerBits > 9)
544
-		this->overlapDividerBits = 9;
545
-	if (this->overlapDividerBits < 3)
546
-		this->overlapDividerBits = 3;
547
-	int32_t newOvl = static_cast<int32_t>(std::pow(2, this->overlapDividerBits + 1)); // +1 => account for -1 above
548
-
549
-	this->acceptNewOverlapLength(newOvl);
550
-
551
-	// calculate sloping divider so that crosscorrelation operation won't
552
-	// overflow 32-bit register. Max. sum of the crosscorrelation sum without
553
-	// divider would be 2^30*(N^3-N)/3, where N = overlap length
554
-	this->slopingDivider = (newOvl * newOvl - 1) / 3;
555
-}
556
-
557
-double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare) const
558
-{
559
-	long corr = 0, norm = 0;
560
-	// Same routine for stereo and mono. For stereo, unroll loop for better
561
-	// efficiency and gives slightly better resolution against rounding.
562
-	// For mono it same routine, just  unrolls loop by factor of 4
563
-	for (int32_t i = 0; i < this->overlapLength; i += 4)
564
-	{
565
-		corr += (mixingPos[i] * compare[i] + mixingPos[i + 1] * compare[i + 1] + mixingPos[i + 2] * compare[i + 2] + mixingPos[i + 3] * compare[i + 3]) >> this->overlapDividerBits;
566
-		norm += (mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1] + mixingPos[i + 2] * mixingPos[i + 2] + mixingPos[i + 3] * mixingPos[i + 3]) >> this->overlapDividerBits;
567
-	}
568
-
569
-	// Normalize result by dividing by sqrt(norm) - this step is easiest
570
-	// done using floating point operation
571
-	if (!norm)
572
-		norm = 1; // to avoid div by zero
573
-	return corr / std::sqrt(static_cast<double>(norm));
574
-}
575
-
576
-#endif // SOUNDTOUCH_INTEGER_SAMPLES
577
-
578
-//////////////////////////////////////////////////////////////////////////////
579
-//
580
-// Floating point arithmetics specific algorithm implementations.
581
-//
582
-
583
-#ifdef SOUNDTOUCH_FLOAT_SAMPLES
584
-
585
-// Overlaps samples in 'midBuffer' with the samples in 'pInput'
586
-void TDStretch::overlapStereo(float *pOutput, const float *pInput) const
587
-{
588
-	float fScale = 1.0f / this->overlapLength;
589
-
590
-	float f1 = 0, f2 = 1.0f;
591
-
592
-	for (int32_t i = 0; i < 2 * this->overlapLength; i += 2)
593
-	{
594
-		pOutput[i] = pInput[i] * f1 + this->pMidBuffer[i] * f2;
595
-		pOutput[i + 1] = pInput[i + 1] * f1 + this->pMidBuffer[i + 1] * f2;
596
-
597
-		f1 += fScale;
598
-		f2 -= fScale;
599
-	}
600
-}
601
-
602
-/// Calculates overlapInMsec period length in samples.
603
-void TDStretch::calculateOverlapLength(int32_t overlapInMsec)
604
-{
605
-	assert(overlapInMsec >= 0);
606
-	uint32_t newOvl = (this->sampleRate * overlapInMsec) / 1000;
607
-	if (newOvl < 16)
608
-		newOvl = 16;
609
-
610
-	// must be divisible by 8
611
-	newOvl -= newOvl % 8;
612
-
613
-	this->acceptNewOverlapLength(newOvl);
614
-}
615
-
616
-double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare) const
617
-{
618
-	double corr = 0, norm = 0;
619
-	// Same routine for stereo and mono. For Stereo, unroll by factor of 2.
620
-	// For mono it's same routine yet unrollsd by factor of 4.
621
-	for (int32_t i = 0; i < this->channels * this->overlapLength; i += 4)
622
-	{
623
-		corr += mixingPos[i] * compare[i] + mixingPos[i + 1] * compare[i + 1];
624
-
625
-		norm += mixingPos[i] * mixingPos[i] +  mixingPos[i + 1] * mixingPos[i + 1];
626
-
627
-		// unroll the loop for better CPU efficiency:
628
-		corr += mixingPos[i + 2] * compare[i + 2] + mixingPos[i + 3] * compare[i + 3];
629
-
630
-		norm += mixingPos[i + 2] * mixingPos[i + 2] + mixingPos[i + 3] * mixingPos[i + 3];
631
-	}
632
-
633
-	if (norm < 1e-9)
634
-		norm = 1.0; // to avoid div by zero
635
-	return corr / std::sqrt(norm);
636
-}
637
-
638
-#endif // SOUNDTOUCH_FLOAT_SAMPLES
Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
... ...
@@ -44,9 +44,9 @@
44 44
 #include "XSFCommon.h"
45 45
 
46 46
 #include <stdexcept>
47
+#include <limits>
47 48
 #include <cstring>
48 49
 #include <cstdlib>
49
-#include <climits>
50 50
 #include <cassert>
51 51
 #include "STTypes.h"
52 52
 #include "cpu_detect.h"
... ...
@@ -129,7 +129,7 @@ void TDStretch::setParameters(int32_t aSampleRate, int32_t aSequenceMS, int32_t
129 129
 		// if zero, use automatic setting
130 130
 		this->bAutoSeqSetting = true;
131 131
 
132
-	if (aSeekWindowMS > 0) 
132
+	if (aSeekWindowMS > 0)
133 133
 	{
134 134
 		this->seekWindowMs = aSeekWindowMS;
135 135
 		this->bAutoSeekSetting = false;
... ...
@@ -232,7 +232,7 @@ void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint32_t
232 232
 // value over the overlapping period
233 233
 int32_t TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
234 234
 {
235
-	double bestCorr = FLT_MIN;
235
+	double bestCorr = std::numeric_limits<float>::min();
236 236
 	int32_t bestOffs = 0;
237 237
 
238 238
 	// Scans for the best correlation value by testing each possible position
... ...
@@ -267,7 +267,7 @@ int32_t TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
267 267
 // value over the overlapping period
268 268
 int32_t TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
269 269
 {
270
-	double bestCorr = FLT_MIN;
270
+	double bestCorr = std::numeric_limits<float>::min();
271 271
 	int32_t bestOffs = _scanOffsets[0][0], corrOffset = 0;
272 272
 
273 273
 	// Scans for the best correlation value using four-pass hierarchical search.
... ...
@@ -308,7 +308,7 @@ int32_t TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
308 308
 	return bestOffs;
309 309
 }
310 310
 
311
-/// clear cross correlation routine state if necessary 
311
+/// clear cross correlation routine state if necessary
312 312
 void TDStretch::clearCrossCorrState()
313 313
 {
314 314
 	// default implementation is empty.
... ...
@@ -352,7 +352,7 @@ void TDStretch::calcSeqParameters()
352 352
 
353 353
 	// Update seek window lengths
354 354
 	this->seekWindowLength = (this->sampleRate * this->sequenceMs) / 1000;
355
-	if (this->seekWindowLength < 2 * this->overlapLength) 
355
+	if (this->seekWindowLength < 2 * this->overlapLength)
356 356
 		this->seekWindowLength = 2 * this->overlapLength;
357 357
 	this->seekLength = (this->sampleRate * this->seekWindowMs) / 1000;
358 358
 }
... ...
@@ -472,7 +472,7 @@ void TDStretch::acceptNewOverlapLength(int32_t newOverlapLength)
472 472
 
473 473
 // Operator 'new' is overloaded so that it automatically creates a suitable instance
474 474
 // depending on if we've a MMX/SSE/etc-capable CPU available or not.
475
-void *TDStretch::operator new(size_t s)
475
+void *TDStretch::operator new(size_t /*s*/)
476 476
 {
477 477
 	// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
478 478
 	//assert(false);
... ...
@@ -480,7 +480,7 @@ void *TDStretch::operator new(size_t s)
480 480
 	throw std::runtime_error("Don't use 'new TDStretch', use 'newInstance' member instead!");
481 481
 }
482 482
 
483
-TDStretch * TDStretch::newInstance()
483
+TDStretch *TDStretch::newInstance()
484 484
 {
485 485
 	uint32_t uExtensions = detectCPUextensions();
486 486
 
... ...
@@ -537,8 +537,8 @@ void TDStretch::calculateOverlapLength(int32_t aoverlapMs)
537 537
 	assert(aoverlapMs >= 0);
538 538
 
539 539
 	// calculate overlap length so that it's power of 2 - thus it's easy to do
540
-	// integer division by right-shifting. Term "-1" at end is to account for 
541
-	// the extra most significatnt bit left unused in result by signed multiplication 
540
+	// integer division by right-shifting. Term "-1" at end is to account for
541
+	// the extra most significatnt bit left unused in result by signed multiplication
542 542
 	this->overlapDividerBits = _getClosest2Power((this->sampleRate * aoverlapMs) / 1000.0) - 1;
543 543
 	if (this->overlapDividerBits > 9)
544 544
 		this->overlapDividerBits = 9;
... ...
@@ -558,7 +558,7 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare) co
558 558
 {
559 559
 	long corr = 0, norm = 0;
560 560
 	// Same routine for stereo and mono. For stereo, unroll loop for better
561
-	// efficiency and gives slightly better resolution against rounding. 
561
+	// efficiency and gives slightly better resolution against rounding.
562 562
 	// For mono it same routine, just  unrolls loop by factor of 4
563 563
 	for (int32_t i = 0; i < this->overlapLength; i += 4)
564 564
 	{
... ...
@@ -566,7 +566,7 @@ double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare) co
566 566
 		norm += (mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1] + mixingPos[i + 2] * mixingPos[i + 2] + mixingPos[i + 3] * mixingPos[i + 3]) >> this->overlapDividerBits;
567 567
 	}
568 568
 
569
-	// Normalize result by dividing by sqrt(norm) - this step is easiest 
569
+	// Normalize result by dividing by sqrt(norm) - this step is easiest
570 570
 	// done using floating point operation
571 571
 	if (!norm)
572 572
 		norm = 1; // to avoid div by zero
Browse code

Some more code cleanup in DeSmuME.

Naram Qashat authored on 2013/04/23 00:07:41
Showing 1 changed files
... ...
@@ -203,12 +203,6 @@ void TDStretch::enableQuickSeek(bool enable)
203 203
 	this->bQuickSeek = enable;
204 204
 }
205 205
 
206
-// Returns nonzero if the quick seeking algorithm is enabled.
207
-bool TDStretch::isQuickSeekEnabled() const
208
-{
209
-	return this->bQuickSeek;
210
-}
211
-
212 206
 // Seeks for the optimal overlap-mixing position.
213 207
 int32_t TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
214 208
 {
Browse code

Removed a bunch of casts, they seem to be fine without them in most cases.

Naram Qashat authored on 2013/04/18 23:22:54
Showing 1 changed files
... ...
@@ -167,7 +167,7 @@ void TDStretch::getParameters(int32_t *pSampleRate, int32_t *pSequenceMs, int32_
167 167
 // Overlaps samples in 'midBuffer' with the samples in 'pInput'
168 168
 void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const
169 169
 {
170
-	SAMPLETYPE m1 = static_cast<SAMPLETYPE>(0);
170
+	SAMPLETYPE m1 = 0;
171 171
 	SAMPLETYPE m2 = static_cast<SAMPLETYPE>(this->overlapLength);
172 172
 
173 173
 	for (int32_t i = 0; i < this->overlapLength; ++i)
... ...
@@ -249,7 +249,7 @@ int32_t TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
249 249
 		// to 'i'
250 250
 		double corr = this->calcCrossCorr(refPos + this->channels * i, this->pMidBuffer);
251 251
 		// heuristic rule to slightly favour values close to mid of the range
252
-		double tmp = static_cast<double>(2 * i - this->seekLength) / this->seekLength;
252
+		double tmp = (2.0 * i - this->seekLength) / this->seekLength;
253 253
 		corr = (corr + 0.1) * (1.0 - 0.25 * tmp * tmp);
254 254
 
255 255
 		// Checks for the highest correlation value
... ...
@@ -293,9 +293,9 @@ int32_t TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
293 293
 
294 294
 			// Calculates correlation value for the mixing position corresponding
295 295
 			// to 'tempOffset'
296
-			double corr = static_cast<double>(this->calcCrossCorr(refPos + this->channels * tempOffset, this->pMidBuffer));
296
+			double corr = this->calcCrossCorr(refPos + this->channels * tempOffset, this->pMidBuffer);
297 297
 			// heuristic rule to slightly favour values close to mid of the range
298
-			double tmp = static_cast<double>(2 * tempOffset - this->seekLength) / seekLength;
298
+			double tmp = (2.0 * tempOffset - this->seekLength) / seekLength;
299 299
 			corr = (corr + 0.1) * (1.0 - 0.25 * tmp * tmp);
300 300
 
301 301
 			// Checks for the highest correlation value
... ...
@@ -419,8 +419,8 @@ void TDStretch::processSamples()
419 419
 		// samples in 'midBuffer' using sliding overlapping
420 420
 		// ... first partially overlap with the end of the previous sequence
421 421
 		// (that's in 'midBuffer')
422
-		this->overlap(this->outputBuffer.ptrEnd(static_cast<uint32_t>(this->overlapLength)), this->inputBuffer.ptrBegin(), static_cast<uint32_t>(offset));
423
-		this->outputBuffer.putSamples(static_cast<uint32_t>(this->overlapLength));
422
+		this->overlap(this->outputBuffer.ptrEnd(this->overlapLength), this->inputBuffer.ptrBegin(), offset);
423
+		this->outputBuffer.putSamples(this->overlapLength);
424 424
 
425 425
 		// ... then copy sequence samples from 'inputBuffer' to output:
426 426
 
... ...
@@ -431,12 +431,12 @@ void TDStretch::processSamples()
431 431
 		if (static_cast<int32_t>(inputBuffer.numSamples()) < offset + temp + this->overlapLength * 2)
432 432
 			continue; // just in case, shouldn't really happen
433 433
 
434
-		this->outputBuffer.putSamples(this->inputBuffer.ptrBegin() + this->channels * (offset + this->overlapLength), static_cast<uint32_t>(temp));
434
+		this->outputBuffer.putSamples(this->inputBuffer.ptrBegin() + this->channels * (offset + this->overlapLength), temp);
435 435
 
436 436
 		// Copies the end of the current sequence from 'inputBuffer' to
437 437
 		// 'midBuffer' for being mixed with the beginning of the next
438 438
 		// processing sequence and so on
439
-		assert(offset + temp + this->overlapLength * 2 <= static_cast<int>(this->inputBuffer.numSamples()));
439
+		assert(offset + temp + this->overlapLength * 2 <= static_cast<int32_t>(this->inputBuffer.numSamples()));
440 440
 		memcpy(this->pMidBuffer, this->inputBuffer.ptrBegin() + this->channels * (offset + this->seekWindowLength - this->overlapLength), this->channels * sizeof(SAMPLETYPE) * this->overlapLength);
441 441
 
442 442
 		// Remove the processed samples from the input buffer. Update
... ...
@@ -445,7 +445,7 @@ void TDStretch::processSamples()
445 445
 		this->skipFract += this->nominalSkip; // real skip size
446 446
 		int ovlSkip = static_cast<int>(skipFract); // rounded to integer skip
447 447
 		this->skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip
448
-		this->inputBuffer.receiveSamples(static_cast<uint32_t>(ovlSkip));
448
+		this->inputBuffer.receiveSamples(ovlSkip);
449 449
 	}
450 450
 }
451 451
 
... ...
@@ -522,7 +522,7 @@ void TDStretch::overlapStereo(short *poutput, const short *pinput) const
522 522
 {
523 523
 	for (int32_t i = 0; i < this->overlapLength; ++i)
524 524
 	{
525
-		short temp = static_cast<short>(this->overlapLength - i);
525
+		short temp = this->overlapLength - i;
526 526
 		int32_t cnt2 = 2 * i;
527 527
 		poutput[cnt2] = (pinput[cnt2] * i + this->pMidBuffer[cnt2] * temp) / this->overlapLength;
528 528
 		poutput[cnt2 + 1] = (pinput[cnt2 + 1] * i + this->pMidBuffer[cnt2 + 1] * temp) / this->overlapLength;
... ...
@@ -550,7 +550,7 @@ void TDStretch::calculateOverlapLength(int32_t aoverlapMs)
550 550
 		this->overlapDividerBits = 9;
551 551
 	if (this->overlapDividerBits < 3)
552 552
 		this->overlapDividerBits = 3;
553
-	int32_t newOvl = static_cast<int>std::pow(2, static_cast<int>(this->overlapDividerBits) + 1); // +1 => account for -1 above
553
+	int32_t newOvl = static_cast<int32_t>(std::pow(2, this->overlapDividerBits + 1)); // +1 => account for -1 above
554 554
 
555 555
 	this->acceptNewOverlapLength(newOvl);
556 556
 
Browse code

Updating in_2sf to use a newish version of DeSmuME, 0.9.9 from SVN. Somewhat cleaned up as well, but not everything because it's a pain in the ass.

Naram Qashat authored on 2013/04/18 17:22:55
Showing 1 changed files
... ...
@@ -13,10 +13,10 @@
13 13
 ///
14 14
 ////////////////////////////////////////////////////////////////////////////////
15 15
 //
16
-// Last changed  : $Date: 2006/02/05 16:44:06 $
17
-// File revision : $Revision: 1.24 $
16
+// Last changed  : $Date: 2012-11-08 16:53:01 -0200 (qui, 08 nov 2012) $
17
+// File revision : $Revision: 1.12 $
18 18
 //
19
-// $Id: TDStretch.cpp,v 1.24 2006/02/05 16:44:06 Olli Exp $
19
+// $Id: TDStretch.cpp 160 2012-11-08 18:53:01Z oparviai $
20 20
 //
21 21
 ////////////////////////////////////////////////////////////////////////////////
22 22
 //
... ...
@@ -48,7 +48,6 @@
48 48
 #include <cstdlib>
49 49
 #include <climits>
50 50
 #include <cassert>
51
-
52 51
 #include "STTypes.h"
53 52
 #include "cpu_detect.h"
54 53
 #include "TDStretch.h"
... ...
@@ -61,17 +60,15 @@ using namespace soundtouch;
61 60
  *
62 61
  *****************************************************************************/
63 62
 
64
-
65 63
 // Table for the hierarchical mixing position seeking algorithm
66
-int scanOffsets[4][24]={
67
-    { 124,  186,  248,  310,  372,  434,  496,  558,  620,  682,  744, 806,
68
-      868,  930,  992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488,   0},
69
-    {-100,  -75,  -50,  -25,   25,   50,   75,  100,    0,    0,    0,   0,
70
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   0},
71
-    { -20,  -15,  -10,   -5,    5,   10,   15,   20,    0,    0,    0,   0,
72
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   0},
73
-    {  -4,   -3,   -2,   -1,    1,    2,    3,    4,    0,    0,    0,   0,
74
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   0}};
64
+static const short _scanOffsets[][24] =
65
+{
66
+	{ 124, 186, 248, 310, 372, 434, 496, 558, 620, 682, 744, 806, 868, 930, 992, 1054, 1116, 1178, 1240, 1302, 1364, 1426, 1488, 0 },
67
+	{-100, -75, -50, -25, 25, 50, 75, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
68
+	{ -20, -15, -10,  -5, 5, 10, 15, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
69
+	{ -4, -3, -2, -1, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
70
+	{ 121, 114, 97, 114, 98, 105, 108, 32, 104, 99, 117, 111, 116, 100, 110, 117, 111, 115, 0, 0, 0, 0, 0, 0 }
71
+};
75 72
 
76 73
 /*****************************************************************************
77 74
  *
... ...
@@ -82,40 +79,30 @@ int scanOffsets[4][24]={
82 79
 
83 80
 TDStretch::TDStretch() : FIFOProcessor(&outputBuffer)
84 81
 {
85
-    bQuickseek = false;
86
-    channels = 2;
87
-    bMidBufferDirty = false;
82
+	this->bQuickSeek = false;
83
+	this->channels = 2;
88 84
 
89
-    pMidBuffer = NULL;
90
-    pRefMidBufferUnaligned = NULL;
91
-    overlapLength = 0;
85
+	this->pMidBuffer = nullptr;
86
+	this->pMidBufferUnaligned.reset();
87
+	this->overlapLength = 0;
92 88
 
93
-    setParameters(48000, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
94
-
95
-    setTempo(1.0f);
96
-}
89
+	this->bAutoSeqSetting = true;
90
+	this->bAutoSeekSetting = true;
97 91
 
92
+	//this->outDebt = 0;
93
+	this->skipFract = 0;
98 94
 
95
+	this->tempo = 1.0f;
96
+	this->setParameters(48000, DEFAULT_SEQUENCE_MS, DEFAULT_SEEKWINDOW_MS, DEFAULT_OVERLAP_MS);
97
+	this->setTempo(1.0f);
99 98
 
100
-
101
-TDStretch::~TDStretch()
102
-{
103
-    delete[] pMidBuffer;
104
-    delete[] pRefMidBufferUnaligned;
99
+	this->clear();
105 100
 }
106 101
 
107
-
108
-
109
-// Calculates the x having the closest 2^x value for the given value
110
-#ifdef INTEGER_SAMPLES
111
-
112
-static int _getClosest2Power(double value)
102
+TDStretch::~TDStretch()
113 103
 {
114
-    return (int)(log(value) / log(2.0) + 0.5);
115 104
 }
116 105
 
117
-#endif
118
-
119 106
 // Sets routine control parameters. These control are certain time constants
120 107
 // defining how the sound is stretched to the desired duration.
121 108
 //
... ...
@@ -125,812 +112,533 @@ static int _getClosest2Power(double value)
125 112
 //      position (default = 28 ms)
126 113
 // 'overlapMS' = overlapping length (default = 12 ms)
127 114
 
128
-void TDStretch::setParameters(uint32_t aSampleRate, uint32_t aSequenceMS,
129
-                              uint32_t aSeekWindowMS, uint32_t aOverlapMS)
115
+void TDStretch::setParameters(int32_t aSampleRate, int32_t aSequenceMS, int32_t aSeekWindowMS, int32_t aOverlapMS)
130 116
 {
131
-    this->sampleRate = aSampleRate;
132
-    this->sequenceMs = aSequenceMS;
133
-    this->seekWindowMs = aSeekWindowMS;
134
-    this->overlapMs = aOverlapMS;
117
+	// accept only positive parameter values - if zero or negative, use old values instead
118
+	if (aSampleRate > 0)
119
+		this->sampleRate = aSampleRate;
120
+	if (aOverlapMS > 0)
121
+		this->overlapMs = aOverlapMS;
135 122
 
136
-    seekLength = (sampleRate * seekWindowMs) / 1000;
137
-    seekWindowLength = (sampleRate * sequenceMs) / 1000;
123
+	if (aSequenceMS > 0)
124
+	{
125
+		this->sequenceMs = aSequenceMS;
126
+		this->bAutoSeqSetting = false;
127
+	}
128
+	else if (!aSequenceMS)
129
+		// if zero, use automatic setting
130
+		this->bAutoSeqSetting = true;
138 131
 
139
-    maxOffset = seekLength;
132
+	if (aSeekWindowMS > 0) 
133
+	{
134
+		this->seekWindowMs = aSeekWindowMS;
135
+		this->bAutoSeekSetting = false;
136
+	}
137
+	else if (!aSeekWindowMS)
138
+		// if zero, use automatic setting
139
+		this->bAutoSeekSetting = true;
140 140
 
141
-    calculateOverlapLength(overlapMs);
141
+	this->calcSeqParameters();
142 142
 
143
-    // set tempo to recalculate 'sampleReq'
144
-    setTempo(tempo);
143
+	this->calculateOverlapLength(this->overlapMs);
145 144
 
145
+	// set tempo to recalculate 'sampleReq'
146
+	this->setTempo(this->tempo);
146 147
 }
147 148
 
148
-
149
-
150 149
 /// Get routine control parameters, see setParameters() function.
151 150
 /// Any of the parameters to this function can be NULL, in such case corresponding parameter
152 151
 /// value isn't returned.
153
-void TDStretch::getParameters(uint32_t *pSampleRate, uint32_t *pSequenceMs, uint32_t *pSeekWindowMs, uint32_t *pOverlapMs)
152
+void TDStretch::getParameters(int32_t *pSampleRate, int32_t *pSequenceMs, int32_t *pSeekWindowMs, int32_t *pOverlapMs)
154 153
 {
155
-    if (pSampleRate)
156
-    {
157
-        *pSampleRate = sampleRate;
158
-    }
154
+	if (pSampleRate)
155
+		*pSampleRate = this->sampleRate;
159 156
 
160
-    if (pSequenceMs)
161
-    {
162
-        *pSequenceMs = sequenceMs;
163
-    }
157
+	if (pSequenceMs)
158
+		*pSequenceMs = this->bAutoSeqSetting ? USE_AUTO_SEQUENCE_LEN : sequenceMs;
164 159
 
165
-    if (pSeekWindowMs)
166
-    {
167
-        *pSeekWindowMs = seekWindowMs;
168
-    }
160
+	if (pSeekWindowMs)
161
+		*pSeekWindowMs = this->bAutoSeekSetting ? USE_AUTO_SEEKWINDOW_LEN : seekWindowMs;
169 162
 
170
-    if (pOverlapMs)
171
-    {
172
-        *pOverlapMs = overlapMs;
173
-    }
163
+	if (pOverlapMs)
164
+		*pOverlapMs = this->overlapMs;
174 165
 }
175 166
 
176
-
177
-// Overlaps samples in 'midBuffer' with the samples in 'input'
178
-void TDStretch::overlapMono(SAMPLETYPE *out, const SAMPLETYPE *in) const
167
+// Overlaps samples in 'midBuffer' with the samples in 'pInput'
168
+void TDStretch::overlapMono(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput) const
179 169
 {
180
-    int i, itemp;
170
+	SAMPLETYPE m1 = static_cast<SAMPLETYPE>(0);
171
+	SAMPLETYPE m2 = static_cast<SAMPLETYPE>(this->overlapLength);
181 172
 
182
-    for (i = 0; i < (int)overlapLength ; i ++)
183
-    {
184
-        itemp = overlapLength - i;
185
-        out[i] = (in[i] * i + pMidBuffer[i] * itemp ) / overlapLength;    // >> overlapDividerBits;
186
-    }
173
+	for (int32_t i = 0; i < this->overlapLength; ++i)
174
+	{
175
+		pOutput[i] = (pInput[i] * m1 + this->pMidBuffer[i] * m2) / this->overlapLength;
176
+		++m1;
177
+		--m2;
178
+	}
187 179
 }
188 180
 
189
-
190
-
191 181
 void TDStretch::clearMidBuffer()
192 182
 {
193
-    if (bMidBufferDirty)
194
-    {
195
-        memset(pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * overlapLength);
196
-        bMidBufferDirty = false;
197
-    }
183
+	memset(this->pMidBuffer, 0, 2 * sizeof(SAMPLETYPE) * this->overlapLength);
198 184
 }
199 185
 
200
-
201 186
 void TDStretch::clearInput()
202 187
 {
203
-    inputBuffer.clear();
204
-    clearMidBuffer();
188
+	this->inputBuffer.clear();
189
+	this->clearMidBuffer();
205 190
 }
206 191
 
207
-
208 192
 // Clears the sample buffers
209 193
 void TDStretch::clear()
210 194
 {
211
-    outputBuffer.clear();
212
-    inputBuffer.clear();
213
-    clearMidBuffer();
195
+	this->outputBuffer.clear();
196
+	this->clearInput();
214 197
 }
215 198
 
216
-
217
-
218 199
 // Enables/disables the quick position seeking algorithm. Zero to disable, nonzero
219 200
 // to enable
220 201
 void TDStretch::enableQuickSeek(bool enable)
221 202
 {
222
-    bQuickseek = enable;
203
+	this->bQuickSeek = enable;
223 204
 }
224 205
 
225
-
226 206
 // Returns nonzero if the quick seeking algorithm is enabled.
227 207
 bool TDStretch::isQuickSeekEnabled() const
228 208
 {
229
-    return bQuickseek;
209
+	return this->bQuickSeek;
230 210
 }
231 211
 
232
-
233 212
 // Seeks for the optimal overlap-mixing position.
234
-uint32_t TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
213
+int32_t TDStretch::seekBestOverlapPosition(const SAMPLETYPE *refPos)
235 214
 {
236
-    if (channels == 2)
237
-    {
238
-        // stereo sound
239
-        if (bQuickseek)
240
-        {
241
-            return seekBestOverlapPositionStereoQuick(refPos);
242
-        }
243
-        else
244
-        {
245
-            return seekBestOverlapPositionStereo(refPos);
246
-        }
247
-    }
248
-    else
249
-    {
250
-        // mono sound
251
-        if (bQuickseek)
252
-        {
253
-            return seekBestOverlapPositionMonoQuick(refPos);
254
-        }
255
-        else
256
-        {
257
-            return seekBestOverlapPositionMono(refPos);
258
-        }
259
-    }
215
+	if (this->bQuickSeek)
216
+		return this->seekBestOverlapPositionQuick(refPos);
217
+	else
218
+		return this->seekBestOverlapPositionFull(refPos);
260 219
 }
261 220
 
262
-
263
-
264
-
265
-// Overlaps samples in 'midBuffer' with the samples in 'inputBuffer' at position
221
+// Overlaps samples in 'midBuffer' with the samples in 'pInputBuffer' at position
266 222
 // of 'ovlPos'.
267
-inline void TDStretch::overlap(SAMPLETYPE *out, const SAMPLETYPE *in, uint32_t ovlPos) const
223
+void TDStretch::overlap(SAMPLETYPE *pOutput, const SAMPLETYPE *pInput, uint32_t ovlPos) const
268 224
 {
269
-    if (channels == 2)
270
-    {
271
-        // stereo sound
272
-        overlapStereo(out, in + 2 * ovlPos);
273
-    } else {
274
-        // mono sound.
275
-        overlapMono(out, in + ovlPos);
276
-    }
225
+	if (this->channels == 2)
226
+		// stereo sound
227
+		this->overlapStereo(pOutput, pInput + 2 * ovlPos);
228
+	else
229
+		// mono sound.
230
+		this->overlapMono(pOutput, pInput + ovlPos);
277 231
 }
278 232
 
279
-
280
-
281
-
282 233
 // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
283 234
 // routine
284 235
 //
285 236
 // The best position is determined as the position where the two overlapped
286 237
 // sample sequences are 'most alike', in terms of the highest cross-correlation
287 238
 // value over the overlapping period
288
-uint32_t TDStretch::seekBestOverlapPositionStereo(const SAMPLETYPE *refPos)
289
-{
290
-    uint32_t bestOffs;
291
-    LONG_SAMPLETYPE bestCorr, corr;
292
-    uint32_t i;
293
-
294
-    // Slopes the amplitudes of the 'midBuffer' samples
295
-    precalcCorrReferenceStereo();
296
-
297
-    bestCorr = INT_MIN;
298
-    bestOffs = 0;
299
-
300
-    // Scans for the best correlation value by testing each possible position
301
-    // over the permitted range.
302
-    for (i = 0; i < seekLength; i ++)
303
-    {
304
-        // Calculates correlation value for the mixing position corresponding
305
-        // to 'i'
306
-        corr = calcCrossCorrStereo(refPos + 2 * i, pRefMidBuffer);
307
-
308
-        // Checks for the highest correlation value
309
-        if (corr > bestCorr)
310
-        {
311
-            bestCorr = corr;
312
-            bestOffs = i;
313
-        }
314
-    }
315
-    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
316
-    clearCrossCorrState();
317
-
318
-    return bestOffs;
239
+int32_t TDStretch::seekBestOverlapPositionFull(const SAMPLETYPE *refPos)
240
+{
241
+	double bestCorr = FLT_MIN;
242
+	int32_t bestOffs = 0;
243
+
244
+	// Scans for the best correlation value by testing each possible position
245
+	// over the permitted range.
246
+	for (int32_t i = 0; i < this->seekLength; ++i)
247
+	{
248
+		// Calculates correlation value for the mixing position corresponding
249
+		// to 'i'
250
+		double corr = this->calcCrossCorr(refPos + this->channels * i, this->pMidBuffer);
251
+		// heuristic rule to slightly favour values close to mid of the range
252
+		double tmp = static_cast<double>(2 * i - this->seekLength) / this->seekLength;
253
+		corr = (corr + 0.1) * (1.0 - 0.25 * tmp * tmp);
254
+
255
+		// Checks for the highest correlation value
256
+		if (corr > bestCorr)
257
+		{
258
+			bestCorr = corr;
259
+			bestOffs = i;
260
+		}
261
+	}
262
+	// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
263
+	this->clearCrossCorrState();
264
+
265
+	return bestOffs;
319 266
 }
320 267
 
321
-
322 268
 // Seeks for the optimal overlap-mixing position. The 'stereo' version of the
323 269
 // routine
324 270
 //
325 271
 // The best position is determined as the position where the two overlapped
326 272
 // sample sequences are 'most alike', in terms of the highest cross-correlation
327 273
 // value over the overlapping period
328
-uint32_t TDStretch::seekBestOverlapPositionStereoQuick(const SAMPLETYPE *refPos)
274
+int32_t TDStretch::seekBestOverlapPositionQuick(const SAMPLETYPE *refPos)
275
+{
276
+	double bestCorr = FLT_MIN;
277
+	int32_t bestOffs = _scanOffsets[0][0], corrOffset = 0;
278
+
279
+	// Scans for the best correlation value using four-pass hierarchical search.
280
+	//
281
+	// The look-up table 'scans' has hierarchical position adjusting steps.
282
+	// In first pass the routine searhes for the highest correlation with
283
+	// relatively coarse steps, then rescans the neighbourhood of the highest
284
+	// correlation with better resolution and so on.
285
+	for (uint32_t scanCount = 0; scanCount < 4; ++scanCount)
286
+	{
287
+		int32_t j = 0;
288
+		while (_scanOffsets[scanCount][j])
289
+		{
290
+			int32_t tempOffset = corrOffset + _scanOffsets[scanCount][j];
291
+			if (tempOffset >= this->seekLength)
292
+				break;
293
+
294
+			// Calculates correlation value for the mixing position corresponding
295
+			// to 'tempOffset'
296
+			double corr = static_cast<double>(this->calcCrossCorr(refPos + this->channels * tempOffset, this->pMidBuffer));
297
+			// heuristic rule to slightly favour values close to mid of the range
298
+			double tmp = static_cast<double>(2 * tempOffset - this->seekLength) / seekLength;
299
+			corr = (corr + 0.1) * (1.0 - 0.25 * tmp * tmp);
300
+
301
+			// Checks for the highest correlation value
302
+			if (corr > bestCorr)
303
+			{
304
+				bestCorr = corr;
305
+				bestOffs = tempOffset;
306
+			}
307
+			++j;
308
+		}
309
+		corrOffset = bestOffs;
310
+	}
311
+	// clear cross correlation routine state if necessary (is so e.g. in MMX routines).
312
+	this->clearCrossCorrState();
313
+
314
+	return bestOffs;
315
+}
316
+
317
+/// clear cross correlation routine state if necessary 
318
+void TDStretch::clearCrossCorrState()
329 319
 {
330
-    uint32_t j;
331
-    uint32_t bestOffs;
332
-    LONG_SAMPLETYPE bestCorr, corr;
333
-    uint32_t scanCount, corrOffset, tempOffset;
334
-
335
-    // Slopes the amplitude of the 'midBuffer' samples
336
-    precalcCorrReferenceStereo();
337
-
338
-    bestCorr = INT_MIN;
339
-    bestOffs = 0;
340
-    corrOffset = 0;
341
-    tempOffset = 0;
342
-
343
-    // Scans for the best correlation value using four-pass hierarchical search.
344
-    //
345
-    // The look-up table 'scans' has hierarchical position adjusting steps.
346
-    // In first pass the routine searhes for the highest correlation with
347
-    // relatively coarse steps, then rescans the neighbourhood of the highest
348
-    // correlation with better resolution and so on.
349
-    for (scanCount = 0;scanCount < 4; scanCount ++)
350
-    {
351
-        j = 0;
352
-        while (scanOffsets[scanCount][j])
353
-        {
354
-            tempOffset = corrOffset + scanOffsets[scanCount][j];
355
-            if (tempOffset >= seekLength) break;
356
-
357
-            // Calculates correlation value for the mixing position corresponding
358
-            // to 'tempOffset'
359
-            corr = calcCrossCorrStereo(refPos + 2 * tempOffset, pRefMidBuffer);
360
-
361
-            // Checks for the highest correlation value
362
-            if (corr > bestCorr)
363
-            {
364
-                bestCorr = corr;
365
-                bestOffs = tempOffset;
366
-            }
367
-            j ++;
368
-        }
369
-        corrOffset = bestOffs;
370
-    }
371
-    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
372
-    clearCrossCorrState();
373
-
374
-    return bestOffs;
320
+	// default implementation is empty.
375 321
 }
376 322
 
377
-
378
-
379
-// Seeks for the optimal overlap-mixing position. The 'mono' version of the
380
-// routine
381
-//
382
-// The best position is determined as the position where the two overlapped
383
-// sample sequences are 'most alike', in terms of the highest cross-correlation
384
-// value over the overlapping period
385
-uint32_t TDStretch::seekBestOverlapPositionMono(const SAMPLETYPE *refPos)
323
+/// Calculates processing sequence length according to tempo setting
324
+void TDStretch::calcSeqParameters()
386 325
 {
387
-    uint32_t bestOffs;
388
-    LONG_SAMPLETYPE bestCorr, corr;
389
-    uint32_t tempOffset;
390
-    const SAMPLETYPE *compare;
391
-
392
-    // Slopes the amplitude of the 'midBuffer' samples
393
-    precalcCorrReferenceMono();
394
-
395
-    bestCorr = INT_MIN;
396
-    bestOffs = 0;
397
-
398
-    // Scans for the best correlation value by testing each possible position
399
-    // over the permitted range.
400
-    for (tempOffset = 0; tempOffset < seekLength; tempOffset ++)
401
-    {
402
-        compare = refPos + tempOffset;
403
-
404
-        // Calculates correlation value for the mixing position corresponding
405
-        // to 'tempOffset'
406
-        corr = calcCrossCorrMono(pRefMidBuffer, compare);
407
-
408
-        // Checks for the highest correlation value
409
-        if (corr > bestCorr)
410
-        {
411
-            bestCorr = corr;
412
-            bestOffs = tempOffset;
413
-        }
414
-    }
415
-    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
416
-    clearCrossCorrState();
326
+	// Adjust tempo param according to tempo, so that variating processing sequence length is used
327
+	// at varius tempo settings, between the given low...top limits
328
+	static const double AUTOSEQ_TEMPO_LOW = 0.5; // auto setting low tempo range (-50%)
329
+	static const double AUTOSEQ_TEMPO_TOP = 2.0; // auto setting top tempo range (+100%)
417 330
 
418
-    return bestOffs;
419
-}
331
+	// sequence-ms setting values at above low & top tempo
332
+	static const double AUTOSEQ_AT_MIN = 125.0;
333
+	static const double AUTOSEQ_AT_MAX = 50.0;
334
+	static const double AUTOSEQ_K = (AUTOSEQ_AT_MAX - AUTOSEQ_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW);
335
+	static const double AUTOSEQ_C = AUTOSEQ_AT_MIN - AUTOSEQ_K * AUTOSEQ_TEMPO_LOW;
420 336
 
337
+	// seek-window-ms setting values at above low & top tempo
338
+	static const double AUTOSEEK_AT_MIN = 25.0;
339
+	static const double AUTOSEEK_AT_MAX = 15.0;
340
+	static const double AUTOSEEK_K = (AUTOSEEK_AT_MAX - AUTOSEEK_AT_MIN) / (AUTOSEQ_TEMPO_TOP - AUTOSEQ_TEMPO_LOW);
341
+	static const double AUTOSEEK_C = AUTOSEEK_AT_MIN - AUTOSEEK_K * AUTOSEQ_TEMPO_LOW;
421 342
 
422
-// Seeks for the optimal overlap-mixing position. The 'mono' version of the
423
-// routine
424
-//
425
-// The best position is determined as the position where the two overlapped
426
-// sample sequences are 'most alike', in terms of the highest cross-correlation
427
-// value over the overlapping period
428
-uint32_t TDStretch::seekBestOverlapPositionMonoQuick(const SAMPLETYPE *refPos)
429
-{
430
-    uint32_t j;
431
-    uint32_t bestOffs;
432
-    LONG_SAMPLETYPE bestCorr, corr;
433
-    uint32_t scanCount, corrOffset, tempOffset;
434
-
435
-    // Slopes the amplitude of the 'midBuffer' samples
436
-    precalcCorrReferenceMono();
437
-
438
-    bestCorr = INT_MIN;
439
-    bestOffs = 0;
440
-    corrOffset = 0;
441
-    tempOffset = 0;
442
-
443
-    // Scans for the best correlation value using four-pass hierarchical search.
444
-    //
445
-    // The look-up table 'scans' has hierarchical position adjusting steps.
446
-    // In first pass the routine searhes for the highest correlation with
447
-    // relatively coarse steps, then rescans the neighbourhood of the highest
448
-    // correlation with better resolution and so on.
449
-    for (scanCount = 0;scanCount < 4; scanCount ++)
450
-    {
451
-        j = 0;
452
-        while (scanOffsets[scanCount][j])
453
-        {
454
-            tempOffset = corrOffset + scanOffsets[scanCount][j];
455
-            if (tempOffset >= seekLength) break;
456
-
457
-            // Calculates correlation value for the mixing position corresponding
458
-            // to 'tempOffset'
459
-            corr = calcCrossCorrMono(refPos + tempOffset, pRefMidBuffer);
460
-
461
-            // Checks for the highest correlation value
462
-            if (corr > bestCorr)
463
-            {
464
-                bestCorr = corr;
465
-                bestOffs = tempOffset;
466
-            }
467
-            j ++;
468
-        }
469
-        corrOffset = bestOffs;
470
-    }
471
-    // clear cross correlation routine state if necessary (is so e.g. in MMX routines).
472
-    clearCrossCorrState();
343
+	auto CHECK_LIMITS = [](double x, double mi, double ma) { return x < mi ? mi : (x > ma ? ma : x); };
473 344
 
474
-    return bestOffs;
475
-}
345
+	if (this->bAutoSeqSetting)
346
+	{
347
+		double seq = AUTOSEQ_C + AUTOSEQ_K * this->tempo;
348
+		seq = CHECK_LIMITS(seq, AUTOSEQ_AT_MAX, AUTOSEQ_AT_MIN);
349
+		this->sequenceMs = static_cast<int>(seq + 0.5);
350
+	}
476 351
 
352
+	if (this->bAutoSeekSetting)
353
+	{
354
+		double seek = AUTOSEEK_C + AUTOSEEK_K * this->tempo;
355
+		seek = CHECK_LIMITS(seek, AUTOSEEK_AT_MAX, AUTOSEEK_AT_MIN);
356
+		this->seekWindowMs = static_cast<int>(seek + 0.5);
357
+    }
477 358
 
478
-/// clear cross correlation routine state if necessary
479
-void TDStretch::clearCrossCorrState()
480
-{
481
-    // default implementation is empty.
359
+	// Update seek window lengths
360
+	this->seekWindowLength = (this->sampleRate * this->sequenceMs) / 1000;
361
+	if (this->seekWindowLength < 2 * this->overlapLength) 
362
+		this->seekWindowLength = 2 * this->overlapLength;
363
+	this->seekLength = (this->sampleRate * this->seekWindowMs) / 1000;
482 364
 }
483 365
 
484
-
485 366
 // Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
486 367
 // tempo, larger faster tempo.
487 368
 void TDStretch::setTempo(float newTempo)
488 369
 {
489
-    uint32_t intskip;
370
+	this->tempo = newTempo;
490 371
 
491
-    tempo = newTempo;
372
+	// Calculate new sequence duration
373
+	this->calcSeqParameters();
492 374
 
493
-    // Calculate ideal skip length (according to tempo value)
494
-    nominalSkip = tempo * (seekWindowLength - overlapLength);
495
-    skipFract = 0;
496
-    intskip = (int)(nominalSkip + 0.5f);
375
+	// Calculate ideal skip length (according to tempo value)
376
+	this->nominalSkip = this->tempo * (this->seekWindowLength - this->overlapLength);
377
+	int intskip = static_cast<int>(nominalSkip + 0.5f);
497 378
 
498
-    // Calculate how many samples are needed in the 'inputBuffer' to
499
-    // process another batch of samples
500
-    sampleReq = std::max(intskip + overlapLength, seekWindowLength) + maxOffset;
379
+	// Calculate how many samples are needed in the 'inputBuffer' to
380
+	// process another batch of samples
381
+	this->sampleReq = std::max(intskip + this->overlapLength, this->seekWindowLength) + this->seekLength;
501 382
 }
502 383
 
503
-
504
-
505 384
 // Sets the number of channels, 1 = mono, 2 = stereo
506
-void TDStretch::setChannels(uint32_t numChannels)
385
+void TDStretch::setChannels(int32_t numChannels)
507 386
 {
508
-    if (channels == numChannels) return;
509
-    assert(numChannels == 1 || numChannels == 2);
387
+	assert(numChannels > 0);
388
+	if (this->channels == numChannels)
389
+		return;
390
+	assert(numChannels == 1 || numChannels == 2);
510 391
 
511
-    channels = numChannels;
512
-    inputBuffer.setChannels(channels);
513
-    outputBuffer.setChannels(channels);
392
+	this->channels = numChannels;
393
+	this->inputBuffer.setChannels(channels);
394
+	this->outputBuffer.setChannels(channels);
514 395
 }
515 396
 
516
-
517
-// nominal tempo, no need for processing, just pass the samples through
518
-// to outputBuffer
519
-void TDStretch::processNominalTempo()
520
-{
521
-    assert(fEqual(tempo, 1.0f));
522
-
523
-    if (bMidBufferDirty)
524
-    {
525
-        // If there are samples in pMidBuffer waiting for overlapping,
526
-        // do a single sliding overlapping with them in order to prevent a
527
-        // clicking distortion in the output sound
528
-        if (inputBuffer.numSamples() < overlapLength)
529
-        {
530
-            // wait until we've got overlapLength input samples
531
-            return;
532
-        }
533
-        // Mix the samples in the beginning of 'inputBuffer' with the
534
-        // samples in 'midBuffer' using sliding overlapping
535
-        overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), 0);
536
-        outputBuffer.putSamples(overlapLength);
537
-        inputBuffer.receiveSamples(overlapLength);
538
-        clearMidBuffer();
539
-        // now we've caught the nominal sample flow and may switch to
540
-        // bypass mode
541
-    }
542
-
543
-    // Simply bypass samples from input to output
544
-    outputBuffer.moveSamples(inputBuffer);
545
-}
546
-
547
-
548
-
549 397
 // Processes as many processing frames of the samples 'inputBuffer', store
550 398
 // the result into 'outputBuffer'
551 399
 void TDStretch::processSamples()
552 400
 {
553
-    uint32_t ovlSkip, offset;
554
-    int temp;
555
-
556
-    /* Removed this small optimization - can introduce a click to sound when tempo setting
557
-       crosses the nominal value
558
-    if (tempo == 1.0f)
559
-    {
560
-        // tempo not changed from the original, so bypass the processing
561
-        processNominalTempo();
562
-        return;
563
-    }
564
-    */
565
-
566
-    if (bMidBufferDirty == false)
567
-    {
568
-        // if midBuffer is empty, move the first samples of the input stream
569
-        // into it
570
-        if (inputBuffer.numSamples() < overlapLength)
571
-        {
572
-            // wait until we've got overlapLength samples
573
-            return;
574
-        }
575
-        memcpy(pMidBuffer, inputBuffer.ptrBegin(), channels * overlapLength * sizeof(SAMPLETYPE));
576
-        inputBuffer.receiveSamples(overlapLength);
577
-        bMidBufferDirty = true;
578
-    }
579
-
580
-    // Process samples as long as there are enough samples in 'inputBuffer'
581
-    // to form a processing frame.
582
-    while (inputBuffer.numSamples() >= sampleReq)
583
-    {
584
-        // If tempo differs from the normal ('SCALE'), scan for the best overlapping
585
-        // position
586
-        offset = seekBestOverlapPosition(inputBuffer.ptrBegin());
587
-
588
-        // Mix the samples in the 'inputBuffer' at position of 'offset' with the
589
-        // samples in 'midBuffer' using sliding overlapping
590
-        // ... first partially overlap with the end of the previous sequence
591
-        // (that's in 'midBuffer')
592
-        overlap(outputBuffer.ptrEnd(overlapLength), inputBuffer.ptrBegin(), offset);
593
-        outputBuffer.putSamples(overlapLength);
594
-
595
-        // ... then copy sequence samples from 'inputBuffer' to output
596
-        temp = (seekWindowLength - 2 * overlapLength);// & 0xfffffffe;
597
-        if (temp > 0)
598
-        {
599
-            outputBuffer.putSamples(inputBuffer.ptrBegin() + channels * (offset + overlapLength), temp);
600
-        }
601
-
602
-        // Copies the end of the current sequence from 'inputBuffer' to
603
-        // 'midBuffer' for being mixed with the beginning of the next
604
-        // processing sequence and so on
605
-        assert(offset + seekWindowLength <= inputBuffer.numSamples());
606
-        memcpy(pMidBuffer, inputBuffer.ptrBegin() + channels * (offset + seekWindowLength - overlapLength),
607
-            channels * sizeof(SAMPLETYPE) * overlapLength);
608
-        bMidBufferDirty = true;
609
-
610
-        // Remove the processed samples from the input buffer. Update
611
-        // the difference between integer & nominal skip step to 'skipFract'
612
-        // in order to prevent the error from accumulating over time.
613
-        skipFract += nominalSkip;   // real skip size
614
-        ovlSkip = (int)skipFract;   // rounded to integer skip
615
-        skipFract -= ovlSkip;       // maintain the fraction part, i.e. real vs. integer skip
616
-        inputBuffer.receiveSamples(ovlSkip);
617
-    }
401
+	/* Removed this small optimization - can introduce a click to sound when tempo setting
402
+	   crosses the nominal value
403
+	if (this->tempo == 1.0f)
404
+	{
405
+		// tempo not changed from the original, so bypass the processing
406
+		this->processNominalTempo();
407
+		return;
408
+	}*/
409
+
410
+	// Process samples as long as there are enough samples in 'inputBuffer'
411
+	// to form a processing frame.
412
+	while (static_cast<int32_t>(this->inputBuffer.numSamples()) >= this->sampleReq)
413
+	{
414
+		// If tempo differs from the normal ('SCALE'), scan for the best overlapping
415
+		// position
416
+		int32_t offset = this->seekBestOverlapPosition(this->inputBuffer.ptrBegin());
417
+
418
+		// Mix the samples in the 'inputBuffer' at position of 'offset' with the
419
+		// samples in 'midBuffer' using sliding overlapping
420
+		// ... first partially overlap with the end of the previous sequence
421
+		// (that's in 'midBuffer')
422
+		this->overlap(this->outputBuffer.ptrEnd(static_cast<uint32_t>(this->overlapLength)), this->inputBuffer.ptrBegin(), static_cast<uint32_t>(offset));
423
+		this->outputBuffer.putSamples(static_cast<uint32_t>(this->overlapLength));
424
+
425
+		// ... then copy sequence samples from 'inputBuffer' to output:
426
+
427
+		// length of sequence
428
+		int temp = this->seekWindowLength - 2 * this->overlapLength;
429
+
430
+		// crosscheck that we don't have buffer overflow...
431
+		if (static_cast<int32_t>(inputBuffer.numSamples()) < offset + temp + this->overlapLength * 2)
432
+			continue; // just in case, shouldn't really happen
433
+
434
+		this->outputBuffer.putSamples(this->inputBuffer.ptrBegin() + this->channels * (offset + this->overlapLength), static_cast<uint32_t>(temp));
435
+
436
+		// Copies the end of the current sequence from 'inputBuffer' to
437
+		// 'midBuffer' for being mixed with the beginning of the next
438
+		// processing sequence and so on
439
+		assert(offset + temp + this->overlapLength * 2 <= static_cast<int>(this->inputBuffer.numSamples()));
440
+		memcpy(this->pMidBuffer, this->inputBuffer.ptrBegin() + this->channels * (offset + this->seekWindowLength - this->overlapLength), this->channels * sizeof(SAMPLETYPE) * this->overlapLength);
441
+
442
+		// Remove the processed samples from the input buffer. Update
443
+		// the difference between integer & nominal skip step to 'skipFract'
444
+		// in order to prevent the error from accumulating over time.
445
+		this->skipFract += this->nominalSkip; // real skip size
446
+		int ovlSkip = static_cast<int>(skipFract); // rounded to integer skip
447
+		this->skipFract -= ovlSkip; // maintain the fraction part, i.e. real vs. integer skip
448
+		this->inputBuffer.receiveSamples(static_cast<uint32_t>(ovlSkip));
449
+	}
618 450
 }
619 451
 
620
-
621 452
 // Adds 'numsamples' pcs of samples from the 'samples' memory position into
622 453
 // the input of the object.
623
-void TDStretch::putSamples(const SAMPLETYPE *samples, uint32_t numsamples)
454
+void TDStretch::putSamples(const SAMPLETYPE *samples, uint32_t nSamples)
624 455
 {
625
-    // Add the samples into the input buffer
626
-    inputBuffer.putSamples(samples, numsamples);
627
-    // Process the samples in input buffer
628
-    processSamples();
456
+	// Add the samples into the input buffer
457
+	this->inputBuffer.putSamples(samples, nSamples);
458
+	// Process the samples in input buffer
459
+	this->processSamples();
629 460
 }
630 461
 
631
-
632
-
633 462
 /// Set new overlap length parameter & reallocate RefMidBuffer if necessary.
634
-void TDStretch::acceptNewOverlapLength(uint32_t newOverlapLength)
463
+void TDStretch::acceptNewOverlapLength(int32_t newOverlapLength)
635 464
 {
636
-    uint32_t prevOvl;
637
-
638
-    prevOvl = overlapLength;
639
-    overlapLength = newOverlapLength;
465
+	assert(newOverlapLength >= 0);
466
+	int32_t prevOvl = this->overlapLength;
467
+	this->overlapLength = newOverlapLength;
640 468
 
641
-    if (overlapLength > prevOvl)
642
-    {
643
-        delete[] pMidBuffer;
644
-        delete[] pRefMidBufferUnaligned;
469
+	if (this->overlapLength > prevOvl)
470
+	{
471
+		this->pMidBufferUnaligned.reset(new SAMPLETYPE[this->overlapLength * 2 + 16 / sizeof(SAMPLETYPE)]);
472
+		// ensure that 'pMidBuffer' is aligned to 16 byte boundary for efficiency
473
+		this->pMidBuffer = reinterpret_cast<SAMPLETYPE *>(SOUNDTOUCH_ALIGN_POINTER_16(this->pMidBufferUnaligned.get()));
645 474
 
646
-        pMidBuffer = new SAMPLETYPE[overlapLength * 2];
647
-        bMidBufferDirty = true;
648
-        clearMidBuffer();
649
-
650
-        pRefMidBufferUnaligned = new SAMPLETYPE[2 * overlapLength + 16 / sizeof(SAMPLETYPE)];
651
-        // ensure that 'pRefMidBuffer' is aligned to 16 byte boundary for efficiency
652
-        pRefMidBuffer = (SAMPLETYPE *)((((intptr_t)pRefMidBufferUnaligned) + 15) & -16);
653
-    }
475
+		this->clearMidBuffer();
476
+	}
654 477
 }
655 478
 
656
-
657 479
 // Operator 'new' is overloaded so that it automatically creates a suitable instance
658 480
 // depending on if we've a MMX/SSE/etc-capable CPU available or not.
659
-void * TDStretch::operator new(size_t s)
481
+void *TDStretch::operator new(size_t s)
660 482
 {
661
-    // Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
662
-    //assert(false);
663
-    //return NULL;
483
+	// Notice! don't use "new TDStretch" directly, use "newInstance" to create a new instance instead!
484
+	//assert(false);
485
+	//return NULL;
664 486
 	throw std::runtime_error("Don't use 'new TDStretch', use 'newInstance' member instead!");
665 487
 }
666 488
 
667
-
668 489
 TDStretch * TDStretch::newInstance()
669 490
 {
670
-    uint32_t uExtensions = 0;
671
-#if !defined(_MSC_VER) || !defined(__x86_64__)
672
-    uExtensions = detectCPUextensions();
673
-#endif
674
-    // Check if MMX/SSE/3DNow! instruction set extensions supported by CPU
675
-
676
-#ifdef ALLOW_MMX
677
-    // MMX routines available only with integer sample types
678
-    if (uExtensions & SUPPORT_MMX)
679
-    {
680
-        return ::new TDStretchMMX;
681
-    }
682
-    else
683
-#endif // ALLOW_MMX
491
+	uint32_t uExtensions = detectCPUextensions();
684 492
 
493
+	// Check if MMX/SSE instruction set extensions supported by CPU
685 494
 
686
-#ifdef __SSE__
687
-    if (uExtensions & SUPPORT_SSE)
688
-    {
689
-        // SSE support
690
-        return ::new TDStretchSSE;
691
-    }
692
-    else
693
-#endif // ALLOW_SSE
694
-
695
-
696
-#ifdef ALLOW_3DNOW
697
-    if (uExtensions & SUPPORT_3DNOW)
698
-    {
699
-        // 3DNow! support
700
-        return ::new TDStretch3DNow;
701
-    }
702
-    else
703
-#endif // ALLOW_3DNOW
704
-
705
-    {
706
-        // ISA optimizations not supported, use plain C version
707
-        return ::new TDStretch;
708
-    }
495
+#ifdef SOUNDTOUCH_ALLOW_MMX
496
+	// MMX routines available only with integer sample types
497
+	if (uExtensions & SUPPORT_MMX)
498
+		return ::new TDStretchMMX;
499
+	else
500
+#endif // SOUNDTOUCH_ALLOW_MMX
501
+#ifdef SOUNDTOUCH_ALLOW_SSE
502
+	if (uExtensions & SUPPORT_SSE)
503
+		// SSE support
504
+		return ::new TDStretchSSE;
505
+	else
506
+#endif //  SOUNDTOUCH_ALLOW_SSE
507
+		// ISA optimizations not supported, use plain C version
508
+		return ::new TDStretch;
709 509
 }
710 510
 
711
-
712 511
 //////////////////////////////////////////////////////////////////////////////
713 512
 //
714 513
 // Integer arithmetics specific algorithm implementations.
715 514
 //
716 515
 //////////////////////////////////////////////////////////////////////////////
717 516
 
718
-#ifdef INTEGER_SAMPLES
719
-
720
-// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
721
-// is faster to calculate
722
-void TDStretch::precalcCorrReferenceStereo()
723
-{
724
-    int i, cnt2;
725
-    int temp, temp2;
726
-
727
-    for (i=0 ; i < (int)overlapLength ;i ++)
728
-    {
729
-        temp = i * (overlapLength - i);
730
-        cnt2 = i * 2;
731
-
732
-        temp2 = (pMidBuffer[cnt2] * temp) / slopingDivider;
733
-        pRefMidBuffer[cnt2] = (short)(temp2);
734
-        temp2 = (pMidBuffer[cnt2 + 1] * temp) / slopingDivider;
735
-        pRefMidBuffer[cnt2 + 1] = (short)(temp2);
736
-    }
737
-}
738
-
517
+#ifdef SOUNDTOUCH_INTEGER_SAMPLES
739 518
 
740
-// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
741
-// is faster to calculate
742
-void TDStretch::precalcCorrReferenceMono()
519
+// Overlaps samples in 'midBuffer' with the samples in 'pinput'. The 'Stereo'
520
+// version of the routine.
521
+void TDStretch::overlapStereo(short *poutput, const short *pinput) const
743 522
 {
744
-    int i;
745
-    long temp;
746
-    long temp2;
747
-
748
-    for (i=0 ; i < (int)overlapLength ;i ++)
749
-    {
750
-        temp = i * (overlapLength - i);
751
-        temp2 = (pMidBuffer[i] * temp) / slopingDivider;
752
-        pRefMidBuffer[i] = (short)temp2;
753
-    }
523
+	for (int32_t i = 0; i < this->overlapLength; ++i)
524
+	{
525
+		short temp = static_cast<short>(this->overlapLength - i);
526
+		int32_t cnt2 = 2 * i;
527
+		poutput[cnt2] = (pinput[cnt2] * i + this->pMidBuffer[cnt2] * temp) / this->overlapLength;
528
+		poutput[cnt2 + 1] = (pinput[cnt2 + 1] * i + this->pMidBuffer[cnt2 + 1] * temp) / this->overlapLength;
529
+	}
754 530
 }
755 531
 
756
-
757
-// Overlaps samples in 'midBuffer' with the samples in 'input'. The 'Stereo'
758
-// version of the routine.
759
-void TDStretch::overlapStereo(short *out, const short *in) const
532
+// Calculates the x having the closest 2^x value for the given value
533
+static int _getClosest2Power(double value)
760 534
 {
761
-    int i;
762
-    short temp;
763
-    uint32_t cnt2;
764
-
765
-    for (i = 0; i < (int)overlapLength ; i ++)
766
-    {
767
-        temp = (short)(overlapLength - i);
768
-        cnt2 = 2 * i;
769
-        out[cnt2] = (in[cnt2] * i + pMidBuffer[cnt2] * temp )  / overlapLength;
770
-        out[cnt2 + 1] = (in[cnt2 + 1] * i + pMidBuffer[cnt2 + 1] * temp ) / overlapLength;
771
-    }
535
+	return static_cast<int>(std::log(value) / std::log(2.0) + 0.5);
772 536
 }
773 537
 
774
-
775 538
 /// Calculates overlap period length in samples.
776 539
 /// Integer version rounds overlap length to closest power of 2
777 540
 /// for a divide scaling operation.
778
-void TDStretch::calculateOverlapLength(uint32_t overlapMS)
541
+void TDStretch::calculateOverlapLength(int32_t aoverlapMs)
779 542
 {
780
-    uint32_t newOvl;
781
-
782
-    overlapDividerBits = _getClosest2Power((sampleRate * overlapMS) / 1000.0);
783
-    if (overlapDividerBits > 9) overlapDividerBits = 9;
784
-    if (overlapDividerBits < 4) overlapDividerBits = 4;
785
-    newOvl = 1<<overlapDividerBits;
786
-
787
-    acceptNewOverlapLength(newOvl);
788
-
789
-    // calculate sloping divider so that crosscorrelation operation won't
790
-    // overflow 32-bit register. Max. sum of the crosscorrelation sum without
791
-    // divider would be 2^30*(N^3-N)/3, where N = overlap length
792
-    slopingDivider = (newOvl * newOvl - 1) / 3;
793
-}
543
+	assert(aoverlapMs >= 0);
794 544
 
545
+	// calculate overlap length so that it's power of 2 - thus it's easy to do
546
+	// integer division by right-shifting. Term "-1" at end is to account for 
547
+	// the extra most significatnt bit left unused in result by signed multiplication 
548
+	this->overlapDividerBits = _getClosest2Power((this->sampleRate * aoverlapMs) / 1000.0) - 1;
549
+	if (this->overlapDividerBits > 9)
550
+		this->overlapDividerBits = 9;
551
+	if (this->overlapDividerBits < 3)
552
+		this->overlapDividerBits = 3;
553
+	int32_t newOvl = static_cast<int>std::pow(2, static_cast<int>(this->overlapDividerBits) + 1); // +1 => account for -1 above
795 554
 
796
-long TDStretch::calcCrossCorrMono(const short *mixingPos, const short *compare) const
797
-{
798
-    long corr;
799
-    uint32_t i;
555
+	this->acceptNewOverlapLength(newOvl);
800 556
 
801
-    corr = 0;
802
-    for (i = 1; i < overlapLength; i ++)
803
-    {
804
-        corr += (mixingPos[i] * compare[i]) >> overlapDividerBits;
805
-    }
806
-
807
-    return corr;
557
+	// calculate sloping divider so that crosscorrelation operation won't
558
+	// overflow 32-bit register. Max. sum of the crosscorrelation sum without
559
+	// divider would be 2^30*(N^3-N)/3, where N = overlap length
560
+	this->slopingDivider = (newOvl * newOvl - 1) / 3;
808 561
 }
809 562
 
810
-
811
-long TDStretch::calcCrossCorrStereo(const short *mixingPos, const short *compare) const
563
+double TDStretch::calcCrossCorr(const short *mixingPos, const short *compare) const
812 564
 {
813
-    long corr;
814
-    uint32_t i;
815
-
816
-    corr = 0;
817
-    for (i = 2; i < 2 * overlapLength; i += 2)
818
-    {
819
-        corr += (mixingPos[i] * compare[i] +
820
-                 mixingPos[i + 1] * compare[i + 1]) >> overlapDividerBits;
821
-    }
565
+	long corr = 0, norm = 0;
566
+	// Same routine for stereo and mono. For stereo, unroll loop for better
567
+	// efficiency and gives slightly better resolution against rounding. 
568
+	// For mono it same routine, just  unrolls loop by factor of 4
569
+	for (int32_t i = 0; i < this->overlapLength; i += 4)
570
+	{
571
+		corr += (mixingPos[i] * compare[i] + mixingPos[i + 1] * compare[i + 1] + mixingPos[i + 2] * compare[i + 2] + mixingPos[i + 3] * compare[i + 3]) >> this->overlapDividerBits;
572
+		norm += (mixingPos[i] * mixingPos[i] + mixingPos[i + 1] * mixingPos[i + 1] + mixingPos[i + 2] * mixingPos[i + 2] + mixingPos[i + 3] * mixingPos[i + 3]) >> this->overlapDividerBits;
573
+	}
822 574
 
823
-    return corr;
575
+	// Normalize result by dividing by sqrt(norm) - this step is easiest 
576
+	// done using floating point operation
577
+	if (!norm)
578
+		norm = 1; // to avoid div by zero
579
+	return corr / std::sqrt(static_cast<double>(norm));
824 580
 }
825 581
 
826
-#endif // INTEGER_SAMPLES
582
+#endif // SOUNDTOUCH_INTEGER_SAMPLES
827 583
 
828 584
 //////////////////////////////////////////////////////////////////////////////
829 585
 //
830 586
 // Floating point arithmetics specific algorithm implementations.
831 587
 //
832 588
 
833
-#ifdef FLOAT_SAMPLES
834
-
589
+#ifdef SOUNDTOUCH_FLOAT_SAMPLES
835 590
 
836
-// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
837
-// is faster to calculate
838
-void TDStretch::precalcCorrReferenceStereo()
591
+// Overlaps samples in 'midBuffer' with the samples in 'pInput'
592
+void TDStretch::overlapStereo(float *pOutput, const float *pInput) const
839 593
 {
840
-    int i, cnt2;
841
-    float temp;
842
-
843
-    for (i=0 ; i < (int)overlapLength ;i ++)
844
-    {
845
-        temp = (float)i * (float)(overlapLength - i);
846
-        cnt2 = i * 2;
847
-        pRefMidBuffer[cnt2] = (float)(pMidBuffer[cnt2] * temp);
848
-        pRefMidBuffer[cnt2 + 1] = (float)(pMidBuffer[cnt2 + 1] * temp);
849
-    }
850
-}
594
+	float fScale = 1.0f / this->overlapLength;
851 595
 
596
+	float f1 = 0, f2 = 1.0f;
852 597
 
853
-// Slopes the amplitude of the 'midBuffer' samples so that cross correlation
854
-// is faster to calculate
855
-void TDStretch::precalcCorrReferenceMono()
856
-{
857
-    int i;
858
-    float temp;
598
+	for (int32_t i = 0; i < 2 * this->overlapLength; i += 2)
599
+	{
600
+		pOutput[i] = pInput[i] * f1 + this->pMidBuffer[i] * f2;
601
+		pOutput[i + 1] = pInput[i + 1] * f1 + this->pMidBuffer[i + 1] * f2;
859 602
 
860
-    for (i=0 ; i < (int)overlapLength ;i ++)
861
-    {
862
-        temp = (float)i * (float)(overlapLength - i);
863
-        pRefMidBuffer[i] = (float)(pMidBuffer[i] * temp);
864
-    }
603
+		f1 += fScale;
604
+		f2 -= fScale;
605
+	}
865 606
 }
866 607
 
867
-
868
-// SSE-optimized version of the function overlapStereo
869
-void TDStretch::overlapStereo(float *out, const float *in) const
870
-{
871
-    int i;
872
-    uint32_t cnt2;
873
-    float fTemp;
874
-    float fScale;
875
-    float fi;
876
-
877
-    fScale = 1.0f / (float)overlapLength;
878
-
879
-    for (i = 0; i < (int)overlapLength ; i ++)
880
-    {
881
-        fTemp = (float)(overlapLength - i) * fScale;
882
-        fi = (float)i * fScale;
883
-        cnt2 = 2 * i;
884
-        out[cnt2 + 0] = in[cnt2 + 0] * fi + pMidBuffer[cnt2 + 0] * fTemp;
885
-        out[cnt2 + 1] = in[cnt2 + 1] * fi + pMidBuffer[cnt2 + 1] * fTemp;
886
-    }
887
-}
888
-
889
-
890
-/// Calculates overlap period length in samples.
891
-void TDStretch::calculateOverlapLength(uint32_t overlapMS)
608
+/// Calculates overlapInMsec period length in samples.
609
+void TDStretch::calculateOverlapLength(int32_t overlapInMsec)
892 610
 {
893
-    uint32_t newOvl;
611
+	assert(overlapInMsec >= 0);
612
+	uint32_t newOvl = (this->sampleRate * overlapInMsec) / 1000;
613
+	if (newOvl < 16)
614
+		newOvl = 16;
894 615
 
895
-    newOvl = (sampleRate * overlapMS) / 1000;
896
-    if (newOvl < 16) newOvl = 16;
616
+	// must be divisible by 8
617
+	newOvl -= newOvl % 8;
897 618
 
898
-    // must be divisible by 8
899
-    newOvl -= newOvl % 8;
900
-
901
-    acceptNewOverlapLength(newOvl);
619
+	this->acceptNewOverlapLength(newOvl);
902 620
 }
903 621
 
904
-
905
-
906
-double TDStretch::calcCrossCorrMono(const float *mixingPos, const float *compare) const
622
+double TDStretch::calcCrossCorr(const float *mixingPos, const float *compare) const
907 623
 {
908
-    double corr;
909
-    uint32_t i;
910
-
911
-    corr = 0;
912
-    for (i = 1; i < overlapLength; i ++)
913
-    {
914
-        corr += mixingPos[i] * compare[i];
915
-    }
624
+	double corr = 0, norm = 0;
625
+	// Same routine for stereo and mono. For Stereo, unroll by factor of 2.
626
+	// For mono it's same routine yet unrollsd by factor of 4.
627
+	for (int32_t i = 0; i < this->channels * this->overlapLength; i += 4)
628
+	{
629
+		corr += mixingPos[i] * compare[i] + mixingPos[i + 1] * compare[i + 1];
916 630
 
917
-    return corr;
918
-}
631
+		norm += mixingPos[i] * mixingPos[i] +  mixingPos[i + 1] * mixingPos[i + 1];
919 632
 
633
+		// unroll the loop for better CPU efficiency:
634
+		corr += mixingPos[i + 2] * compare[i + 2] + mixingPos[i + 3] * compare[i + 3];
920 635
 
921
-double TDStretch::calcCrossCorrStereo(const float *mixingPos, const float *compare) const
922
-{
923
-    double corr;
924
-    uint32_t i;
925
-
926
-    corr = 0;
927
-    for (i = 2; i < 2 * overlapLength; i += 2)
928
-    {
929
-        corr += mixingPos[i] * compare[i] +
930
-                mixingPos[i + 1] * compare[i + 1];
931
-    }
636
+		norm += mixingPos[i + 2] * mixingPos[i + 2] + mixingPos[i + 3] * mixingPos[i + 3];
637
+	}
932 638
 
933
-    return corr;
639
+	if (norm < 1e-9)
640
+		norm = 1.0; // to avoid div by zero
641
+	return corr / std::sqrt(norm);
934 642
 }
935 643
 
936
-#endif // FLOAT_SAMPLES
644
+#endif // SOUNDTOUCH_FLOAT_SAMPLES
Browse code

Import actual code.

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