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,336 +0,0 @@
1
-//////////////////////////////////////////////////////////////////////////////
2
-///
3
-/// SoundTouch - main class for tempo/pitch/rate adjusting routines.
4
-///
5
-/// Notes:
6
-/// - Initialize the SoundTouch object instance by setting up the sound stream
7
-///   parameters with functions 'setSampleRate' and 'setChannels', then set
8
-///   desired tempo/pitch/rate settings with the corresponding functions.
9
-///
10
-/// - The SoundTouch class behaves like a first-in-first-out pipeline: The
11
-///   samples that are to be processed are fed into one of the pipe by calling
12
-///   function 'putSamples', while the ready processed samples can be read
13
-///   from the other end of the pipeline with function 'receiveSamples'.
14
-///
15
-/// - The SoundTouch processing classes require certain sized 'batches' of
16
-///   samples in order to process the sound. For this reason the classes buffer
17
-///   incoming samples until there are enough of samples available for
18
-///   processing, then they carry out the processing step and consequently
19
-///   make the processed samples available for outputting.
20
-///
21
-/// - For the above reason, the processing routines introduce a certain
22
-///   'latency' between the input and output, so that the samples input to
23
-///   SoundTouch may not be immediately available in the output, and neither
24
-///   the amount of outputtable samples may not immediately be in direct
25
-///   relationship with the amount of previously input samples.
26
-///
27
-/// - The tempo/pitch/rate control parameters can be altered during processing.
28
-///   Please notice though that they aren't currently protected by semaphores,
29
-///   so in multi-thread application external semaphore protection may be
30
-///   required.
31
-///
32
-/// - This class utilizes classes 'TDStretch' for tempo change (without modifying
33
-///   pitch) and 'RateTransposer' for changing the playback rate (that is, both
34
-///   tempo and pitch in the same ratio) of the sound. The third available control
35
-///   'pitch' (change pitch but maintain tempo) is produced by a combination of
36
-///   combining the two other controls.
37
-///
38
-/// Author        : Copyright (c) Olli Parviainen
39
-/// Author e-mail : oparviai 'at' iki.fi
40
-/// SoundTouch WWW: http://www.surina.net/soundtouch
41
-///
42
-////////////////////////////////////////////////////////////////////////////////
43
-//
44
-// Last changed  : $Date: 2012-06-13 16:29:53 -0300 (qua, 13 jun 2012) $
45
-// File revision : $Revision: 4 $
46
-//
47
-// $Id: SoundTouch.cpp 143 2012-06-13 19:29:53Z oparviai $
48
-//
49
-////////////////////////////////////////////////////////////////////////////////
50
-//
51
-// License :
52
-//
53
-//  SoundTouch audio processing library
54
-//  Copyright (c) Olli Parviainen
55
-//
56
-//  This library is free software; you can redistribute it and/or
57
-//  modify it under the terms of the GNU Lesser General Public
58
-//  License as published by the Free Software Foundation; either
59
-//  version 2.1 of the License, or (at your option) any later version.
60
-//
61
-//  This library is distributed in the hope that it will be useful,
62
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
63
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
64
-//  Lesser General Public License for more details.
65
-//
66
-//  You should have received a copy of the GNU Lesser General Public
67
-//  License along with this library; if not, write to the Free Software
68
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
69
-//
70
-////////////////////////////////////////////////////////////////////////////////
71
-
72
-#include "XSFCommon.h"
73
-
74
-#include <stdexcept>
75
-#include <cassert>
76
-#include <cstdlib>
77
-#include <cstring>
78
-#include <cstdio>
79
-#include "SoundTouch.h"
80
-#include "cpu_detect.h"
81
-
82
-using namespace soundtouch;
83
-
84
-SoundTouch::SoundTouch()
85
-{
86
-	// Initialize rate transposer and tempo changer instances
87
-
88
-	this->pRateTransposer.reset(RateTransposer::newInstance());
89
-	this->pTDStretch.reset(TDStretch::newInstance());
90
-
91
-	this->setOutPipe(this->pTDStretch.get());
92
-
93
-	this->rate = this->tempo = 0;
94
-
95
-	this->virtualPitch = this->virtualRate = this->virtualTempo = 1.0;
96
-
97
-	this->calcEffectiveRateAndTempo();
98
-
99
-	this->channels = 0;
100
-	this->bSrateSet = false;
101
-}
102
-
103
-// Sets the number of channels, 1 = mono, 2 = stereo
104
-void SoundTouch::setChannels(uint32_t numChannels)
105
-{
106
-	if (numChannels != 1 && numChannels != 2)
107
-		throw std::runtime_error("Illegal number of channels");
108
-	this->channels = numChannels;
109
-	this->pRateTransposer->setChannels(numChannels);
110
-	this->pTDStretch->setChannels(numChannels);
111
-}
112
-
113
-// Sets new rate control value. Normal rate = 1.0, smaller values
114
-// represent slower rate, larger faster rates.
115
-void SoundTouch::setRate(float newRate)
116
-{
117
-	this->virtualRate = newRate;
118
-	this->calcEffectiveRateAndTempo();
119
-}
120
-
121
-// Sets new tempo control value. Normal tempo = 1.0, smaller values
122
-// represent slower tempo, larger faster tempo.
123
-void SoundTouch::setTempo(float newTempo)
124
-{
125
-	this->virtualTempo = newTempo;
126
-	this->calcEffectiveRateAndTempo();
127
-}
128
-
129
-// Calculates 'effective' rate and tempo values from the
130
-// nominal control values.
131
-void SoundTouch::calcEffectiveRateAndTempo()
132
-{
133
-	float oldTempo = this->tempo;
134
-	float oldRate = this->rate;
135
-
136
-	this->tempo = this->virtualTempo / this->virtualPitch;
137
-	this->rate = this->virtualPitch * this->virtualRate;
138
-
139
-	if (!fEqual(this->rate, oldRate))
140
-		this->pRateTransposer->setRate(this->rate);
141
-	if (!fEqual(this->tempo, oldTempo))
142
-		this->pTDStretch->setTempo(this->tempo);
143
-
144
-#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
145
-	if (this->rate <= 1.0f)
146
-	{
147
-		if (this->output != this->pTDStretch.get())
148
-		{
149
-			FIFOSamplePipe *tempoOut;
150
-
151
-			assert(this->output == this->pRateTransposer.get());
152
-			// move samples in the current output buffer to the output of pTDStretch
153
-			tempoOut = this->pTDStretch->getOutput();
154
-			tempoOut->moveSamples(*this->output);
155
-			// move samples in pitch transposer's store buffer to tempo changer's input
156
-			this->pTDStretch->moveSamples(*this->pRateTransposer->getStore());
157
-
158
-			this->output = pTDStretch.get();
159
-		}
160
-	}
161
-	else
162
-#endif
163
-	{
164
-		if (this->output != this->pRateTransposer.get())
165
-		{
166
-			assert(this->output == this->pTDStretch.get());
167
-			// move samples in the current output buffer to the output of pRateTransposer
168
-			FIFOSamplePipe *transOut = this->pRateTransposer->getOutput();
169
-			transOut->moveSamples(*this->output);
170
-			// move samples in tempo changer's input to pitch transposer's input
171
-			this->pRateTransposer->moveSamples(*this->pTDStretch->getInput());
172
-
173
-			this->output = this->pRateTransposer.get();
174
-		}
175
-	}
176
-}
177
-
178
-// Sets sample rate.
179
-void SoundTouch::setSampleRate(uint32_t srate)
180
-{
181
-	this->bSrateSet = true;
182
-	// set sample rate, leave other tempo changer parameters as they are.
183
-	this->pTDStretch->setParameters(srate);
184
-}
185
-
186
-// Adds 'numSamples' pcs of samples from the 'samples' memory position into
187
-// the input of the object.
188
-void SoundTouch::putSamples(const SAMPLETYPE *samples, uint32_t nSamples)
189
-{
190
-	if (!this->bSrateSet)
191
-		throw std::runtime_error("SoundTouch : Sample rate not defined");
192
-	else if (!this->channels)
193
-		throw std::runtime_error("SoundTouch : Number of channels not defined");
194
-
195
-	// Transpose the rate of the new samples if necessary
196
-	/* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value...
197
-	if (this->rate == 1.0f)
198
-	{
199
-		// The rate value is same as the original, simply evaluate the tempo changer.
200
-		assert(this->output == this->pTDStretch.get());
201
-		if (!this->pRateTransposer->isEmpty())
202
-		{
203
-			// yet flush the last samples in the pitch transposer buffer
204
-			// (may happen if 'rate' changes from a non-zero value to zero)
205
-			this->pTDStretch->moveSamples(*this->pRateTransposer);
206
-		}
207
-		this->pTDStretch->putSamples(samples, nSamples);
208
-	}*/
209
-#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
210
-	else if (this->rate <= 1.0f)
211
-	{
212
-		// transpose the rate down, output the transposed sound to tempo changer buffer
213
-		assert(this->output == this->pTDStretch.get());
214
-		this->pRateTransposer->putSamples(samples, nSamples);
215
-		this->pTDStretch->moveSamples(*this->pRateTransposer);
216
-	}
217
-	else
218
-#endif
219
-	{
220
-		assert(this->rate > 1.0f);
221
-		// evaluate the tempo changer, then transpose the rate up,
222
-		assert(this->output == this->pRateTransposer.get());
223
-		this->pTDStretch->putSamples(samples, nSamples);
224
-		this->pRateTransposer->moveSamples(*this->pTDStretch);
225
-	}
226
-}
227
-
228
-// Flushes the last samples from the processing pipeline to the output.
229
-// Clears also the internal processing buffers.
230
-//
231
-// Note: This function is meant for extracting the last samples of a sound
232
-// stream. This function may introduce additional blank samples in the end
233
-// of the sound stream, and thus it's not recommended to call this function
234
-// in the middle of a sound stream.
235
-void SoundTouch::flush()
236
-{
237
-	// check how many samples still await processing, and scale
238
-	// that by tempo & rate to get expected output sample count
239
-	int32_t nUnprocessed = this->numUnprocessedSamples();
240
-	nUnprocessed = static_cast<int32_t>(nUnprocessed / (tempo * rate) + 0.5);
241
-
242
-	int32_t nOut = this->numSamples(); // ready samples currently in buffer ...
243
-	nOut += nUnprocessed; // ... and how many we expect there to be in the end
244
-
245
-	// "Push" the last active samples out from the processing pipeline by
246
-	// feeding blank samples into the processing pipeline until new,
247
-	// processed samples appear in the output (not however, more than
248
-	// 8ksamples in any case)
249
-	SAMPLETYPE buff[128] = { 0 };
250
-	for (int i = 0; i < 128; ++i)
251
-	{
252
-		this->putSamples(buff, 64);
253
-		if (static_cast<int32_t>(this->numSamples()) >= nOut)
254
-		{
255
-			// Enough new samples have appeared into the output!
256
-			// As samples come from processing with bigger chunks, now truncate it
257
-			// back to maximum "nOut" samples to improve duration accuracy
258
-			this->adjustAmountOfSamples(nOut);
259
-
260
-			// finish
261
-			break;
262
-		}
263
-	}
264
-
265
-	// Clear working buffers
266
-	this->pRateTransposer->clear();
267
-	this->pTDStretch->clearInput();
268
-	// yet leave the 'tempoChanger' output intouched as that's where the
269
-	// flushed samples are!
270
-}
271
-
272
-// Changes a setting controlling the processing system behaviour. See the
273
-// 'SETTING_...' defines for available setting ID's.
274
-bool SoundTouch::setSetting(int32_t settingId, int32_t value)
275
-{
276
-	int32_t sampleRate, sequenceMs, seekWindowMs, overlapMs;
277
-
278
-	// read current tdstretch routine parameters
279
-	pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs);
280
-
281
-	switch (settingId)
282
-	{
283
-		case SETTING_USE_AA_FILTER:
284
-			// enables / disabless anti-alias filter
285
-			this->pRateTransposer->enableAAFilter(!!value);
286
-			return true;
287
-
288
-		case SETTING_AA_FILTER_LENGTH:
289
-			// sets anti-alias filter length
290
-			this->pRateTransposer->getAAFilter()->setLength(value);
291
-			return true;
292
-
293
-		case SETTING_USE_QUICKSEEK:
294
-			// enables / disables tempo routine quick seeking algorithm
295
-			this->pTDStretch->enableQuickSeek(!!value);
296
-			return true;
297
-
298
-		case SETTING_SEQUENCE_MS:
299
-			// change time-stretch sequence duration parameter
300
-			this->pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs);
301
-			return true;
302
-
303
-		case SETTING_SEEKWINDOW_MS:
304
-			// change time-stretch seek window length parameter
305
-			this->pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs);
306
-			return true;
307
-
308
-		case SETTING_OVERLAP_MS:
309
-			// change time-stretch overlap length parameter
310
-			this->pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value);
311
-			return true;
312
-
313
-		default:
314
-			return false;
315
-	}
316
-}
317
-
318
-// Clears all the samples in the object's output and internal processing
319
-// buffers.
320
-void SoundTouch::clear()
321
-{
322
-	this->pRateTransposer->clear();
323
-	this->pTDStretch->clear();
324
-}
325
-
326
-/// Returns number of samples currently unprocessed.
327
-uint32_t SoundTouch::numUnprocessedSamples() const
328
-{
329
-	if (this->pTDStretch)
330
-	{
331
-		FIFOSamplePipe *psp = this->pTDStretch->getInput();
332
-		if (psp)
333
-			return psp->numSamples();
334
-	}
335
-	return 0;
336
-}
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
... ...
@@ -77,8 +77,6 @@
77 77
 #include <cstring>
78 78
 #include <cstdio>
79 79
 #include "SoundTouch.h"
80
-#include "TDStretch.h"
81
-#include "RateTransposer.h"
82 80
 #include "cpu_detect.h"
83 81
 
84 82
 using namespace soundtouch;
... ...
@@ -144,7 +142,7 @@ void SoundTouch::calcEffectiveRateAndTempo()
144 142
 		this->pTDStretch->setTempo(this->tempo);
145 143
 
146 144
 #ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
147
-	if (this->rate <= 1.0f) 
145
+	if (this->rate <= 1.0f)
148 146
 	{
149 147
 		if (this->output != this->pTDStretch.get())
150 148
 		{
... ...
@@ -256,7 +254,7 @@ void SoundTouch::flush()
256 254
 		{
257 255
 			// Enough new samples have appeared into the output!
258 256
 			// As samples come from processing with bigger chunks, now truncate it
259
-			// back to maximum "nOut" samples to improve duration accuracy 
257
+			// back to maximum "nOut" samples to improve duration accuracy
260 258
 			this->adjustAmountOfSamples(nOut);
261 259
 
262 260
 			// finish
Browse code

Added Lanczos interpolation to the NCSF plugin, and cleaned up a bit of the other code, as well as removing pstdint.h since it's no longer needed.

Naram Qashat authored on 2013/04/23 20:29:21
Showing 1 changed files
... ...
@@ -328,7 +328,7 @@ void SoundTouch::clear()
328 328
 /// Returns number of samples currently unprocessed.
329 329
 uint32_t SoundTouch::numUnprocessedSamples() const
330 330
 {
331
-	if (this->pTDStretch.get())
331
+	if (this->pTDStretch)
332 332
 	{
333 333
 		FIFOSamplePipe *psp = this->pTDStretch->getInput();
334 334
 		if (psp)
Browse code

Some more code cleanup in DeSmuME.

Naram Qashat authored on 2013/04/23 00:07:41
Showing 1 changed files
... ...
@@ -102,10 +102,6 @@ SoundTouch::SoundTouch()
102 102
 	this->bSrateSet = false;
103 103
 }
104 104
 
105
-SoundTouch::~SoundTouch()
106
-{
107
-}
108
-
109 105
 // Sets the number of channels, 1 = mono, 2 = stereo
110 106
 void SoundTouch::setChannels(uint32_t numChannels)
111 107
 {
... ...
@@ -124,14 +120,6 @@ void SoundTouch::setRate(float newRate)
124 120
 	this->calcEffectiveRateAndTempo();
125 121
 }
126 122
 
127
-// Sets new rate control value as a difference in percents compared
128
-// to the original rate (-50 .. +100 %)
129
-void SoundTouch::setRateChange(float newRate)
130
-{
131
-	this->virtualRate = 1.0f + 0.01f * newRate;
132
-	this->calcEffectiveRateAndTempo();
133
-}
134
-
135 123
 // Sets new tempo control value. Normal tempo = 1.0, smaller values
136 124
 // represent slower tempo, larger faster tempo.
137 125
 void SoundTouch::setTempo(float newTempo)
... ...
@@ -140,42 +128,6 @@ void SoundTouch::setTempo(float newTempo)
140 128
 	this->calcEffectiveRateAndTempo();
141 129
 }
142 130
 
143
-// Sets new tempo control value as a difference in percents compared
144
-// to the original tempo (-50 .. +100 %)
145
-void SoundTouch::setTempoChange(float newTempo)
146
-{
147
-	this->virtualTempo = 1.0f + 0.01f * newTempo;
148
-	this->calcEffectiveRateAndTempo();
149
-}
150
-
151
-// Sets new pitch control value. Original pitch = 1.0, smaller values
152
-// represent lower pitches, larger values higher pitch.
153
-void SoundTouch::setPitch(float newPitch)
154
-{
155
-	this->virtualPitch = newPitch;
156
-	this->calcEffectiveRateAndTempo();
157
-}
158
-
159
-// Sets pitch change in octaves compared to the original pitch
160
-// (-1.00 .. +1.00)
161
-void SoundTouch::setPitchOctaves(float newPitch)
162
-{
163
-	this->virtualPitch = std::exp(0.69314718056f * newPitch);
164
-	this->calcEffectiveRateAndTempo();
165
-}
166
-
167
-// Sets pitch change in semi-tones compared to the original pitch
168
-// (-12 .. +12)
169
-void SoundTouch::setPitchSemiTones(int newPitch)
170
-{
171
-	this->setPitchOctaves(newPitch / 12.0f);
172
-}
173
-
174
-void SoundTouch::setPitchSemiTones(float newPitch)
175
-{
176
-	this->setPitchOctaves(newPitch / 12.0f);
177
-}
178
-
179 131
 // Calculates 'effective' rate and tempo values from the
180 132
 // nominal control values.
181 133
 void SoundTouch::calcEffectiveRateAndTempo()
... ...
@@ -365,48 +317,6 @@ bool SoundTouch::setSetting(int32_t settingId, int32_t value)
365 317
 	}
366 318
 }
367 319
 
368
-// Reads a setting controlling the processing system behaviour. See the
369
-// 'SETTING_...' defines for available setting ID's.
370
-//
371
-// Returns the setting value.
372
-int32_t SoundTouch::getSetting(int32_t settingId) const
373
-{
374
-	int32_t temp;
375
-
376
-	switch (settingId)
377
-	{
378
-		case SETTING_USE_AA_FILTER:
379
-			return this->pRateTransposer->isAAFilterEnabled();
380
-
381
-		case SETTING_AA_FILTER_LENGTH:
382
-			return this->pRateTransposer->getAAFilter()->getLength();
383
-
384
-		case SETTING_USE_QUICKSEEK:
385
-			return this->pTDStretch->isQuickSeekEnabled();
386
-
387
-		case SETTING_SEQUENCE_MS:
388
-			this->pTDStretch->getParameters(nullptr, &temp, nullptr, nullptr);
389
-			return temp;
390
-
391
-		case SETTING_SEEKWINDOW_MS:
392
-			this->pTDStretch->getParameters(nullptr, nullptr, &temp, nullptr);
393
-			return temp;
394
-
395
-		case SETTING_OVERLAP_MS:
396
-			this->pTDStretch->getParameters(nullptr, nullptr, nullptr, &temp);
397
-			return temp;
398
-
399
-		case SETTING_NOMINAL_INPUT_SEQUENCE:
400
-			return this->pTDStretch->getInputSampleReq();
401
-
402
-		case SETTING_NOMINAL_OUTPUT_SEQUENCE:
403
-			return this->pTDStretch->getOutputBatchSize();
404
-
405
-		default:
406
-			return 0;
407
-	}
408
-}
409
-
410 320
 // Clears all the samples in the object's output and internal processing
411 321
 // buffers.
412 322
 void SoundTouch::clear()
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
... ...
@@ -112,8 +112,8 @@ void SoundTouch::setChannels(uint32_t numChannels)
112 112
 	if (numChannels != 1 && numChannels != 2)
113 113
 		throw std::runtime_error("Illegal number of channels");
114 114
 	this->channels = numChannels;
115
-	this->pRateTransposer->setChannels(static_cast<int32_t>(numChannels));
116
-	this->pTDStretch->setChannels(static_cast<int32_t>(numChannels));
115
+	this->pRateTransposer->setChannels(numChannels);
116
+	this->pTDStretch->setChannels(numChannels);
117 117
 }
118 118
 
119 119
 // Sets new rate control value. Normal rate = 1.0, smaller values
... ...
@@ -230,7 +230,7 @@ void SoundTouch::setSampleRate(uint32_t srate)
230 230
 {
231 231
 	this->bSrateSet = true;
232 232
 	// set sample rate, leave other tempo changer parameters as they are.
233
-	this->pTDStretch->setParameters(static_cast<int32_t>(srate));
233
+	this->pTDStretch->setParameters(srate);
234 234
 }
235 235
 
236 236
 // Adds 'numSamples' pcs of samples from the 'samples' memory position into
... ...
@@ -300,7 +300,7 @@ void SoundTouch::flush()
300 300
 	for (int i = 0; i < 128; ++i)
301 301
 	{
302 302
 		this->putSamples(buff, 64);
303
-		if (static_cast<int32_t>(numSamples()) >= nOut)
303
+		if (static_cast<int32_t>(this->numSamples()) >= nOut)
304 304
 		{
305 305
 			// Enough new samples have appeared into the output!
306 306
 			// As samples come from processing with bigger chunks, now truncate it
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
... ...
@@ -41,10 +41,10 @@
41 41
 ///
42 42
 ////////////////////////////////////////////////////////////////////////////////
43 43
 //
44
-// Last changed  : $Date: 2006/02/05 16:44:06 $
45
-// File revision : $Revision: 1.13 $
44
+// Last changed  : $Date: 2012-06-13 16:29:53 -0300 (qua, 13 jun 2012) $
45
+// File revision : $Revision: 4 $
46 46
 //
47
-// $Id: SoundTouch.cpp,v 1.13 2006/02/05 16:44:06 Olli Exp $
47
+// $Id: SoundTouch.cpp 143 2012-06-13 19:29:53Z oparviai $
48 48
 //
49 49
 ////////////////////////////////////////////////////////////////////////////////
50 50
 //
... ...
@@ -76,7 +76,6 @@
76 76
 #include <cstdlib>
77 77
 #include <cstring>
78 78
 #include <cstdio>
79
-
80 79
 #include "SoundTouch.h"
81 80
 #include "TDStretch.h"
82 81
 #include "RateTransposer.h"
... ...
@@ -84,253 +83,198 @@
84 83
 
85 84
 using namespace soundtouch;
86 85
 
87
-/// Print library version string
88
-extern "C" void soundtouch_ac_test()
89
-{
90
-    printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION);
91
-}
92
-
93
-
94 86
 SoundTouch::SoundTouch()
95 87
 {
96
-    // Initialize rate transposer and tempo changer instances
88
+	// Initialize rate transposer and tempo changer instances
97 89
 
98
-    pRateTransposer = RateTransposer::newInstance();
99
-    pTDStretch = TDStretch::newInstance();
90
+	this->pRateTransposer.reset(RateTransposer::newInstance());
91
+	this->pTDStretch.reset(TDStretch::newInstance());
100 92
 
101
-    setOutPipe(pTDStretch);
93
+	this->setOutPipe(this->pTDStretch.get());
102 94
 
103
-    rate = tempo = 0;
95
+	this->rate = this->tempo = 0;
104 96
 
105
-    virtualPitch =
106
-    virtualRate =
107
-    virtualTempo = 1.0;
97
+	this->virtualPitch = this->virtualRate = this->virtualTempo = 1.0;
108 98
 
109
-    calcEffectiveRateAndTempo();
99
+	this->calcEffectiveRateAndTempo();
110 100
 
111
-    channels = 0;
112
-    bSrateSet = false;
101
+	this->channels = 0;
102
+	this->bSrateSet = false;
113 103
 }
114 104
 
115
-
116
-
117 105
 SoundTouch::~SoundTouch()
118 106
 {
119
-    delete pRateTransposer;
120
-    delete pTDStretch;
121 107
 }
122 108
 
123
-
124
-
125
-/// Get SoundTouch library version string
126
-const char *SoundTouch::getVersionString()
127
-{
128
-    static const char *_version = SOUNDTOUCH_VERSION;
129
-
130
-    return _version;
131
-}
132
-
133
-
134
-/// Get SoundTouch library version Id
135
-uint32_t SoundTouch::getVersionId()
136
-{
137
-    return SOUNDTOUCH_VERSION_ID;
138
-}
139
-
140
-
141 109
 // Sets the number of channels, 1 = mono, 2 = stereo
142 110
 void SoundTouch::setChannels(uint32_t numChannels)
143 111
 {
144
-    if (numChannels != 1 && numChannels != 2)
145
-    {
146
-        throw std::runtime_error("Illegal number of channels");
147
-    }
148
-    channels = numChannels;
149
-    pRateTransposer->setChannels(numChannels);
150
-    pTDStretch->setChannels(numChannels);
112
+	if (numChannels != 1 && numChannels != 2)
113
+		throw std::runtime_error("Illegal number of channels");
114
+	this->channels = numChannels;
115
+	this->pRateTransposer->setChannels(static_cast<int32_t>(numChannels));
116
+	this->pTDStretch->setChannels(static_cast<int32_t>(numChannels));
151 117
 }
152 118
 
153
-
154
-
155 119
 // Sets new rate control value. Normal rate = 1.0, smaller values
156 120
 // represent slower rate, larger faster rates.
157 121
 void SoundTouch::setRate(float newRate)
158 122
 {
159
-    virtualRate = newRate;
160
-    calcEffectiveRateAndTempo();
123
+	this->virtualRate = newRate;
124
+	this->calcEffectiveRateAndTempo();
161 125
 }
162 126
 
163
-
164
-
165 127
 // Sets new rate control value as a difference in percents compared
166 128
 // to the original rate (-50 .. +100 %)
167 129
 void SoundTouch::setRateChange(float newRate)
168 130
 {
169
-    virtualRate = 1.0f + 0.01f * newRate;
170
-    calcEffectiveRateAndTempo();
131
+	this->virtualRate = 1.0f + 0.01f * newRate;
132
+	this->calcEffectiveRateAndTempo();
171 133
 }
172 134
 
173
-
174
-
175 135
 // Sets new tempo control value. Normal tempo = 1.0, smaller values
176 136
 // represent slower tempo, larger faster tempo.
177 137
 void SoundTouch::setTempo(float newTempo)
178 138
 {
179
-    virtualTempo = newTempo;
180
-    calcEffectiveRateAndTempo();
139
+	this->virtualTempo = newTempo;
140
+	this->calcEffectiveRateAndTempo();
181 141
 }
182 142
 
183
-
184
-
185 143
 // Sets new tempo control value as a difference in percents compared
186 144
 // to the original tempo (-50 .. +100 %)
187 145
 void SoundTouch::setTempoChange(float newTempo)
188 146
 {
189
-    virtualTempo = 1.0f + 0.01f * newTempo;
190
-    calcEffectiveRateAndTempo();
147
+	this->virtualTempo = 1.0f + 0.01f * newTempo;
148
+	this->calcEffectiveRateAndTempo();
191 149
 }
192 150
 
193
-
194
-
195 151
 // Sets new pitch control value. Original pitch = 1.0, smaller values
196 152
 // represent lower pitches, larger values higher pitch.
197 153
 void SoundTouch::setPitch(float newPitch)
198 154
 {
199
-    virtualPitch = newPitch;
200
-    calcEffectiveRateAndTempo();
155
+	this->virtualPitch = newPitch;
156
+	this->calcEffectiveRateAndTempo();
201 157
 }
202 158
 
203
-
204
-
205 159
 // Sets pitch change in octaves compared to the original pitch
206 160
 // (-1.00 .. +1.00)
207 161
 void SoundTouch::setPitchOctaves(float newPitch)
208 162
 {
209
-    virtualPitch = (float)exp(0.69314718056f * newPitch);
210
-    calcEffectiveRateAndTempo();
163
+	this->virtualPitch = std::exp(0.69314718056f * newPitch);
164
+	this->calcEffectiveRateAndTempo();
211 165
 }
212 166
 
213
-
214
-
215 167
 // Sets pitch change in semi-tones compared to the original pitch
216 168
 // (-12 .. +12)
217 169
 void SoundTouch::setPitchSemiTones(int newPitch)
218 170
 {
219
-    setPitchOctaves((float)newPitch / 12.0f);
171
+	this->setPitchOctaves(newPitch / 12.0f);
220 172
 }
221 173
 
222
-
223
-
224 174
 void SoundTouch::setPitchSemiTones(float newPitch)
225 175
 {
226
-    setPitchOctaves(newPitch / 12.0f);
176
+	this->setPitchOctaves(newPitch / 12.0f);
227 177
 }
228 178
 
229
-
230 179
 // Calculates 'effective' rate and tempo values from the
231 180
 // nominal control values.
232 181
 void SoundTouch::calcEffectiveRateAndTempo()
233 182
 {
234
-    float oldTempo = tempo;
235
-    float oldRate = rate;
236
-
237
-    tempo = virtualTempo / virtualPitch;
238
-    rate = virtualPitch * virtualRate;
239
-
240
-    if (!fEqual(rate, oldRate)) pRateTransposer->setRate(rate);
241
-    if (!fEqual(tempo, oldTempo)) pTDStretch->setTempo(tempo);
242
-
243
-    if (rate > 1.0f)
244
-    {
245
-        if (output != pRateTransposer)
246
-        {
247
-            FIFOSamplePipe *transOut;
248
-
249
-            assert(output == pTDStretch);
250
-            // move samples in the current output buffer to the output of pRateTransposer
251
-            transOut = pRateTransposer->getOutput();
252
-            transOut->moveSamples(*output);
253
-            // move samples in tempo changer's input to pitch transposer's input
254
-            pRateTransposer->moveSamples(*pTDStretch->getInput());
255
-
256
-            output = pRateTransposer;
257
-        }
258
-    }
259
-    else
260
-    {
261
-        if (output != pTDStretch)
262
-        {
263
-            FIFOSamplePipe *tempoOut;
264
-
265
-            assert(output == pRateTransposer);
266
-            // move samples in the current output buffer to the output of pTDStretch
267
-            tempoOut = pTDStretch->getOutput();
268
-            tempoOut->moveSamples(*output);
269
-            // move samples in pitch transposer's store buffer to tempo changer's input
270
-            pTDStretch->moveSamples(*pRateTransposer->getStore());
271
-
272
-            output = pTDStretch;
273
-
274
-        }
275
-    }
183
+	float oldTempo = this->tempo;
184
+	float oldRate = this->rate;
185
+
186
+	this->tempo = this->virtualTempo / this->virtualPitch;
187
+	this->rate = this->virtualPitch * this->virtualRate;
188
+
189
+	if (!fEqual(this->rate, oldRate))
190
+		this->pRateTransposer->setRate(this->rate);
191
+	if (!fEqual(this->tempo, oldTempo))
192
+		this->pTDStretch->setTempo(this->tempo);
193
+
194
+#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
195
+	if (this->rate <= 1.0f) 
196
+	{
197
+		if (this->output != this->pTDStretch.get())
198
+		{
199
+			FIFOSamplePipe *tempoOut;
200
+
201
+			assert(this->output == this->pRateTransposer.get());
202
+			// move samples in the current output buffer to the output of pTDStretch
203
+			tempoOut = this->pTDStretch->getOutput();
204
+			tempoOut->moveSamples(*this->output);
205
+			// move samples in pitch transposer's store buffer to tempo changer's input
206
+			this->pTDStretch->moveSamples(*this->pRateTransposer->getStore());
207
+
208
+			this->output = pTDStretch.get();
209
+		}
210
+	}
211
+	else
212
+#endif
213
+	{
214
+		if (this->output != this->pRateTransposer.get())
215
+		{
216
+			assert(this->output == this->pTDStretch.get());
217
+			// move samples in the current output buffer to the output of pRateTransposer
218
+			FIFOSamplePipe *transOut = this->pRateTransposer->getOutput();
219
+			transOut->moveSamples(*this->output);
220
+			// move samples in tempo changer's input to pitch transposer's input
221
+			this->pRateTransposer->moveSamples(*this->pTDStretch->getInput());
222
+
223
+			this->output = this->pRateTransposer.get();
224
+		}
225
+	}
276 226
 }
277 227
 
278
-
279 228
 // Sets sample rate.
280 229
 void SoundTouch::setSampleRate(uint32_t srate)
281 230
 {
282
-    bSrateSet = true;
283
-    // set sample rate, leave other tempo changer parameters as they are.
284
-    pTDStretch->setParameters(srate);
231
+	this->bSrateSet = true;
232
+	// set sample rate, leave other tempo changer parameters as they are.
233
+	this->pTDStretch->setParameters(static_cast<int32_t>(srate));
285 234
 }
286 235
 
287
-
288 236
 // Adds 'numSamples' pcs of samples from the 'samples' memory position into
289 237
 // the input of the object.
290
-void SoundTouch::putSamples(const SAMPLETYPE *samples, uint32_t numsamples)
238
+void SoundTouch::putSamples(const SAMPLETYPE *samples, uint32_t nSamples)
291 239
 {
292
-    if (bSrateSet == false)
293
-    {
294
-        throw std::runtime_error("SoundTouch : Sample rate not defined");
295
-    }
296
-    else if (channels == 0)
297
-    {
298
-        throw std::runtime_error("SoundTouch : Number of channels not defined");
299
-    }
300
-
301
-    // Transpose the rate of the new samples if necessary
302
-    /* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value...
303
-    if (rate == 1.0f)
304
-    {
305
-        // The rate value is same as the original, simply evaluate the tempo changer.
306
-        assert(output == pTDStretch);
307
-        if (pRateTransposer->isEmpty() == 0)
308
-        {
309
-            // yet flush the last samples in the pitch transposer buffer
310
-            // (may happen if 'rate' changes from a non-zero value to zero)
311
-            pTDStretch->moveSamples(*pRateTransposer);
312
-        }
313
-        pTDStretch->putSamples(samples, numSamples);
314
-    }
315
-    */
316
-    else if (rate <= 1.0f)
317
-    {
318
-        // transpose the rate down, output the transposed sound to tempo changer buffer
319
-        assert(output == pTDStretch);
320
-        pRateTransposer->putSamples(samples, numsamples);
321
-        pTDStretch->moveSamples(*pRateTransposer);
322
-    }
323
-    else
324
-    {
325
-        assert(rate > 1.0f);
326
-        // evaluate the tempo changer, then transpose the rate up,
327
-        assert(output == pRateTransposer);
328
-        pTDStretch->putSamples(samples, numsamples);
329
-        pRateTransposer->moveSamples(*pTDStretch);
330
-    }
240
+	if (!this->bSrateSet)
241
+		throw std::runtime_error("SoundTouch : Sample rate not defined");
242
+	else if (!this->channels)
243
+		throw std::runtime_error("SoundTouch : Number of channels not defined");
244
+
245
+	// Transpose the rate of the new samples if necessary
246
+	/* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value...
247
+	if (this->rate == 1.0f)
248
+	{
249
+		// The rate value is same as the original, simply evaluate the tempo changer.
250
+		assert(this->output == this->pTDStretch.get());
251
+		if (!this->pRateTransposer->isEmpty())
252
+		{
253
+			// yet flush the last samples in the pitch transposer buffer
254
+			// (may happen if 'rate' changes from a non-zero value to zero)
255
+			this->pTDStretch->moveSamples(*this->pRateTransposer);
256
+		}
257
+		this->pTDStretch->putSamples(samples, nSamples);
258
+	}*/
259
+#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
260
+	else if (this->rate <= 1.0f)
261
+	{
262
+		// transpose the rate down, output the transposed sound to tempo changer buffer
263
+		assert(this->output == this->pTDStretch.get());
264
+		this->pRateTransposer->putSamples(samples, nSamples);
265
+		this->pTDStretch->moveSamples(*this->pRateTransposer);
266
+	}
267
+	else
268
+#endif
269
+	{
270
+		assert(this->rate > 1.0f);
271
+		// evaluate the tempo changer, then transpose the rate up,
272
+		assert(this->output == this->pRateTransposer.get());
273
+		this->pTDStretch->putSamples(samples, nSamples);
274
+		this->pRateTransposer->moveSamples(*this->pTDStretch);
275
+	}
331 276
 }
332 277
 
333
-
334 278
 // Flushes the last samples from the processing pipeline to the output.
335 279
 // Clears also the internal processing buffers.
336 280
 //
... ...
@@ -340,136 +284,145 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint32_t numsamples)
340 284
 // in the middle of a sound stream.
341 285
 void SoundTouch::flush()
342 286
 {
343
-    int i;
344
-    uint32_t nOut;
345
-    SAMPLETYPE buff[128];
346
-
347
-    nOut = numSamples();
348
-
349
-    memset(buff, 0, 128 * sizeof(SAMPLETYPE));
350
-    // "Push" the last active samples out from the processing pipeline by
351
-    // feeding blank samples into the processing pipeline until new,
352
-    // processed samples appear in the output (not however, more than
353
-    // 8ksamples in any case)
354
-    for (i = 0; i < 128; i ++)
355
-    {
356
-        putSamples(buff, 64);
357
-        if (numSamples() != nOut) break;  // new samples have appeared in the output!
358
-    }
359
-
360
-    // Clear working buffers
361
-    pRateTransposer->clear();
362
-    pTDStretch->clearInput();
363
-    // yet leave the 'tempoChanger' output intouched as that's where the
364
-    // flushed samples are!
287
+	// check how many samples still await processing, and scale
288
+	// that by tempo & rate to get expected output sample count
289
+	int32_t nUnprocessed = this->numUnprocessedSamples();
290
+	nUnprocessed = static_cast<int32_t>(nUnprocessed / (tempo * rate) + 0.5);
291
+
292
+	int32_t nOut = this->numSamples(); // ready samples currently in buffer ...
293
+	nOut += nUnprocessed; // ... and how many we expect there to be in the end
294
+
295
+	// "Push" the last active samples out from the processing pipeline by
296
+	// feeding blank samples into the processing pipeline until new,
297
+	// processed samples appear in the output (not however, more than
298
+	// 8ksamples in any case)
299
+	SAMPLETYPE buff[128] = { 0 };
300
+	for (int i = 0; i < 128; ++i)
301
+	{
302
+		this->putSamples(buff, 64);
303
+		if (static_cast<int32_t>(numSamples()) >= nOut)
304
+		{
305
+			// Enough new samples have appeared into the output!
306
+			// As samples come from processing with bigger chunks, now truncate it
307
+			// back to maximum "nOut" samples to improve duration accuracy 
308
+			this->adjustAmountOfSamples(nOut);
309
+
310
+			// finish
311
+			break;
312
+		}
313
+	}
314
+
315
+	// Clear working buffers
316
+	this->pRateTransposer->clear();
317
+	this->pTDStretch->clearInput();
318
+	// yet leave the 'tempoChanger' output intouched as that's where the
319
+	// flushed samples are!
365 320
 }
366 321
 
367
-
368 322
 // Changes a setting controlling the processing system behaviour. See the
369 323
 // 'SETTING_...' defines for available setting ID's.
370
-bool SoundTouch::setSetting(uint32_t settingId, uint32_t value)
324
+bool SoundTouch::setSetting(int32_t settingId, int32_t value)
371 325
 {
372
-    uint32_t sampleRate, sequenceMs, seekWindowMs, overlapMs;
373
-
374
-    // read current tdstretch routine parameters
375
-    pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs);
376
-
377
-    switch (settingId)
378
-    {
379
-        case SETTING_USE_AA_FILTER :
380
-            // enables / disabless anti-alias filter
381
-            pRateTransposer->enableAAFilter((value != 0) ? true : false);
382
-            return true;
383
-
384
-        case SETTING_AA_FILTER_LENGTH :
385
-            // sets anti-alias filter length
386
-            pRateTransposer->getAAFilter()->setLength(value);
387
-            return true;
388
-
389
-        case SETTING_USE_QUICKSEEK :
390
-            // enables / disables tempo routine quick seeking algorithm
391
-            pTDStretch->enableQuickSeek((value != 0) ? true : false);
392
-            return true;
393
-
394
-        case SETTING_SEQUENCE_MS:
395
-            // change time-stretch sequence duration parameter
396
-            pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs);
397
-            return true;
398
-
399
-        case SETTING_SEEKWINDOW_MS:
400
-            // change time-stretch seek window length parameter
401
-            pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs);
402
-            return true;
403
-
404
-        case SETTING_OVERLAP_MS:
405
-            // change time-stretch overlap length parameter
406
-            pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value);
407
-            return true;
408
-
409
-        default :
410
-            return false;
411
-    }
326
+	int32_t sampleRate, sequenceMs, seekWindowMs, overlapMs;
327
+
328
+	// read current tdstretch routine parameters
329
+	pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs);
330
+
331
+	switch (settingId)
332
+	{
333
+		case SETTING_USE_AA_FILTER:
334
+			// enables / disabless anti-alias filter
335
+			this->pRateTransposer->enableAAFilter(!!value);
336
+			return true;
337
+
338
+		case SETTING_AA_FILTER_LENGTH:
339
+			// sets anti-alias filter length
340
+			this->pRateTransposer->getAAFilter()->setLength(value);
341
+			return true;
342
+
343
+		case SETTING_USE_QUICKSEEK:
344
+			// enables / disables tempo routine quick seeking algorithm
345
+			this->pTDStretch->enableQuickSeek(!!value);
346
+			return true;
347
+
348
+		case SETTING_SEQUENCE_MS:
349
+			// change time-stretch sequence duration parameter
350
+			this->pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs);
351
+			return true;
352
+
353
+		case SETTING_SEEKWINDOW_MS:
354
+			// change time-stretch seek window length parameter
355
+			this->pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs);
356
+			return true;
357
+
358
+		case SETTING_OVERLAP_MS:
359
+			// change time-stretch overlap length parameter
360
+			this->pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value);
361
+			return true;
362
+
363
+		default:
364
+			return false;
365
+	}
412 366
 }
413 367
 
414
-
415 368
 // Reads a setting controlling the processing system behaviour. See the
416 369
 // 'SETTING_...' defines for available setting ID's.
417 370
 //
418 371
 // Returns the setting value.
419
-uint32_t SoundTouch::getSetting(uint32_t settingId) const
372
+int32_t SoundTouch::getSetting(int32_t settingId) const
420 373
 {
421
-    uint32_t temp;
374
+	int32_t temp;
422 375
 
423
-    switch (settingId)
424
-    {
425
-        case SETTING_USE_AA_FILTER :
426
-            return pRateTransposer->isAAFilterEnabled();
376
+	switch (settingId)
377
+	{
378
+		case SETTING_USE_AA_FILTER:
379
+			return this->pRateTransposer->isAAFilterEnabled();
427 380
 
428
-        case SETTING_AA_FILTER_LENGTH :
429
-            return pRateTransposer->getAAFilter()->getLength();
381
+		case SETTING_AA_FILTER_LENGTH:
382
+			return this->pRateTransposer->getAAFilter()->getLength();
430 383
 
431
-        case SETTING_USE_QUICKSEEK :
432
-            return pTDStretch->isQuickSeekEnabled();
384
+		case SETTING_USE_QUICKSEEK:
385
+			return this->pTDStretch->isQuickSeekEnabled();
433 386
 
434
-        case SETTING_SEQUENCE_MS:
435
-            pTDStretch->getParameters(NULL, &temp, NULL, NULL);
436
-            return temp;
387
+		case SETTING_SEQUENCE_MS:
388
+			this->pTDStretch->getParameters(nullptr, &temp, nullptr, nullptr);
389
+			return temp;
437 390
 
438
-        case SETTING_SEEKWINDOW_MS:
439
-            pTDStretch->getParameters(NULL, NULL, &temp, NULL);
440
-            return temp;
391
+		case SETTING_SEEKWINDOW_MS:
392
+			this->pTDStretch->getParameters(nullptr, nullptr, &temp, nullptr);
393
+			return temp;
441 394
 
442
-        case SETTING_OVERLAP_MS:
443
-            pTDStretch->getParameters(NULL, NULL, NULL, &temp);
444
-            return temp;
395
+		case SETTING_OVERLAP_MS:
396
+			this->pTDStretch->getParameters(nullptr, nullptr, nullptr, &temp);
397
+			return temp;
445 398
 
446
-        default :
447
-            return 0;
448
-    }
449
-}
399
+		case SETTING_NOMINAL_INPUT_SEQUENCE:
400
+			return this->pTDStretch->getInputSampleReq();
401
+
402
+		case SETTING_NOMINAL_OUTPUT_SEQUENCE:
403
+			return this->pTDStretch->getOutputBatchSize();
450 404
 
405
+		default:
406
+			return 0;
407
+	}
408
+}
451 409
 
452 410
 // Clears all the samples in the object's output and internal processing
453 411
 // buffers.
454 412
 void SoundTouch::clear()
455 413
 {
456
-    pRateTransposer->clear();
457
-    pTDStretch->clear();
414
+	this->pRateTransposer->clear();
415
+	this->pTDStretch->clear();
458 416
 }
459 417
 
460
-
461
-
462 418
 /// Returns number of samples currently unprocessed.
463 419
 uint32_t SoundTouch::numUnprocessedSamples() const
464 420
 {
465
-    FIFOSamplePipe * psp;
466
-    if (pTDStretch)
467
-    {
468
-        psp = pTDStretch->getInput();
469
-        if (psp)
470
-        {
471
-            return psp->numSamples();
472
-        }
473
-    }
474
-    return 0;
421
+	if (this->pTDStretch.get())
422
+	{
423
+		FIFOSamplePipe *psp = this->pTDStretch->getInput();
424
+		if (psp)
425
+			return psp->numSamples();
426
+	}
427
+	return 0;
475 428
 }
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,475 @@
1
+//////////////////////////////////////////////////////////////////////////////
2
+///
3
+/// SoundTouch - main class for tempo/pitch/rate adjusting routines.
4
+///
5
+/// Notes:
6
+/// - Initialize the SoundTouch object instance by setting up the sound stream
7
+///   parameters with functions 'setSampleRate' and 'setChannels', then set
8
+///   desired tempo/pitch/rate settings with the corresponding functions.
9
+///
10
+/// - The SoundTouch class behaves like a first-in-first-out pipeline: The
11
+///   samples that are to be processed are fed into one of the pipe by calling
12
+///   function 'putSamples', while the ready processed samples can be read
13
+///   from the other end of the pipeline with function 'receiveSamples'.
14
+///
15
+/// - The SoundTouch processing classes require certain sized 'batches' of
16
+///   samples in order to process the sound. For this reason the classes buffer
17
+///   incoming samples until there are enough of samples available for
18
+///   processing, then they carry out the processing step and consequently
19
+///   make the processed samples available for outputting.
20
+///
21
+/// - For the above reason, the processing routines introduce a certain
22
+///   'latency' between the input and output, so that the samples input to
23
+///   SoundTouch may not be immediately available in the output, and neither
24
+///   the amount of outputtable samples may not immediately be in direct
25
+///   relationship with the amount of previously input samples.
26
+///
27
+/// - The tempo/pitch/rate control parameters can be altered during processing.
28
+///   Please notice though that they aren't currently protected by semaphores,
29
+///   so in multi-thread application external semaphore protection may be
30
+///   required.
31
+///
32
+/// - This class utilizes classes 'TDStretch' for tempo change (without modifying
33
+///   pitch) and 'RateTransposer' for changing the playback rate (that is, both
34
+///   tempo and pitch in the same ratio) of the sound. The third available control
35
+///   'pitch' (change pitch but maintain tempo) is produced by a combination of
36
+///   combining the two other controls.
37
+///
38
+/// Author        : Copyright (c) Olli Parviainen
39
+/// Author e-mail : oparviai 'at' iki.fi
40
+/// SoundTouch WWW: http://www.surina.net/soundtouch
41
+///
42
+////////////////////////////////////////////////////////////////////////////////
43
+//
44
+// Last changed  : $Date: 2006/02/05 16:44:06 $
45
+// File revision : $Revision: 1.13 $
46
+//
47
+// $Id: SoundTouch.cpp,v 1.13 2006/02/05 16:44:06 Olli Exp $
48
+//
49
+////////////////////////////////////////////////////////////////////////////////
50
+//
51
+// License :
52
+//
53
+//  SoundTouch audio processing library
54
+//  Copyright (c) Olli Parviainen
55
+//
56
+//  This library is free software; you can redistribute it and/or
57
+//  modify it under the terms of the GNU Lesser General Public
58
+//  License as published by the Free Software Foundation; either
59
+//  version 2.1 of the License, or (at your option) any later version.
60
+//
61
+//  This library is distributed in the hope that it will be useful,
62
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
63
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
64
+//  Lesser General Public License for more details.
65
+//
66
+//  You should have received a copy of the GNU Lesser General Public
67
+//  License along with this library; if not, write to the Free Software
68
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
69
+//
70
+////////////////////////////////////////////////////////////////////////////////
71
+
72
+#include "XSFCommon.h"
73
+
74
+#include <stdexcept>
75
+#include <cassert>
76
+#include <cstdlib>
77
+#include <cstring>
78
+#include <cstdio>
79
+
80
+#include "SoundTouch.h"
81
+#include "TDStretch.h"
82
+#include "RateTransposer.h"
83
+#include "cpu_detect.h"
84
+
85
+using namespace soundtouch;
86
+
87
+/// Print library version string
88
+extern "C" void soundtouch_ac_test()
89
+{
90
+    printf("SoundTouch Version: %s\n",SOUNDTOUCH_VERSION);
91
+}
92
+
93
+
94
+SoundTouch::SoundTouch()
95
+{
96
+    // Initialize rate transposer and tempo changer instances
97
+
98
+    pRateTransposer = RateTransposer::newInstance();
99
+    pTDStretch = TDStretch::newInstance();
100
+
101
+    setOutPipe(pTDStretch);
102
+
103
+    rate = tempo = 0;
104
+
105
+    virtualPitch =
106
+    virtualRate =
107
+    virtualTempo = 1.0;
108
+
109
+    calcEffectiveRateAndTempo();
110
+
111
+    channels = 0;
112
+    bSrateSet = false;
113
+}
114
+
115
+
116
+
117
+SoundTouch::~SoundTouch()
118
+{
119
+    delete pRateTransposer;
120
+    delete pTDStretch;
121
+}
122
+
123
+
124
+
125
+/// Get SoundTouch library version string
126
+const char *SoundTouch::getVersionString()
127
+{
128
+    static const char *_version = SOUNDTOUCH_VERSION;
129
+
130
+    return _version;
131
+}
132
+
133
+
134
+/// Get SoundTouch library version Id
135
+uint32_t SoundTouch::getVersionId()
136
+{
137
+    return SOUNDTOUCH_VERSION_ID;
138
+}
139
+
140
+
141
+// Sets the number of channels, 1 = mono, 2 = stereo
142
+void SoundTouch::setChannels(uint32_t numChannels)
143
+{
144
+    if (numChannels != 1 && numChannels != 2)
145
+    {
146
+        throw std::runtime_error("Illegal number of channels");
147
+    }
148
+    channels = numChannels;
149
+    pRateTransposer->setChannels(numChannels);
150
+    pTDStretch->setChannels(numChannels);
151
+}
152
+
153
+
154
+
155
+// Sets new rate control value. Normal rate = 1.0, smaller values
156
+// represent slower rate, larger faster rates.
157
+void SoundTouch::setRate(float newRate)
158
+{
159
+    virtualRate = newRate;
160
+    calcEffectiveRateAndTempo();
161
+}
162
+
163
+
164
+
165
+// Sets new rate control value as a difference in percents compared
166
+// to the original rate (-50 .. +100 %)
167
+void SoundTouch::setRateChange(float newRate)
168
+{
169
+    virtualRate = 1.0f + 0.01f * newRate;
170
+    calcEffectiveRateAndTempo();
171
+}
172
+
173
+
174
+
175
+// Sets new tempo control value. Normal tempo = 1.0, smaller values
176
+// represent slower tempo, larger faster tempo.
177
+void SoundTouch::setTempo(float newTempo)
178
+{
179
+    virtualTempo = newTempo;
180
+    calcEffectiveRateAndTempo();
181
+}
182
+
183
+
184
+
185
+// Sets new tempo control value as a difference in percents compared
186
+// to the original tempo (-50 .. +100 %)
187
+void SoundTouch::setTempoChange(float newTempo)
188
+{
189
+    virtualTempo = 1.0f + 0.01f * newTempo;
190
+    calcEffectiveRateAndTempo();
191
+}
192
+
193
+
194
+
195
+// Sets new pitch control value. Original pitch = 1.0, smaller values
196
+// represent lower pitches, larger values higher pitch.
197
+void SoundTouch::setPitch(float newPitch)
198
+{
199
+    virtualPitch = newPitch;
200
+    calcEffectiveRateAndTempo();
201
+}
202
+
203
+
204
+
205
+// Sets pitch change in octaves compared to the original pitch
206
+// (-1.00 .. +1.00)
207
+void SoundTouch::setPitchOctaves(float newPitch)
208
+{
209
+    virtualPitch = (float)exp(0.69314718056f * newPitch);
210
+    calcEffectiveRateAndTempo();
211
+}
212
+
213
+
214
+
215
+// Sets pitch change in semi-tones compared to the original pitch
216
+// (-12 .. +12)
217
+void SoundTouch::setPitchSemiTones(int newPitch)
218
+{
219
+    setPitchOctaves((float)newPitch / 12.0f);
220
+}
221
+
222
+
223
+
224
+void SoundTouch::setPitchSemiTones(float newPitch)
225
+{
226
+    setPitchOctaves(newPitch / 12.0f);
227
+}
228
+
229
+
230
+// Calculates 'effective' rate and tempo values from the
231
+// nominal control values.
232
+void SoundTouch::calcEffectiveRateAndTempo()
233
+{
234
+    float oldTempo = tempo;
235
+    float oldRate = rate;
236
+
237
+    tempo = virtualTempo / virtualPitch;
238
+    rate = virtualPitch * virtualRate;
239
+
240
+    if (!fEqual(rate, oldRate)) pRateTransposer->setRate(rate);
241
+    if (!fEqual(tempo, oldTempo)) pTDStretch->setTempo(tempo);
242
+
243
+    if (rate > 1.0f)
244
+    {
245
+        if (output != pRateTransposer)
246
+        {
247
+            FIFOSamplePipe *transOut;
248
+
249
+            assert(output == pTDStretch);
250
+            // move samples in the current output buffer to the output of pRateTransposer
251
+            transOut = pRateTransposer->getOutput();
252
+            transOut->moveSamples(*output);
253
+            // move samples in tempo changer's input to pitch transposer's input
254
+            pRateTransposer->moveSamples(*pTDStretch->getInput());
255
+
256
+            output = pRateTransposer;
257
+        }
258
+    }
259
+    else
260
+    {
261
+        if (output != pTDStretch)
262
+        {
263
+            FIFOSamplePipe *tempoOut;
264
+
265
+            assert(output == pRateTransposer);
266
+            // move samples in the current output buffer to the output of pTDStretch
267
+            tempoOut = pTDStretch->getOutput();
268
+            tempoOut->moveSamples(*output);
269
+            // move samples in pitch transposer's store buffer to tempo changer's input
270
+            pTDStretch->moveSamples(*pRateTransposer->getStore());
271
+
272
+            output = pTDStretch;
273
+
274
+        }
275
+    }
276
+}
277
+
278
+
279
+// Sets sample rate.
280
+void SoundTouch::setSampleRate(uint32_t srate)
281
+{
282
+    bSrateSet = true;
283
+    // set sample rate, leave other tempo changer parameters as they are.
284
+    pTDStretch->setParameters(srate);
285
+}
286
+
287
+
288
+// Adds 'numSamples' pcs of samples from the 'samples' memory position into
289
+// the input of the object.
290
+void SoundTouch::putSamples(const SAMPLETYPE *samples, uint32_t numsamples)
291
+{
292
+    if (bSrateSet == false)
293
+    {
294
+        throw std::runtime_error("SoundTouch : Sample rate not defined");
295
+    }
296
+    else if (channels == 0)
297
+    {
298
+        throw std::runtime_error("SoundTouch : Number of channels not defined");
299
+    }
300
+
301
+    // Transpose the rate of the new samples if necessary
302
+    /* Bypass the nominal setting - can introduce a click in sound when tempo/pitch control crosses the nominal value...
303
+    if (rate == 1.0f)
304
+    {
305
+        // The rate value is same as the original, simply evaluate the tempo changer.
306
+        assert(output == pTDStretch);
307
+        if (pRateTransposer->isEmpty() == 0)
308
+        {
309
+            // yet flush the last samples in the pitch transposer buffer
310
+            // (may happen if 'rate' changes from a non-zero value to zero)
311
+            pTDStretch->moveSamples(*pRateTransposer);
312
+        }
313
+        pTDStretch->putSamples(samples, numSamples);
314
+    }
315
+    */
316
+    else if (rate <= 1.0f)
317
+    {
318
+        // transpose the rate down, output the transposed sound to tempo changer buffer
319
+        assert(output == pTDStretch);
320
+        pRateTransposer->putSamples(samples, numsamples);
321
+        pTDStretch->moveSamples(*pRateTransposer);
322
+    }
323
+    else
324
+    {
325
+        assert(rate > 1.0f);
326
+        // evaluate the tempo changer, then transpose the rate up,
327
+        assert(output == pRateTransposer);
328
+        pTDStretch->putSamples(samples, numsamples);
329
+        pRateTransposer->moveSamples(*pTDStretch);
330
+    }
331
+}
332
+
333
+
334
+// Flushes the last samples from the processing pipeline to the output.
335
+// Clears also the internal processing buffers.
336
+//
337
+// Note: This function is meant for extracting the last samples of a sound
338
+// stream. This function may introduce additional blank samples in the end
339
+// of the sound stream, and thus it's not recommended to call this function
340
+// in the middle of a sound stream.
341
+void SoundTouch::flush()
342
+{
343
+    int i;
344
+    uint32_t nOut;
345
+    SAMPLETYPE buff[128];
346
+
347
+    nOut = numSamples();
348
+
349
+    memset(buff, 0, 128 * sizeof(SAMPLETYPE));
350
+    // "Push" the last active samples out from the processing pipeline by
351
+    // feeding blank samples into the processing pipeline until new,
352
+    // processed samples appear in the output (not however, more than
353
+    // 8ksamples in any case)
354
+    for (i = 0; i < 128; i ++)
355
+    {
356
+        putSamples(buff, 64);
357
+        if (numSamples() != nOut) break;  // new samples have appeared in the output!
358
+    }
359
+
360
+    // Clear working buffers
361
+    pRateTransposer->clear();
362
+    pTDStretch->clearInput();
363
+    // yet leave the 'tempoChanger' output intouched as that's where the
364
+    // flushed samples are!
365
+}
366
+
367
+
368
+// Changes a setting controlling the processing system behaviour. See the
369
+// 'SETTING_...' defines for available setting ID's.
370
+bool SoundTouch::setSetting(uint32_t settingId, uint32_t value)
371
+{
372
+    uint32_t sampleRate, sequenceMs, seekWindowMs, overlapMs;
373
+
374
+    // read current tdstretch routine parameters
375
+    pTDStretch->getParameters(&sampleRate, &sequenceMs, &seekWindowMs, &overlapMs);
376
+
377
+    switch (settingId)
378
+    {
379
+        case SETTING_USE_AA_FILTER :
380
+            // enables / disabless anti-alias filter
381
+            pRateTransposer->enableAAFilter((value != 0) ? true : false);
382
+            return true;
383
+
384
+        case SETTING_AA_FILTER_LENGTH :
385
+            // sets anti-alias filter length
386
+            pRateTransposer->getAAFilter()->setLength(value);
387
+            return true;
388
+
389
+        case SETTING_USE_QUICKSEEK :
390
+            // enables / disables tempo routine quick seeking algorithm
391
+            pTDStretch->enableQuickSeek((value != 0) ? true : false);
392
+            return true;
393
+
394
+        case SETTING_SEQUENCE_MS:
395
+            // change time-stretch sequence duration parameter
396
+            pTDStretch->setParameters(sampleRate, value, seekWindowMs, overlapMs);
397
+            return true;
398
+
399
+        case SETTING_SEEKWINDOW_MS:
400
+            // change time-stretch seek window length parameter
401
+            pTDStretch->setParameters(sampleRate, sequenceMs, value, overlapMs);
402
+            return true;
403
+
404
+        case SETTING_OVERLAP_MS:
405
+            // change time-stretch overlap length parameter
406
+            pTDStretch->setParameters(sampleRate, sequenceMs, seekWindowMs, value);
407
+            return true;
408
+
409
+        default :
410
+            return false;
411
+    }
412
+}
413
+
414
+
415
+// Reads a setting controlling the processing system behaviour. See the
416
+// 'SETTING_...' defines for available setting ID's.
417
+//
418
+// Returns the setting value.
419
+uint32_t SoundTouch::getSetting(uint32_t settingId) const
420
+{
421
+    uint32_t temp;
422
+
423
+    switch (settingId)
424
+    {
425
+        case SETTING_USE_AA_FILTER :
426
+            return pRateTransposer->isAAFilterEnabled();
427
+
428
+        case SETTING_AA_FILTER_LENGTH :
429
+            return pRateTransposer->getAAFilter()->getLength();
430
+
431
+        case SETTING_USE_QUICKSEEK :
432
+            return pTDStretch->isQuickSeekEnabled();
433
+
434
+        case SETTING_SEQUENCE_MS:
435
+            pTDStretch->getParameters(NULL, &temp, NULL, NULL);
436
+            return temp;
437
+
438
+        case SETTING_SEEKWINDOW_MS:
439
+            pTDStretch->getParameters(NULL, NULL, &temp, NULL);
440
+            return temp;
441
+
442
+        case SETTING_OVERLAP_MS:
443
+            pTDStretch->getParameters(NULL, NULL, NULL, &temp);
444
+            return temp;
445
+
446
+        default :
447
+            return 0;
448
+    }
449
+}
450
+
451
+
452
+// Clears all the samples in the object's output and internal processing
453
+// buffers.
454
+void SoundTouch::clear()
455
+{
456
+    pRateTransposer->clear();
457
+    pTDStretch->clear();
458
+}
459
+
460
+
461
+
462
+/// Returns number of samples currently unprocessed.
463
+uint32_t SoundTouch::numUnprocessedSamples() const
464
+{
465
+    FIFOSamplePipe * psp;
466
+    if (pTDStretch)
467
+    {
468
+        psp = pTDStretch->getInput();
469
+        if (psp)
470
+        {
471
+            return psp->numSamples();
472
+        }
473
+    }
474
+    return 0;
475
+}