mirror of
https://github.com/azahar-emu/soundtouch
synced 2025-11-07 07:30:02 +01:00
- Improved SoundTouch::flush() so that it produces exactly accurate number of output samples.
- Changed 'float' variables into 'double' for more precise calculation of input-vs-output samples.
This commit is contained in:
parent
da748228b9
commit
c9507ff7f1
@ -151,17 +151,24 @@ private:
|
|||||||
class TDStretch *pTDStretch;
|
class TDStretch *pTDStretch;
|
||||||
|
|
||||||
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
||||||
float virtualRate;
|
double virtualRate;
|
||||||
|
|
||||||
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
||||||
float virtualTempo;
|
double virtualTempo;
|
||||||
|
|
||||||
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
/// Virtual pitch parameter. Effective rate & tempo are calculated from these parameters.
|
||||||
float virtualPitch;
|
double virtualPitch;
|
||||||
|
|
||||||
/// Flag: Has sample rate been set?
|
/// Flag: Has sample rate been set?
|
||||||
bool bSrateSet;
|
bool bSrateSet;
|
||||||
|
|
||||||
|
/// Accumulator for how many samples in total will be expected as output vs. samples put in,
|
||||||
|
/// considering current processing settings.
|
||||||
|
double samplesExpectedOut;
|
||||||
|
|
||||||
|
/// Accumulator for how many samples in total have been read out from the processing so far
|
||||||
|
long samplesOutput;
|
||||||
|
|
||||||
/// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and
|
/// Calculates effective rate & tempo valuescfrom 'virtualRate', 'virtualTempo' and
|
||||||
/// 'virtualPitch' parameters.
|
/// 'virtualPitch' parameters.
|
||||||
void calcEffectiveRateAndTempo();
|
void calcEffectiveRateAndTempo();
|
||||||
@ -171,10 +178,10 @@ protected :
|
|||||||
uint channels;
|
uint channels;
|
||||||
|
|
||||||
/// Effective 'rate' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch'
|
/// Effective 'rate' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch'
|
||||||
float rate;
|
double rate;
|
||||||
|
|
||||||
/// Effective 'tempo' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch'
|
/// Effective 'tempo' value calculated from 'virtualRate', 'virtualTempo' and 'virtualPitch'
|
||||||
float tempo;
|
double tempo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SoundTouch();
|
SoundTouch();
|
||||||
@ -188,32 +195,32 @@ public:
|
|||||||
|
|
||||||
/// Sets new rate control value. Normal rate = 1.0, smaller values
|
/// Sets new rate control value. Normal rate = 1.0, smaller values
|
||||||
/// represent slower rate, larger faster rates.
|
/// represent slower rate, larger faster rates.
|
||||||
void setRate(float newRate);
|
void setRate(double newRate);
|
||||||
|
|
||||||
/// Sets new tempo control value. Normal tempo = 1.0, smaller values
|
/// Sets new tempo control value. Normal tempo = 1.0, smaller values
|
||||||
/// represent slower tempo, larger faster tempo.
|
/// represent slower tempo, larger faster tempo.
|
||||||
void setTempo(float newTempo);
|
void setTempo(double newTempo);
|
||||||
|
|
||||||
/// Sets new rate control value as a difference in percents compared
|
/// Sets new rate control value as a difference in percents compared
|
||||||
/// to the original rate (-50 .. +100 %)
|
/// to the original rate (-50 .. +100 %)
|
||||||
void setRateChange(float newRate);
|
void setRateChange(double newRate);
|
||||||
|
|
||||||
/// Sets new tempo control value as a difference in percents compared
|
/// Sets new tempo control value as a difference in percents compared
|
||||||
/// to the original tempo (-50 .. +100 %)
|
/// to the original tempo (-50 .. +100 %)
|
||||||
void setTempoChange(float newTempo);
|
void setTempoChange(double newTempo);
|
||||||
|
|
||||||
/// Sets new pitch control value. Original pitch = 1.0, smaller values
|
/// Sets new pitch control value. Original pitch = 1.0, smaller values
|
||||||
/// represent lower pitches, larger values higher pitch.
|
/// represent lower pitches, larger values higher pitch.
|
||||||
void setPitch(float newPitch);
|
void setPitch(double newPitch);
|
||||||
|
|
||||||
/// Sets pitch change in octaves compared to the original pitch
|
/// Sets pitch change in octaves compared to the original pitch
|
||||||
/// (-1.00 .. +1.00)
|
/// (-1.00 .. +1.00)
|
||||||
void setPitchOctaves(float newPitch);
|
void setPitchOctaves(double newPitch);
|
||||||
|
|
||||||
/// Sets pitch change in semi-tones compared to the original pitch
|
/// Sets pitch change in semi-tones compared to the original pitch
|
||||||
/// (-12 .. +12)
|
/// (-12 .. +12)
|
||||||
void setPitchSemiTones(int newPitch);
|
void setPitchSemiTones(int newPitch);
|
||||||
void setPitchSemiTones(float newPitch);
|
void setPitchSemiTones(double newPitch);
|
||||||
|
|
||||||
/// Sets the number of channels, 1 = mono, 2 = stereo
|
/// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
void setChannels(uint numChannels);
|
void setChannels(uint numChannels);
|
||||||
@ -240,6 +247,23 @@ public:
|
|||||||
///< contains data for both channels.
|
///< contains data for both channels.
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// Output samples from beginning of the sample buffer. Copies requested samples to
|
||||||
|
/// output buffer and removes them from the sample buffer. If there are less than
|
||||||
|
/// 'numsample' samples in the buffer, returns all that available.
|
||||||
|
///
|
||||||
|
/// \return Number of samples returned.
|
||||||
|
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
|
||||||
|
uint maxSamples ///< How many samples to receive at max.
|
||||||
|
);
|
||||||
|
|
||||||
|
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
|
||||||
|
/// sample buffer without copying them anywhere.
|
||||||
|
///
|
||||||
|
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
|
||||||
|
/// with 'ptrBegin' function.
|
||||||
|
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
|
||||||
|
);
|
||||||
|
|
||||||
/// Clears all the samples in the object's output and internal processing
|
/// Clears all the samples in the object's output and internal processing
|
||||||
/// buffers.
|
/// buffers.
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|||||||
@ -56,7 +56,7 @@ protected:
|
|||||||
const SAMPLETYPE *src,
|
const SAMPLETYPE *src,
|
||||||
int &srcSamples);
|
int &srcSamples);
|
||||||
|
|
||||||
float fract;
|
double fract;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InterpolateCubic();
|
InterpolateCubic();
|
||||||
|
|||||||
@ -170,9 +170,9 @@ int InterpolateLinearInteger::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE
|
|||||||
|
|
||||||
// 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 InterpolateLinearInteger::setRate(float newRate)
|
void InterpolateLinearInteger::setRate(double newRate)
|
||||||
{
|
{
|
||||||
iRate = (int)(newRate * SCALE + 0.5f);
|
iRate = (int)(newRate * SCALE + 0.5);
|
||||||
TransposerBase::setRate(newRate);
|
TransposerBase::setRate(newRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ InterpolateLinearFloat::InterpolateLinearFloat() : TransposerBase()
|
|||||||
// 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.
|
||||||
resetRegisters();
|
resetRegisters();
|
||||||
setRate(1.0f);
|
setRate(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -275,12 +275,13 @@ int InterpolateLinearFloat::transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *s
|
|||||||
i = 0;
|
i = 0;
|
||||||
while (srcCount < srcSampleEnd)
|
while (srcCount < srcSampleEnd)
|
||||||
{
|
{
|
||||||
float temp, vol1;
|
float temp, vol1, fract_float;
|
||||||
|
|
||||||
vol1 = (1.0f- fract);
|
vol1 = (float)(1.0 - fract);
|
||||||
|
fract_float = (float)fract;
|
||||||
for (int c = 0; c < numChannels; c ++)
|
for (int c = 0; c < numChannels; c ++)
|
||||||
{
|
{
|
||||||
temp = vol1 * src[c] + fract * src[c + numChannels];
|
temp = vol1 * src[c] + fract_float * src[c + numChannels];
|
||||||
*dest = (SAMPLETYPE)temp;
|
*dest = (SAMPLETYPE)temp;
|
||||||
dest ++;
|
dest ++;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,7 +63,7 @@ public:
|
|||||||
|
|
||||||
/// 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(double newRate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ public:
|
|||||||
class InterpolateLinearFloat : public TransposerBase
|
class InterpolateLinearFloat : public TransposerBase
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
float fract;
|
double fract;
|
||||||
|
|
||||||
virtual void resetRegisters();
|
virtual void resetRegisters();
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ protected:
|
|||||||
const SAMPLETYPE *src,
|
const SAMPLETYPE *src,
|
||||||
int &srcSamples);
|
int &srcSamples);
|
||||||
|
|
||||||
float fract;
|
double fract;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InterpolateShannon();
|
InterpolateShannon();
|
||||||
|
|||||||
@ -97,20 +97,20 @@ AAFilter *RateTransposer::getAAFilter()
|
|||||||
|
|
||||||
// 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 RateTransposer::setRate(float newRate)
|
void RateTransposer::setRate(double newRate)
|
||||||
{
|
{
|
||||||
double fCutoff;
|
double fCutoff;
|
||||||
|
|
||||||
pTransposer->setRate(newRate);
|
pTransposer->setRate(newRate);
|
||||||
|
|
||||||
// design a new anti-alias filter
|
// design a new anti-alias filter
|
||||||
if (newRate > 1.0f)
|
if (newRate > 1.0)
|
||||||
{
|
{
|
||||||
fCutoff = 0.5f / newRate;
|
fCutoff = 0.5 / newRate;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fCutoff = 0.5f * newRate;
|
fCutoff = 0.5 * newRate;
|
||||||
}
|
}
|
||||||
pAAFilter->setCutoffFreq(fCutoff);
|
pAAFilter->setCutoffFreq(fCutoff);
|
||||||
}
|
}
|
||||||
@ -225,7 +225,7 @@ void TransposerBase::setAlgorithm(TransposerBase::ALGORITHM a)
|
|||||||
int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
|
int TransposerBase::transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src)
|
||||||
{
|
{
|
||||||
int numSrcSamples = src.numSamples();
|
int numSrcSamples = src.numSamples();
|
||||||
int sizeDemand = (int)((float)numSrcSamples / rate) + 8;
|
int sizeDemand = (int)((double)numSrcSamples / rate) + 8;
|
||||||
int numOutput;
|
int numOutput;
|
||||||
SAMPLETYPE *psrc = src.ptrBegin();
|
SAMPLETYPE *psrc = src.ptrBegin();
|
||||||
SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
|
SAMPLETYPE *pdest = dest.ptrEnd(sizeDemand);
|
||||||
@ -270,7 +270,7 @@ void TransposerBase::setChannels(int channels)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TransposerBase::setRate(float newRate)
|
void TransposerBase::setRate(double newRate)
|
||||||
{
|
{
|
||||||
rate = newRate;
|
rate = newRate;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,14 +81,14 @@ protected:
|
|||||||
static ALGORITHM algorithm;
|
static ALGORITHM algorithm;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
float rate;
|
double rate;
|
||||||
int numChannels;
|
int numChannels;
|
||||||
|
|
||||||
TransposerBase();
|
TransposerBase();
|
||||||
virtual ~TransposerBase();
|
virtual ~TransposerBase();
|
||||||
|
|
||||||
virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
|
virtual int transpose(FIFOSampleBuffer &dest, FIFOSampleBuffer &src);
|
||||||
virtual void setRate(float newRate);
|
virtual void setRate(double newRate);
|
||||||
virtual void setChannels(int channels);
|
virtual void setChannels(int channels);
|
||||||
|
|
||||||
// static factory function
|
// static factory function
|
||||||
@ -158,7 +158,7 @@ public:
|
|||||||
|
|
||||||
/// 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(double newRate);
|
||||||
|
|
||||||
/// Sets the number of channels, 1 = mono, 2 = stereo
|
/// Sets the number of channels, 1 = mono, 2 = stereo
|
||||||
void setChannels(int channels);
|
void setChannels(int channels);
|
||||||
|
|||||||
@ -110,6 +110,9 @@ SoundTouch::SoundTouch()
|
|||||||
|
|
||||||
calcEffectiveRateAndTempo();
|
calcEffectiveRateAndTempo();
|
||||||
|
|
||||||
|
samplesExpectedOut = 0;
|
||||||
|
samplesOutput = 0;
|
||||||
|
|
||||||
channels = 0;
|
channels = 0;
|
||||||
bSrateSet = false;
|
bSrateSet = false;
|
||||||
}
|
}
|
||||||
@ -157,7 +160,7 @@ void SoundTouch::setChannels(uint numChannels)
|
|||||||
|
|
||||||
// Sets new rate control value. Normal rate = 1.0, smaller values
|
// Sets new rate control value. Normal rate = 1.0, smaller values
|
||||||
// represent slower rate, larger faster rates.
|
// represent slower rate, larger faster rates.
|
||||||
void SoundTouch::setRate(float newRate)
|
void SoundTouch::setRate(double newRate)
|
||||||
{
|
{
|
||||||
virtualRate = newRate;
|
virtualRate = newRate;
|
||||||
calcEffectiveRateAndTempo();
|
calcEffectiveRateAndTempo();
|
||||||
@ -167,9 +170,9 @@ void SoundTouch::setRate(float newRate)
|
|||||||
|
|
||||||
// Sets new rate control value as a difference in percents compared
|
// Sets new rate control value as a difference in percents compared
|
||||||
// to the original rate (-50 .. +100 %)
|
// to the original rate (-50 .. +100 %)
|
||||||
void SoundTouch::setRateChange(float newRate)
|
void SoundTouch::setRateChange(double newRate)
|
||||||
{
|
{
|
||||||
virtualRate = 1.0f + 0.01f * newRate;
|
virtualRate = 1.0 + 0.01 * newRate;
|
||||||
calcEffectiveRateAndTempo();
|
calcEffectiveRateAndTempo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +180,7 @@ void SoundTouch::setRateChange(float newRate)
|
|||||||
|
|
||||||
// Sets new tempo control value. Normal tempo = 1.0, smaller values
|
// Sets new tempo control value. Normal tempo = 1.0, smaller values
|
||||||
// represent slower tempo, larger faster tempo.
|
// represent slower tempo, larger faster tempo.
|
||||||
void SoundTouch::setTempo(float newTempo)
|
void SoundTouch::setTempo(double newTempo)
|
||||||
{
|
{
|
||||||
virtualTempo = newTempo;
|
virtualTempo = newTempo;
|
||||||
calcEffectiveRateAndTempo();
|
calcEffectiveRateAndTempo();
|
||||||
@ -187,9 +190,9 @@ void SoundTouch::setTempo(float newTempo)
|
|||||||
|
|
||||||
// Sets new tempo control value as a difference in percents compared
|
// Sets new tempo control value as a difference in percents compared
|
||||||
// to the original tempo (-50 .. +100 %)
|
// to the original tempo (-50 .. +100 %)
|
||||||
void SoundTouch::setTempoChange(float newTempo)
|
void SoundTouch::setTempoChange(double newTempo)
|
||||||
{
|
{
|
||||||
virtualTempo = 1.0f + 0.01f * newTempo;
|
virtualTempo = 1.0 + 0.01 * newTempo;
|
||||||
calcEffectiveRateAndTempo();
|
calcEffectiveRateAndTempo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,7 +200,7 @@ void SoundTouch::setTempoChange(float newTempo)
|
|||||||
|
|
||||||
// Sets new pitch control value. Original pitch = 1.0, smaller values
|
// Sets new pitch control value. Original pitch = 1.0, smaller values
|
||||||
// represent lower pitches, larger values higher pitch.
|
// represent lower pitches, larger values higher pitch.
|
||||||
void SoundTouch::setPitch(float newPitch)
|
void SoundTouch::setPitch(double newPitch)
|
||||||
{
|
{
|
||||||
virtualPitch = newPitch;
|
virtualPitch = newPitch;
|
||||||
calcEffectiveRateAndTempo();
|
calcEffectiveRateAndTempo();
|
||||||
@ -207,9 +210,9 @@ void SoundTouch::setPitch(float newPitch)
|
|||||||
|
|
||||||
// Sets pitch change in octaves compared to the original pitch
|
// Sets pitch change in octaves compared to the original pitch
|
||||||
// (-1.00 .. +1.00)
|
// (-1.00 .. +1.00)
|
||||||
void SoundTouch::setPitchOctaves(float newPitch)
|
void SoundTouch::setPitchOctaves(double newPitch)
|
||||||
{
|
{
|
||||||
virtualPitch = (float)exp(0.69314718056f * newPitch);
|
virtualPitch = exp(0.69314718056 * newPitch);
|
||||||
calcEffectiveRateAndTempo();
|
calcEffectiveRateAndTempo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,14 +222,14 @@ void SoundTouch::setPitchOctaves(float newPitch)
|
|||||||
// (-12 .. +12)
|
// (-12 .. +12)
|
||||||
void SoundTouch::setPitchSemiTones(int newPitch)
|
void SoundTouch::setPitchSemiTones(int newPitch)
|
||||||
{
|
{
|
||||||
setPitchOctaves((float)newPitch / 12.0f);
|
setPitchOctaves((double)newPitch / 12.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void SoundTouch::setPitchSemiTones(float newPitch)
|
void SoundTouch::setPitchSemiTones(double newPitch)
|
||||||
{
|
{
|
||||||
setPitchOctaves(newPitch / 12.0f);
|
setPitchOctaves(newPitch / 12.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -234,14 +237,14 @@ void SoundTouch::setPitchSemiTones(float newPitch)
|
|||||||
// nominal control values.
|
// nominal control values.
|
||||||
void SoundTouch::calcEffectiveRateAndTempo()
|
void SoundTouch::calcEffectiveRateAndTempo()
|
||||||
{
|
{
|
||||||
float oldTempo = tempo;
|
double oldTempo = tempo;
|
||||||
float oldRate = rate;
|
double oldRate = rate;
|
||||||
|
|
||||||
tempo = virtualTempo / virtualPitch;
|
tempo = virtualTempo / virtualPitch;
|
||||||
rate = virtualPitch * virtualRate;
|
rate = virtualPitch * virtualRate;
|
||||||
|
|
||||||
if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate);
|
if (!TEST_FLOAT_EQUAL(rate,oldRate)) pRateTransposer->setRate(rate);
|
||||||
if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo);
|
if (!TEST_FLOAT_EQUAL(tempo, oldTempo)) pTDStretch->setTempo(tempo);
|
||||||
|
|
||||||
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
||||||
if (rate <= 1.0f)
|
if (rate <= 1.0f)
|
||||||
@ -317,8 +320,13 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
|
|||||||
pTDStretch->putSamples(samples, nSamples);
|
pTDStretch->putSamples(samples, nSamples);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// accumulate how many samples are expected out from processing, given the current
|
||||||
|
// processing setting
|
||||||
|
samplesExpectedOut += (double)nSamples / ((double)rate * (double)tempo);
|
||||||
|
|
||||||
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
#ifndef SOUNDTOUCH_PREVENT_CLICK_AT_RATE_CROSSOVER
|
||||||
else if (rate <= 1.0f)
|
if (rate <= 1.0f)
|
||||||
{
|
{
|
||||||
// transpose the rate down, output the transposed sound to tempo changer buffer
|
// transpose the rate down, output the transposed sound to tempo changer buffer
|
||||||
assert(output == pTDStretch);
|
assert(output == pTDStretch);
|
||||||
@ -346,44 +354,30 @@ void SoundTouch::putSamples(const SAMPLETYPE *samples, uint nSamples)
|
|||||||
void SoundTouch::flush()
|
void SoundTouch::flush()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int nUnprocessed;
|
int numStillExpected;
|
||||||
int nOut;
|
SAMPLETYPE *buff = new SAMPLETYPE[128 * channels];
|
||||||
SAMPLETYPE *buff = new SAMPLETYPE[64 * channels];
|
|
||||||
|
|
||||||
// check how many samples still await processing, and scale
|
|
||||||
// that by tempo & rate to get expected output sample count
|
|
||||||
nUnprocessed = numUnprocessedSamples();
|
|
||||||
nUnprocessed = (int)((double)nUnprocessed / (tempo * rate) + 0.5);
|
|
||||||
|
|
||||||
nOut = numSamples(); // ready samples currently in buffer ...
|
// how many samples are still expected to output
|
||||||
nOut += nUnprocessed; // ... and how many we expect there to be in the end
|
numStillExpected = (int)((long)(samplesExpectedOut + 0.5) - samplesOutput);
|
||||||
|
|
||||||
memset(buff, 0, 64 * channels * sizeof(SAMPLETYPE));
|
memset(buff, 0, 128 * channels * sizeof(SAMPLETYPE));
|
||||||
// "Push" the last active samples out from the processing pipeline by
|
// "Push" the last active samples out from the processing pipeline by
|
||||||
// feeding blank samples into the processing pipeline until new,
|
// feeding blank samples into the processing pipeline until new,
|
||||||
// processed samples appear in the output (not however, more than
|
// processed samples appear in the output (not however, more than
|
||||||
// 8ksamples in any case)
|
// 24ksamples in any case)
|
||||||
for (i = 0; i < 128; i ++)
|
for (i = 0; (numStillExpected > (int)numSamples()) && (i < 200); i ++)
|
||||||
{
|
{
|
||||||
putSamples(buff, 64);
|
putSamples(buff, 128);
|
||||||
if ((int)numSamples() >= nOut)
|
}
|
||||||
{
|
|
||||||
// Enough new samples have appeared into the output!
|
|
||||||
// As samples come from processing with bigger chunks, now truncate it
|
|
||||||
// back to maximum "nOut" samples to improve duration accuracy
|
|
||||||
adjustAmountOfSamples(nOut);
|
|
||||||
|
|
||||||
// finish
|
adjustAmountOfSamples(numStillExpected);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] buff;
|
delete[] buff;
|
||||||
|
|
||||||
// Clear working buffers
|
// Clear input buffers
|
||||||
pRateTransposer->clear();
|
// pRateTransposer->clearInput();
|
||||||
pTDStretch->clearInput();
|
pTDStretch->clearInput();
|
||||||
// yet leave the 'tempoChanger' output intouched as that's where the
|
// yet leave the output intouched as that's where the
|
||||||
// flushed samples are!
|
// flushed samples are!
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,6 +476,7 @@ int SoundTouch::getSetting(int settingId) const
|
|||||||
// buffers.
|
// buffers.
|
||||||
void SoundTouch::clear()
|
void SoundTouch::clear()
|
||||||
{
|
{
|
||||||
|
samplesExpectedOut = 0;
|
||||||
pRateTransposer->clear();
|
pRateTransposer->clear();
|
||||||
pTDStretch->clear();
|
pTDStretch->clear();
|
||||||
}
|
}
|
||||||
@ -502,3 +497,30 @@ uint SoundTouch::numUnprocessedSamples() const
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Output samples from beginning of the sample buffer. Copies requested samples to
|
||||||
|
/// output buffer and removes them from the sample buffer. If there are less than
|
||||||
|
/// 'numsample' samples in the buffer, returns all that available.
|
||||||
|
///
|
||||||
|
/// \return Number of samples returned.
|
||||||
|
uint SoundTouch::receiveSamples(SAMPLETYPE *output, uint maxSamples)
|
||||||
|
{
|
||||||
|
uint ret = FIFOProcessor::receiveSamples(output, maxSamples);
|
||||||
|
samplesOutput += (long)ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
|
||||||
|
/// sample buffer without copying them anywhere.
|
||||||
|
///
|
||||||
|
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
|
||||||
|
/// with 'ptrBegin' function.
|
||||||
|
uint SoundTouch::receiveSamples(uint maxSamples)
|
||||||
|
{
|
||||||
|
uint ret = FIFOProcessor::receiveSamples(maxSamples);
|
||||||
|
samplesOutput += (long)ret;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
@ -459,7 +459,7 @@ void TDStretch::calcSeqParameters()
|
|||||||
|
|
||||||
// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
|
// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
|
||||||
// tempo, larger faster tempo.
|
// tempo, larger faster tempo.
|
||||||
void TDStretch::setTempo(float newTempo)
|
void TDStretch::setTempo(double newTempo)
|
||||||
{
|
{
|
||||||
int intskip;
|
int intskip;
|
||||||
|
|
||||||
@ -470,7 +470,7 @@ void TDStretch::setTempo(float newTempo)
|
|||||||
|
|
||||||
// Calculate ideal skip length (according to tempo value)
|
// Calculate ideal skip length (according to tempo value)
|
||||||
nominalSkip = tempo * (seekWindowLength - overlapLength);
|
nominalSkip = tempo * (seekWindowLength - overlapLength);
|
||||||
intskip = (int)(nominalSkip + 0.5f);
|
intskip = (int)(nominalSkip + 0.5);
|
||||||
|
|
||||||
// Calculate how many samples are needed in the 'inputBuffer' to
|
// Calculate how many samples are needed in the 'inputBuffer' to
|
||||||
// process another batch of samples
|
// process another batch of samples
|
||||||
|
|||||||
@ -112,7 +112,7 @@ class TDStretch : public FIFOProcessor
|
|||||||
protected:
|
protected:
|
||||||
int channels;
|
int channels;
|
||||||
int sampleReq;
|
int sampleReq;
|
||||||
float tempo;
|
double tempo;
|
||||||
|
|
||||||
SAMPLETYPE *pMidBuffer;
|
SAMPLETYPE *pMidBuffer;
|
||||||
SAMPLETYPE *pMidBufferUnaligned;
|
SAMPLETYPE *pMidBufferUnaligned;
|
||||||
@ -121,8 +121,8 @@ protected:
|
|||||||
int seekWindowLength;
|
int seekWindowLength;
|
||||||
int overlapDividerBits;
|
int overlapDividerBits;
|
||||||
int slopingDivider;
|
int slopingDivider;
|
||||||
float nominalSkip;
|
double nominalSkip;
|
||||||
float skipFract;
|
double skipFract;
|
||||||
FIFOSampleBuffer outputBuffer;
|
FIFOSampleBuffer outputBuffer;
|
||||||
FIFOSampleBuffer inputBuffer;
|
FIFOSampleBuffer inputBuffer;
|
||||||
bool bQuickSeek;
|
bool bQuickSeek;
|
||||||
@ -182,7 +182,7 @@ public:
|
|||||||
|
|
||||||
/// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
|
/// Sets new target tempo. Normal tempo = 'SCALE', smaller values represent slower
|
||||||
/// tempo, larger faster tempo.
|
/// tempo, larger faster tempo.
|
||||||
void setTempo(float newTempo);
|
void setTempo(double newTempo);
|
||||||
|
|
||||||
/// Returns nonzero if there aren't any samples available for outputting.
|
/// Returns nonzero if there aren't any samples available for outputting.
|
||||||
virtual void clear();
|
virtual void clear();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user