Restructured RateTransposer to allow hosting alternative resampling algorithms.

This commit is contained in:
oparviai 2014-01-05 21:40:22 +00:00
parent 8174f6bc10
commit abfeb3fcc9
6 changed files with 203 additions and 164 deletions

View File

@ -162,6 +162,12 @@ public:
/// Sets number of channels, 1 = mono, 2 = stereo. /// Sets number of channels, 1 = mono, 2 = stereo.
void setChannels(int numChannels); void setChannels(int numChannels);
/// Get number of channels
int getChannels()
{
return channels;
}
/// Returns nonzero if there aren't any samples available for outputting. /// Returns nonzero if there aren't any samples available for outputting.
virtual int isEmpty() const; virtual int isEmpty() const;

View File

@ -205,6 +205,31 @@ uint AAFilter::evaluate(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples
} }
/// Applies the filter to the given src & dest pipes, so that processed amount of
/// samples get removed from src, and produced amount added to dest
/// Note : The amount of outputted samples is by value of 'filter length'
/// smaller than the amount of input samples.
uint AAFilter::evaluate(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) const
{
SAMPLETYPE *pdest;
const SAMPLETYPE *psrc;
uint numSrcSamples;
uint result;
int numChannels = src.getChannels();
assert(numChannels == dest.getChannels());
numSrcSamples = src.numSamples();
psrc = src.ptrBegin();
pdest = dest.ptrEnd(numSrcSamples);
result = pFIR->evaluate(pdest, psrc, numSrcSamples, numChannels);
src.receiveSamples(result);
dest.putSamples(result);
return result;
}
uint AAFilter::getLength() const uint AAFilter::getLength() const
{ {
return pFIR->getLength(); return pFIR->getLength();

View File

@ -45,6 +45,7 @@
#define AAFilter_H #define AAFilter_H
#include "STTypes.h" #include "STTypes.h"
#include "FIFOSampleBuffer.h"
namespace soundtouch namespace soundtouch
{ {
@ -84,6 +85,14 @@ public:
const SAMPLETYPE *src, const SAMPLETYPE *src,
uint numSamples, uint numSamples,
uint numChannels) const; uint numChannels) const;
/// Applies the filter to the given src & dest pipes, so that processed amount of
/// samples get removed from src, and produced amount added to dest
/// Note : The amount of outputted samples is by value of 'filter length'
/// smaller than the amount of input samples.
uint AAFilter::evaluate(FIFOSampleBuffer &dest,
FIFOSampleBuffer &src) const;
}; };
} }

View File

@ -48,9 +48,31 @@
using namespace soundtouch; using namespace soundtouch;
/// A linear samplerate transposer class that uses integer arithmetics. /// A linear samplerate transposer class that uses integer arithmetics.
/// for the transposing. /// for the transposing.
class RateTransposerInteger : public RateTransposer class LinearTransposerBase: public TransposerBase
{
protected:
virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples) = 0;
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples) = 0;
virtual int transposeMulti(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples) = 0;
public:
virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
static LinearTransposerBase *newInstance();
};
/// A linear samplerate transposer class that uses integer arithmetics.
/// for the transposing.
class LinearTransposerInteger : public LinearTransposerBase
{ {
protected: protected:
int iSlopeCount; int iSlopeCount;
@ -67,19 +89,18 @@ protected:
uint numSamples); uint numSamples);
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples); virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint numSamples);
public: public:
RateTransposerInteger(); LinearTransposerInteger();
virtual ~RateTransposerInteger(); virtual ~LinearTransposerInteger();
/// Sets new target rate. Normal rate = 1.0, smaller values represent slower /// Sets new target rate. Normal rate = 1.0, smaller values represent slower
/// rate, larger faster rates. /// rate, larger faster rates.
virtual void setRate(float newRate); virtual void setRate(float newRate);
}; };
/// A linear samplerate transposer class that uses floating point arithmetics /// A linear samplerate transposer class that uses floating point arithmetics
/// for the transposing. /// for the transposing.
class RateTransposerFloat : public RateTransposer class LinearTransposerFloat : public LinearTransposerBase
{ {
protected: protected:
float fSlopeCount; float fSlopeCount;
@ -96,28 +117,53 @@ protected:
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples); virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples);
public: public:
RateTransposerFloat(); LinearTransposerFloat();
virtual ~RateTransposerFloat(); virtual ~LinearTransposerFloat();
}; };
TransposerBase::TransposerBase()
{
numChannels = 0;
rate = 1.0f;
}
TransposerBase::~TransposerBase()
{
}
void TransposerBase::setChannels(int channels)
{
numChannels = channels;
resetRegisters();
}
void TransposerBase::setRate(float newRate)
{
rate = newRate;
}
// Operator 'new' is overloaded so that it automatically creates a suitable instance // Operator 'new' is overloaded so that it automatically creates a suitable instance
// depending on if we've a MMX/SSE/etc-capable CPU available or not. // depending on if we've a MMX/SSE/etc-capable CPU available or not.
/*
void * RateTransposer::operator new(size_t s) void * RateTransposer::operator new(size_t s)
{ {
ST_THROW_RT_ERROR("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!"); ST_THROW_RT_ERROR("Error in RateTransoser::new: don't use \"new TDStretch\" directly, use \"newInstance\" to create a new instance instead!");
return newInstance(); return newInstance();
} }
*/
RateTransposer *RateTransposer::newInstance() TransposerBase *TransposerBase::newInstance()
{ {
#ifdef SOUNDTOUCH_INTEGER_SAMPLES #ifdef SOUNDTOUCH_INTEGER_SAMPLES
return ::new RateTransposerInteger; return ::new LinearTransposerInteger;
#else #else
return ::new RateTransposerFloat; return ::new LinearTransposerFloat;
#endif #endif
} }
@ -125,13 +171,12 @@ RateTransposer *RateTransposer::newInstance()
// Constructor // Constructor
RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer) RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
{ {
numChannels = 2;
bUseAAFilter = TRUE; bUseAAFilter = TRUE;
fRate = 0;
// Instantiates the anti-alias filter with default tap length // Instantiates the anti-alias filter with default tap length
// of 32 // of 32
pAAFilter = new AAFilter(32); pAAFilter = new AAFilter(32);
pTransposer = TransposerBase::newInstance();
} }
@ -139,6 +184,7 @@ RateTransposer::RateTransposer() : FIFOProcessor(&outputBuffer)
RateTransposer::~RateTransposer() RateTransposer::~RateTransposer()
{ {
delete pAAFilter; delete pAAFilter;
delete pTransposer;
} }
@ -170,7 +216,7 @@ void RateTransposer::setRate(float newRate)
{ {
double fCutoff; double fCutoff;
fRate = newRate; pTransposer->setRate(newRate);
// design a new anti-alias filter // design a new anti-alias filter
if (newRate > 1.0f) if (newRate > 1.0f)
@ -192,11 +238,11 @@ void RateTransposer::setRate(float newRate)
// It's allowed for 'output' and 'input' parameters to point to the same // It's allowed for 'output' and 'input' parameters to point to the same
// memory position. // memory position.
/* /*
void RateTransposer::flushStoreBuffer() void RateTransposer::flushinputBuffer()
{ {
if (storeBuffer.isEmpty()) return; if (inputBuffer.isEmpty()) return;
outputBuffer.moveSamples(storeBuffer); outputBuffer.moveSamples(inputBuffer);
} }
*/ */
@ -209,70 +255,6 @@ void RateTransposer::putSamples(const SAMPLETYPE *samples, uint nSamples)
} }
// Transposes up the sample rate, causing the observed playback 'rate' of the
// sound to decrease
void RateTransposer::upsample(const SAMPLETYPE *src, uint nSamples)
{
uint count, sizeTemp, num;
// If the parameter 'uRate' value is smaller than 'SCALE', first transpose
// the samples and then apply the anti-alias filter to remove aliasing.
// First check that there's enough room in 'storeBuffer'
// (+16 is to reserve some slack in the destination buffer)
sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
// Transpose the samples, store the result into the end of "storeBuffer"
count = transpose(storeBuffer.ptrEnd(sizeTemp), src, nSamples);
storeBuffer.putSamples(count);
// Apply the anti-alias filter to samples in "store output", output the
// result to "dest"
num = storeBuffer.numSamples();
count = pAAFilter->evaluate(outputBuffer.ptrEnd(num),
storeBuffer.ptrBegin(), num, (uint)numChannels);
outputBuffer.putSamples(count);
// Remove the processed samples from "storeBuffer"
storeBuffer.receiveSamples(count);
}
// Transposes down the sample rate, causing the observed playback 'rate' of the
// sound to increase
void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples)
{
uint count, sizeTemp;
// If the parameter 'uRate' value is larger than 'SCALE', first apply the
// anti-alias filter to remove high frequencies (prevent them from folding
// over the lover frequencies), then transpose.
// Add the new samples to the end of the storeBuffer
storeBuffer.putSamples(src, nSamples);
// Anti-alias filter the samples to prevent folding and output the filtered
// data to tempBuffer. Note : because of the FIR filter length, the
// filtering routine takes in 'filter_length' more samples than it outputs.
assert(tempBuffer.isEmpty());
sizeTemp = storeBuffer.numSamples();
count = pAAFilter->evaluate(tempBuffer.ptrEnd(sizeTemp),
storeBuffer.ptrBegin(), sizeTemp, (uint)numChannels);
if (count == 0) return;
// Remove the filtered samples from 'storeBuffer'
storeBuffer.receiveSamples(count);
// Transpose the samples (+16 is to reserve some slack in the destination buffer)
sizeTemp = (uint)((float)nSamples / fRate + 16.0f);
count = transpose(outputBuffer.ptrEnd(sizeTemp), tempBuffer.ptrBegin(), count);
outputBuffer.putSamples(count);
}
// Transposes sample rate by applying anti-alias filter to prevent folding. // Transposes sample rate by applying anti-alias filter to prevent folding.
// Returns amount of samples returned in the "dest" buffer. // Returns amount of samples returned in the "dest" buffer.
// The maximum amount of samples that can be returned at a time is set by // The maximum amount of samples that can be returned at a time is set by
@ -280,52 +262,77 @@ void RateTransposer::downsample(const SAMPLETYPE *src, uint nSamples)
void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples) void RateTransposer::processSamples(const SAMPLETYPE *src, uint nSamples)
{ {
uint count; uint count;
uint sizeReq;
if (nSamples == 0) return; if (nSamples == 0) return;
assert(pAAFilter);
// Store samples to input buffer
inputBuffer.putSamples(src, nSamples);
// If anti-alias filter is turned off, simply transpose without applying // If anti-alias filter is turned off, simply transpose without applying
// the filter // the filter
if (bUseAAFilter == FALSE) if (bUseAAFilter == FALSE)
{ {
sizeReq = (uint)((float)nSamples / fRate + 1.0f); count = pTransposer->transpose(outputBuffer, inputBuffer);
count = transpose(outputBuffer.ptrEnd(sizeReq), src, nSamples);
outputBuffer.putSamples(count);
return; return;
} }
assert(pAAFilter);
// Transpose with anti-alias filter // Transpose with anti-alias filter
if (fRate < 1.0f) if (pTransposer->rate < 1.0f)
{ {
upsample(src, nSamples); // If the parameter 'Rate' value is smaller than 1, first transpose
// the samples and then apply the anti-alias filter to remove aliasing.
// Transpose the samples, store the result to end of "midBuffer"
pTransposer->transpose(midBuffer, inputBuffer);
// Apply the anti-alias filter for transposed samples in midBuffer
pAAFilter->evaluate(outputBuffer, midBuffer);
} }
else else
{ {
downsample(src, nSamples); // If the parameter 'Rate' value is larger than 1, first apply the
// anti-alias filter to remove high frequencies (prevent them from folding
// over the lover frequencies), then transpose.
// Apply the anti-alias filter for samples in inputBuffer
pAAFilter->evaluate(midBuffer, inputBuffer);
// Transpose the AA-filtered samples in "midBuffer"
pTransposer->transpose(outputBuffer, midBuffer);
} }
} }
// Transposes the sample rate of the given samples using linear interpolation. // Transposes the sample rate of the given samples using linear interpolation.
// Returns the number of samples returned in the "dest" buffer // Returns the number of samples returned in the "dest" buffer
inline int RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) int LinearTransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
{ {
int numSrcSamples = src.numSamples();
int sizeDemand = (int)((float)numSrcSamples / rate) + 8;
int numOutput;
SAMPLETYPE *psrc = src.ptrBegin();
SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
#ifndef USE_MULTICH_ALWAYS #ifndef USE_MULTICH_ALWAYS
if (numChannels == 1) if (numChannels == 1)
{ {
return transposeMono(dest, src, nSamples); numOutput = transposeMono(pdest, psrc, numSrcSamples);
} }
else if (numChannels == 2) else if (numChannels == 2)
{ {
return transposeStereo(dest, src, nSamples); numOutput = transposeStereo(pdest, psrc, numSrcSamples);
} }
else else
#endif // USE_MULTICH_ALWAYS #endif // USE_MULTICH_ALWAYS
{ {
assert(numChannels > 0); assert(numChannels > 0);
return transposeMulti(dest, src, nSamples); numOutput = transposeMulti(pdest, psrc, numSrcSamples);
} }
dest.putSamples(numOutput);
src.receiveSamples(numOutput);
return numOutput;
} }
@ -333,17 +340,13 @@ inline int RateTransposer::transpose(SAMPLETYPE *dest, const SAMPLETYPE *src, ui
void RateTransposer::setChannels(int nChannels) void RateTransposer::setChannels(int nChannels)
{ {
assert(nChannels > 0); assert(nChannels > 0);
if (numChannels == nChannels) return;
// assert(nChannels == 1 || nChannels == 2); if (pTransposer->numChannels == nChannels) return;
numChannels = nChannels; pTransposer->setChannels(nChannels);
storeBuffer.setChannels(numChannels); inputBuffer.setChannels(nChannels);
tempBuffer.setChannels(numChannels); midBuffer.setChannels(nChannels);
outputBuffer.setChannels(numChannels); outputBuffer.setChannels(nChannels);
// Inits the linear interpolation registers
resetRegisters();
} }
@ -351,7 +354,8 @@ void RateTransposer::setChannels(int nChannels)
void RateTransposer::clear() void RateTransposer::clear()
{ {
outputBuffer.clear(); outputBuffer.clear();
storeBuffer.clear(); midBuffer.clear();
inputBuffer.clear();
} }
@ -362,36 +366,36 @@ int RateTransposer::isEmpty() const
res = FIFOProcessor::isEmpty(); res = FIFOProcessor::isEmpty();
if (res == 0) return 0; if (res == 0) return 0;
return storeBuffer.isEmpty(); return inputBuffer.isEmpty();
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// RateTransposerInteger - integer arithmetic implementation // LinearTransposerInteger - integer arithmetic implementation
// //
/// fixed-point interpolation routine precision /// fixed-point interpolation routine precision
#define SCALE 65536 #define SCALE 65536
// Constructor // Constructor
RateTransposerInteger::RateTransposerInteger() : RateTransposer() LinearTransposerInteger::LinearTransposerInteger() : LinearTransposerBase()
{ {
// Notice: use local function calling syntax for sake of clarity, // Notice: use local function calling syntax for sake of clarity,
// to indicate the fact that C++ constructor can't call virtual functions. // to indicate the fact that C++ constructor can't call virtual functions.
sPrevSample=0; sPrevSample=0;
RateTransposerInteger::resetRegisters(); resetRegisters();
RateTransposerInteger::setRate(1.0f); setRate(1.0f);
} }
RateTransposerInteger::~RateTransposerInteger() LinearTransposerInteger::~LinearTransposerInteger()
{ {
if (sPrevSample) delete[] sPrevSample; if (sPrevSample) delete[] sPrevSample;
} }
void RateTransposerInteger::resetRegisters() void LinearTransposerInteger::resetRegisters()
{ {
iSlopeCount = 0; iSlopeCount = 0;
delete[] sPrevSample; delete[] sPrevSample;
@ -404,7 +408,7 @@ void RateTransposerInteger::resetRegisters()
// Transposes the sample rate of the given samples using linear interpolation. // Transposes the sample rate of the given samples using linear interpolation.
// 'Mono' version of the routine. Returns the number of samples returned in // 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer // the "dest" buffer
int RateTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) int LinearTransposerInteger::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{ {
int i, remain; int i, remain;
LONG_SAMPLETYPE temp, vol1; LONG_SAMPLETYPE temp, vol1;
@ -453,7 +457,7 @@ end:
// Transposes the sample rate of the given samples using linear interpolation. // Transposes the sample rate of the given samples using linear interpolation.
// 'Stereo' version of the routine. Returns the number of samples returned in // 'Stereo' version of the routine. Returns the number of samples returned in
// the "dest" buffer // the "dest" buffer
int RateTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) int LinearTransposerInteger::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{ {
int i, remain; int i, remain;
LONG_SAMPLETYPE temp, vol1; LONG_SAMPLETYPE temp, vol1;
@ -504,7 +508,7 @@ end:
} }
int RateTransposerInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) int LinearTransposerInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{ {
int i, remaining; int i, remaining;
LONG_SAMPLETYPE temp, vol1; LONG_SAMPLETYPE temp, vol1;
@ -561,37 +565,37 @@ end:
// Sets new target iRate. Normal iRate = 1.0, smaller values represent slower // Sets new target iRate. Normal iRate = 1.0, smaller values represent slower
// iRate, larger faster iRates. // iRate, larger faster iRates.
void RateTransposerInteger::setRate(float newRate) void LinearTransposerInteger::setRate(float newRate)
{ {
iRate = (int)(newRate * SCALE + 0.5f); iRate = (int)(newRate * SCALE + 0.5f);
RateTransposer::setRate(newRate); TransposerBase::setRate(newRate);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// RateTransposerFloat - floating point arithmetic implementation // LinearTransposerFloat - floating point arithmetic implementation
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Constructor // Constructor
RateTransposerFloat::RateTransposerFloat() : RateTransposer() LinearTransposerFloat::LinearTransposerFloat() : LinearTransposerBase()
{ {
// Notice: use local function calling syntax for sake of clarity, // Notice: use local function calling syntax for sake of clarity,
// to indicate the fact that C++ constructor can't call virtual functions. // to indicate the fact that C++ constructor can't call virtual functions.
sPrevSample = NULL; sPrevSample = NULL;
RateTransposerFloat::resetRegisters(); resetRegisters();
RateTransposerFloat::setRate(1.0f); setRate(1.0f);
} }
RateTransposerFloat::~RateTransposerFloat() LinearTransposerFloat::~LinearTransposerFloat()
{ {
delete[] sPrevSample; delete[] sPrevSample;
} }
void RateTransposerFloat::resetRegisters() void LinearTransposerFloat::resetRegisters()
{ {
fSlopeCount = 0; fSlopeCount = 0;
delete[] sPrevSample; delete[] sPrevSample;
@ -604,19 +608,19 @@ void RateTransposerFloat::resetRegisters()
// Transposes the sample rate of the given samples using linear interpolation. // Transposes the sample rate of the given samples using linear interpolation.
// 'Mono' version of the routine. Returns the number of samples returned in // 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer // the "dest" buffer
int RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) int LinearTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{ {
int i, remain; int i, remain;
remain = nSamples - 1; remain = nSamples - 1;
i = 0; i = 0;
// Process the last sample saved from the previous call first... // Process the last sample saved from the previous call first...
while (fSlopeCount <= 1.0f) while (fSlopeCount <= 1.0f)
{ {
dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[0] + fSlopeCount * src[0]); dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[0] + fSlopeCount * src[0]);
i++; i++;
fSlopeCount += fRate; fSlopeCount += rate;
} }
fSlopeCount -= 1.0f; fSlopeCount -= 1.0f;
@ -633,7 +637,7 @@ int RateTransposerFloat::transposeMono(SAMPLETYPE *dest, const SAMPLETYPE *src,
} }
dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[0] + fSlopeCount * src[1]); dest[i] = (SAMPLETYPE)((1.0f - fSlopeCount) * src[0] + fSlopeCount * src[1]);
i++; i++;
fSlopeCount += fRate; fSlopeCount += rate;
} }
} }
end: end:
@ -647,7 +651,7 @@ end:
// Transposes the sample rate of the given samples using linear interpolation. // Transposes the sample rate of the given samples using linear interpolation.
// 'Mono' version of the routine. Returns the number of samples returned in // 'Mono' version of the routine. Returns the number of samples returned in
// the "dest" buffer // the "dest" buffer
int RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) int LinearTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{ {
int i, remain; int i, remain;
@ -662,7 +666,7 @@ int RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src
dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[0] + fSlopeCount * src[0]); dest[2 * i] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[0] + fSlopeCount * src[0]);
dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[1] + fSlopeCount * src[1]); dest[2 * i + 1] = (SAMPLETYPE)((1.0f - fSlopeCount) * sPrevSample[1] + fSlopeCount * src[1]);
i++; i++;
fSlopeCount += fRate; fSlopeCount += rate;
} }
// now always (iSlopeCount > 1.0f) // now always (iSlopeCount > 1.0f)
fSlopeCount -= 1.0f; fSlopeCount -= 1.0f;
@ -685,7 +689,7 @@ int RateTransposerFloat::transposeStereo(SAMPLETYPE *dest, const SAMPLETYPE *src
+ fSlopeCount * src[3]); + fSlopeCount * src[3]);
i++; i++;
fSlopeCount += fRate; fSlopeCount += rate;
} }
} }
end: end:
@ -696,7 +700,7 @@ end:
return i; return i;
} }
int RateTransposerFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) int LinearTransposerFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples)
{ {
int i, remaining; int i, remaining;
@ -714,7 +718,7 @@ int RateTransposerFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src,
dest ++; dest ++;
} }
i++; i++;
fSlopeCount += fRate; fSlopeCount += rate;
} }
// now always (iSlopeCount > 1.0f) // now always (iSlopeCount > 1.0f)
fSlopeCount -= 1.0f; fSlopeCount -= 1.0f;
@ -737,7 +741,7 @@ int RateTransposerFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src,
} }
i++; i++;
fSlopeCount += fRate; fSlopeCount += rate;
} }
end: end:

View File

@ -55,51 +55,47 @@
namespace soundtouch namespace soundtouch
{ {
/// Abstract base class for transposer implementations (linear, advanced vs integer, float etc)
class TransposerBase
{
protected:
virtual void resetRegisters() = 0;
public:
float rate;
int numChannels;
TransposerBase();
virtual ~TransposerBase();
virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src) = 0;
virtual void setRate(float newRate);
virtual void setChannels(int channels);
static TransposerBase *newInstance();
};
/// A common linear samplerate transposer class. /// A common linear samplerate transposer class.
/// ///
/// Note: Use function "RateTransposer::newInstance()" to create a new class
/// instance instead of the "new" operator; that function automatically
/// chooses a correct implementation depending on if integer or floating
/// arithmetics are to be used.
class RateTransposer : public FIFOProcessor class RateTransposer : public FIFOProcessor
{ {
protected: protected:
/// Anti-alias filter object /// Anti-alias filter object
AAFilter *pAAFilter; AAFilter *pAAFilter;
TransposerBase *pTransposer;
float fRate;
int numChannels;
/// Buffer for collecting samples to feed the anti-alias filter between /// Buffer for collecting samples to feed the anti-alias filter between
/// two batches /// two batches
FIFOSampleBuffer storeBuffer; FIFOSampleBuffer inputBuffer;
/// Buffer for keeping samples between transposing & anti-alias filter /// Buffer for keeping samples between transposing & anti-alias filter
FIFOSampleBuffer tempBuffer; FIFOSampleBuffer midBuffer;
/// Output sample buffer /// Output sample buffer
FIFOSampleBuffer outputBuffer; FIFOSampleBuffer outputBuffer;
BOOL bUseAAFilter; BOOL bUseAAFilter;
virtual void resetRegisters() = 0;
virtual int transposeStereo(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples) = 0;
virtual int transposeMono(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples) = 0;
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uint nSamples) = 0;
inline int transpose(SAMPLETYPE *dest,
const SAMPLETYPE *src,
uint numSamples);
void downsample(const SAMPLETYPE *src,
uint numSamples);
void upsample(const SAMPLETYPE *src,
uint numSamples);
/// Transposes sample rate by applying anti-alias filter to prevent folding. /// Transposes sample rate by applying anti-alias filter to prevent folding.
/// Returns amount of samples returned in the "dest" buffer. /// Returns amount of samples returned in the "dest" buffer.
@ -108,25 +104,24 @@ protected:
void processSamples(const SAMPLETYPE *src, void processSamples(const SAMPLETYPE *src,
uint numSamples); uint numSamples);
public: public:
RateTransposer(); RateTransposer();
virtual ~RateTransposer(); virtual ~RateTransposer();
/// Operator 'new' is overloaded so that it automatically creates a suitable instance /// Operator 'new' is overloaded so that it automatically creates a suitable instance
/// depending on if we're to use integer or floating point arithmetics. /// depending on if we're to use integer or floating point arithmetics.
static void *operator new(size_t s); // static void *operator new(size_t s);
/// Use this function instead of "new" operator to create a new instance of this class. /// Use this function instead of "new" operator to create a new instance of this class.
/// This function automatically chooses a correct implementation, depending on if /// This function automatically chooses a correct implementation, depending on if
/// integer ot floating point arithmetics are to be used. /// integer ot floating point arithmetics are to be used.
static RateTransposer *newInstance(); // static RateTransposer *newInstance();
/// Returns the output buffer object /// Returns the output buffer object
FIFOSamplePipe *getOutput() { return &outputBuffer; }; FIFOSamplePipe *getOutput() { return &outputBuffer; };
/// Returns the store buffer object /// Returns the store buffer object
FIFOSamplePipe *getStore() { return &storeBuffer; }; // FIFOSamplePipe *getStore() { return &storeBuffer; };
/// Return anti-alias filter object /// Return anti-alias filter object
AAFilter *getAAFilter(); AAFilter *getAAFilter();

View File

@ -97,7 +97,7 @@ SoundTouch::SoundTouch()
{ {
// Initialize rate transposer and tempo changer instances // Initialize rate transposer and tempo changer instances
pRateTransposer = RateTransposer::newInstance(); pRateTransposer = new RateTransposer();
pTDStretch = TDStretch::newInstance(); pTDStretch = TDStretch::newInstance();
setOutPipe(pTDStretch); setOutPipe(pTDStretch);
@ -255,7 +255,7 @@ void SoundTouch::calcEffectiveRateAndTempo()
tempoOut = pTDStretch->getOutput(); tempoOut = pTDStretch->getOutput();
tempoOut->moveSamples(*output); tempoOut->moveSamples(*output);
// move samples in pitch transposer's store buffer to tempo changer's input // move samples in pitch transposer's store buffer to tempo changer's input
pTDStretch->moveSamples(*pRateTransposer->getStore()); // deprecated : pTDStretch->moveSamples(*pRateTransposer->getStore());
output = pTDStretch; output = pTDStretch;
} }