1 ////////////////////////////////////////////////////////////////////////////////
3 /// Sample rate transposer. Changes sample rate by using linear interpolation
4 /// together with anti-alias filtering (first order interpolation with anti-
5 /// alias filtering should be quite adequate for this application)
7 /// Author : Copyright (c) Olli Parviainen
8 /// Author e-mail : oparviai @ iki.fi
9 /// SoundTouch WWW: http://www.iki.fi/oparviai/soundtouch
11 ////////////////////////////////////////////////////////////////////////////////
13 // Last changed : $Date$
14 // File revision : $Revision$
18 ////////////////////////////////////////////////////////////////////////////////
22 // SoundTouch audio processing library
23 // Copyright (c) Olli Parviainen
25 // This library is free software; you can redistribute it and/or
26 // modify it under the terms of the GNU Lesser General Public
27 // License as published by the Free Software Foundation; either
28 // version 2.1 of the License, or (at your option) any later version.
30 // This library is distributed in the hope that it will be useful,
31 // but WITHOUT ANY WARRANTY; without even the implied warranty of
32 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 // Lesser General Public License for more details.
35 // You should have received a copy of the GNU Lesser General Public
36 // License along with this library; if not, write to the Free Software
37 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 ////////////////////////////////////////////////////////////////////////////////
46 #include "RateTransposer.h"
49 using namespace soundtouch;
52 /// A linear samplerate transposer class that uses integer arithmetics.
53 /// for the transposing.
54 class RateTransposerInteger : public RateTransposer
59 SAMPLETYPE sPrevSampleL, sPrevSampleR;
61 virtual void resetRegisters();
63 virtual uint transposeStereo(SAMPLETYPE *dest,
64 const SAMPLETYPE *src,
66 virtual uint transposeMono(SAMPLETYPE *dest,
67 const SAMPLETYPE *src,
71 RateTransposerInteger();
72 virtual ~RateTransposerInteger();
74 /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
75 /// rate, larger faster rates.
76 virtual void setRate(float newRate);
81 /// A linear samplerate transposer class that uses floating point arithmetics
82 /// for the transposing.
83 class RateTransposerFloat : public RateTransposer
88 SAMPLETYPE sPrevSampleL, sPrevSampleR;
90 virtual void resetRegisters();
92 virtual uint transposeStereo(SAMPLETYPE *dest,
93 const SAMPLETYPE *src,
95 virtual uint transposeMono(SAMPLETYPE *dest,
96 const SAMPLETYPE *src,
100 RateTransposerFloat();
101 virtual ~RateTransposerFloat();
107 #define min(a,b) ((a > b) ? b : a)
108 #define max(a,b) ((a < b) ? b : a)
111 RateTransposer *RateTransposer::newInstance()
113 #ifdef INTEGER_SAMPLES
114 return ::new RateTransposerInteger;
116 return ::new RateTransposerFloat;
122 RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
127 // Instantiates the anti-alias filter with default tap length
129 pAAFilter = new AAFilter(32);
134 RateTransposer::~RateTransposer()
141 /// Enables/disables the anti-alias filter. Zero to disable, nonzero to enable
142 void RateTransposer::enableAAFilter(const BOOL newMode)
144 bUseAAFilter = newMode;
148 /// Returns nonzero if anti-alias filter is enabled.
149 BOOL RateTransposer::isAAFilterEnabled() const
155 AAFilter *RateTransposer::getAAFilter() const
162 // Sets new target uRate. Normal uRate = 1.0, smaller values represent slower
163 // uRate, larger faster uRates.
164 void RateTransposer::setRate(float newRate)
170 // design a new anti-alias filter
173 fCutoff = 0.5f / newRate;
177 fCutoff = 0.5f * newRate;
179 pAAFilter->setCutoffFreq(fCutoff);
183 // Outputs as many samples of the 'outputBuffer' as possible, and if there's
184 // any room left, outputs also as many of the incoming samples as possible.
185 // The goal is to drive the outputBuffer empty.
187 // It's allowed for 'output' and 'input' parameters to point to the same
189 void RateTransposer::flushStoreBuffer()
191 if (storeBuffer.isEmpty()) return;
193 outputBuffer.moveSamples(storeBuffer);
197 // Adds 'numSamples' pcs of samples from the 'samples' memory position into
198 // the input of the object.
199 void RateTransposer::putSamples(const SAMPLETYPE *samples, uint numSamples)
201 processSamples(samples, numSamples);
206 // Transposes up the sample rate, causing the observed playback 'rate' of the
208 void RateTransposer::upsample(const SAMPLETYPE *src, uint numSamples)
210 int count, sizeTemp, num;
212 // If the parameter 'uRate' value is smaller than 'SCALE', first transpose
213 // the samples and then apply the anti-alias filter to remove aliasing.
215 // First check that there's enough room in 'storeBuffer'
216 // (+16 is to reserve some slack in the destination buffer)
217 sizeTemp = (int)((float)numSamples / fRate + 16.0f);
219 // Transpose the samples, store the result into the end of "storeBuffer"
220 count = transpose(storeBuffer.ptrEnd(sizeTemp), src, numSamples);
221 storeBuffer.putSamples(count);
223 // Apply the anti-alias filter to samples in "store output", output the
225 num = storeBuffer.numSamples();
226 count = pAAFilter->evaluate(outputBuffer.ptrEnd(num),
227 storeBuffer.ptrBegin(), num, uChannels);
228 outputBuffer.putSamples(count);
230 // Remove the processed samples from "storeBuffer"
231 storeBuffer.receiveSamples(count);
235 // Transposes down the sample rate, causing the observed playback 'rate' of the
237 void RateTransposer::downsample(const SAMPLETYPE *src, uint numSamples)
241 // If the parameter 'uRate' value is larger than 'SCALE', first apply the
242 // anti-alias filter to remove high frequencies (prevent them from folding
243 // over the lover frequencies), then transpose. */
245 // Add the new samples to the end of the storeBuffer */
246 storeBuffer.putSamples(src, numSamples);
248 // Anti-alias filter the samples to prevent folding and output the filtered
249 // data to tempBuffer. Note : because of the FIR filter length, the
250 // filtering routine takes in 'filter_length' more samples than it outputs.
251 assert(tempBuffer.isEmpty());
252 sizeTemp = storeBuffer.numSamples();
254 count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp),
255 storeBuffer.ptrBegin(), sizeTemp, uChannels);
257 // Remove the filtered samples from 'storeBuffer'
258 storeBuffer.receiveSamples(count);
260 // Transpose the samples (+16 is to reserve some slack in the destination buffer)
261 sizeTemp = (int)((float)numSamples / fRate + 16.0f);
262 count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count);
263 outputBuffer.putSamples(count);
267 // Transposes sample rate by applying anti-alias filter to prevent folding.
268 // Returns amount of samples returned in the "dest" buffer.
269 // The maximum amount of samples that can be returned at a time is set by
270 // the 'set_returnBuffer_size' function.
271 void RateTransposer::processSamples(const SAMPLETYPE *src, uint numSamples)
276 if (numSamples == 0) return;
279 // If anti-alias filter is turned off, simply transpose without applying
281 if (bUseAAFilter == FALSE)
283 sizeReq = (int)((float)numSamples / fRate + 1.0f);
284 count = transpose(outputBuffer.ptrEnd(sizeReq), src, numSamples);
285 outputBuffer.putSamples(count);
289 // Transpose with anti-alias filter
292 upsample(src, numSamples);
296 downsample(src, numSamples);
301 // Transposes the sample rate of the given samples using linear interpolation.
302 // Returns the number of samples returned in the "dest" buffer
303 inline uint RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
307 return transposeStereo(dest, src, numSamples);
311 return transposeMono(dest, src, numSamples);
316 // Sets the number of channels, 1 = mono, 2 = stereo
317 void RateTransposer::setChannels(const uint numchannels)
319 if (uChannels == numchannels) return;
321 assert(numchannels == 1 || numchannels == 2);
322 uChannels = numchannels;
324 storeBuffer.setChannels(uChannels);
325 tempBuffer.setChannels(uChannels);
326 outputBuffer.setChannels(uChannels);
328 // Inits the linear interpolation registers
333 // Clears all the samples in the object
334 void RateTransposer::clear()
336 outputBuffer.clear();
341 // Returns nonzero if there aren't any samples available for outputting.
342 int RateTransposer::isEmpty() const
346 res = FIFOProcessor::isEmpty();
347 if (res == 0) return 0;
348 return storeBuffer.isEmpty();
352 //////////////////////////////////////////////////////////////////////////////
354 // RateTransposerInteger - integer arithmetic implementation
357 /// fixed-point interpolation routine precision
361 RateTransposerInteger::RateTransposerInteger() : RateTransposer()
363 // call these here as these are virtual functions; calling these
364 // from the base class constructor wouldn't execute the overloaded
365 // versions (<master yoda>peculiar C++ can be</my>).
371 RateTransposerInteger::~RateTransposerInteger()
376 void RateTransposerInteger::resetRegisters()
385 // Transposes the sample rate of the given samples using linear interpolation.
386 // 'Mono' version of the routine. Returns the number of samples returned in
388 uint RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
390 unsigned int i, used;
391 LONG_SAMPLETYPE temp, vol1;
396 // Process the last sample saved from the previous call first...
397 while (iSlopeCount <= SCALE)
399 vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
400 temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
401 dest[i] = (SAMPLETYPE)(temp / SCALE);
403 iSlopeCount += uRate;
405 // now always (iSlopeCount > SCALE)
406 iSlopeCount -= SCALE;
410 while (iSlopeCount > SCALE)
412 iSlopeCount -= SCALE;
414 if (used >= numSamples - 1) goto end;
416 vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
417 temp = src[used] * vol1 + iSlopeCount * src[used + 1];
418 dest[i] = (SAMPLETYPE)(temp / SCALE);
421 iSlopeCount += uRate;
424 // Store the last sample for the next round
425 sPrevSampleL = src[numSamples - 1];
431 // Transposes the sample rate of the given samples using linear interpolation.
432 // 'Mono' version of the routine. Returns the number of samples returned in
434 uint RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
436 unsigned int srcPos, i, used;
437 LONG_SAMPLETYPE temp, vol1;
439 if (numSamples == 0) return 0; // no samples, no work
444 // Process the last sample saved from the sPrevSampleLious call first...
445 while (iSlopeCount <= SCALE)
447 vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
448 temp = vol1 * sPrevSampleL + iSlopeCount * src[0];
449 dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
450 temp = vol1 * sPrevSampleR + iSlopeCount * src[1];
451 dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
453 iSlopeCount += uRate;
455 // now always (iSlopeCount > SCALE)
456 iSlopeCount -= SCALE;
460 while (iSlopeCount > SCALE)
462 iSlopeCount -= SCALE;
464 if (used >= numSamples - 1) goto end;
467 vol1 = (LONG_SAMPLETYPE)(SCALE - iSlopeCount);
468 temp = src[srcPos] * vol1 + iSlopeCount * src[srcPos + 2];
469 dest[2 * i] = (SAMPLETYPE)(temp / SCALE);
470 temp = src[srcPos + 1] * vol1 + iSlopeCount * src[srcPos + 3];
471 dest[2 * i + 1] = (SAMPLETYPE)(temp / SCALE);
474 iSlopeCount += uRate;
477 // Store the last sample for the next round
478 sPrevSampleL = src[2 * numSamples - 2];
479 sPrevSampleR = src[2 * numSamples - 1];
485 // Sets new target uRate. Normal uRate = 1.0, smaller values represent slower
486 // uRate, larger faster uRates.
487 void RateTransposerInteger::setRate(float newRate)
489 uRate = (int)(newRate * SCALE + 0.5f);
490 RateTransposer::setRate(newRate);
494 //////////////////////////////////////////////////////////////////////////////
496 // RateTransposerFloat - floating point arithmetic implementation
498 //////////////////////////////////////////////////////////////////////////////
501 RateTransposerFloat::RateTransposerFloat() : RateTransposer()
503 // call these here as these are virtual functions; calling these
504 // from the base class constructor wouldn't execute the overloaded
505 // versions (<master yoda>peculiar C++ can be</my>).
511 RateTransposerFloat::~RateTransposerFloat()
516 void RateTransposerFloat::resetRegisters()
525 // Transposes the sample rate of the given samples using linear interpolation.
526 // 'Mono' version of the routine. Returns the number of samples returned in
528 uint RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
530 unsigned int i, used;
535 // Process the last sample saved from the previous call first...
536 while (fSlopeCount <= 1.0f)
538 dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
540 fSlopeCount += fRate;
546 while (fSlopeCount > 1.0f)
550 if (used >= numSamples - 1) goto end;
552 dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[used] + fSlopeCount * src[used + 1]);
554 fSlopeCount += fRate;
557 // Store the last sample for the next round
558 sPrevSampleL = src[numSamples - 1];
564 // Transposes the sample rate of the given samples using linear interpolation.
565 // 'Mono' version of the routine. Returns the number of samples returned in
567 uint RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples)
569 unsigned int srcPos, i, used;
571 if (numSamples == 0) return 0; // no samples, no work
576 // Process the last sample saved from the sPrevSampleLious call first...
577 while (fSlopeCount <= 1.0f)
579 dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleL + fSlopeCount * src[0]);
580 dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSampleR + fSlopeCount * src[1]);
582 fSlopeCount += fRate;
584 // now always (iSlopeCount > 1.0f)
589 while (fSlopeCount > 1.0f)
593 if (used >= numSamples - 1) goto end;
597 dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos]
598 + fSlopeCount * src[srcPos + 2]);
599 dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[srcPos + 1]
600 + fSlopeCount * src[srcPos + 3]);
603 fSlopeCount += fRate;
606 // Store the last sample for the next round
607 sPrevSampleL = src[2 * numSamples - 2];
608 sPrevSampleR = src[2 * numSamples - 1];