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];