* Rationalise naming: block -> window or chunk

This commit is contained in:
Chris Cannam
2007-11-18 21:38:18 +00:00
parent 35dc16b611
commit f327e0c415
17 changed files with 272 additions and 289 deletions

View File

@@ -72,7 +72,7 @@ public:
virtual void setPhaseOption(Options options);
virtual void setExpectedInputDuration(size_t samples);
virtual void setMaxProcessBlockSize(size_t samples);
virtual void setMaxProcessSize(size_t samples);
virtual size_t getSamplesRequired() const;
// if samples == 0, input may be null

View File

@@ -17,9 +17,9 @@
namespace RubberBand
{
AudioCurve::AudioCurve(size_t sampleRate, size_t blockSize) :
AudioCurve::AudioCurve(size_t sampleRate, size_t windowSize) :
m_sampleRate(sampleRate),
m_blockSize(blockSize)
m_windowSize(windowSize)
{
}

View File

@@ -23,17 +23,17 @@ namespace RubberBand
class AudioCurve
{
public:
AudioCurve(size_t sampleRate, size_t blockSize);
AudioCurve(size_t sampleRate, size_t windowSize);
virtual ~AudioCurve();
virtual void setBlockSize(size_t newSize) = 0;
virtual void setWindowSize(size_t newSize) = 0;
virtual float process(float *mag, size_t increment) = 0;
virtual void reset() = 0;
protected:
size_t m_sampleRate;
size_t m_blockSize;
size_t m_windowSize;
};
}

View File

@@ -17,8 +17,8 @@
namespace RubberBand
{
ConstantAudioCurve::ConstantAudioCurve(size_t sampleRate, size_t blockSize) :
AudioCurve(sampleRate, blockSize)
ConstantAudioCurve::ConstantAudioCurve(size_t sampleRate, size_t windowSize) :
AudioCurve(sampleRate, windowSize)
{
}
@@ -32,9 +32,9 @@ ConstantAudioCurve::reset()
}
void
ConstantAudioCurve::setBlockSize(size_t newSize)
ConstantAudioCurve::setWindowSize(size_t newSize)
{
m_blockSize = newSize;
m_windowSize = newSize;
}
float

View File

@@ -23,10 +23,10 @@ namespace RubberBand
class ConstantAudioCurve : public AudioCurve
{
public:
ConstantAudioCurve(size_t sampleRate, size_t blockSize);
ConstantAudioCurve(size_t sampleRate, size_t windowSize);
virtual ~ConstantAudioCurve();
virtual void setBlockSize(size_t newSize);
virtual void setWindowSize(size_t newSize);
virtual float process(float *mag, size_t increment);
virtual void reset();

View File

@@ -17,12 +17,12 @@
namespace RubberBand
{
HighFrequencyAudioCurve::HighFrequencyAudioCurve(size_t sampleRate, size_t blockSize) :
AudioCurve(sampleRate, blockSize)
HighFrequencyAudioCurve::HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize) :
AudioCurve(sampleRate, windowSize)
{
m_prevMag = new double[m_blockSize/2 + 1];
m_prevMag = new double[m_windowSize/2 + 1];
for (size_t i = 0; i <= m_blockSize/2; ++i) {
for (size_t i = 0; i <= m_windowSize/2; ++i) {
m_prevMag[i] = 0.f;
}
}
@@ -35,15 +35,15 @@ HighFrequencyAudioCurve::~HighFrequencyAudioCurve()
void
HighFrequencyAudioCurve::reset()
{
for (size_t i = 0; i <= m_blockSize/2; ++i) {
for (size_t i = 0; i <= m_windowSize/2; ++i) {
m_prevMag[i] = 0;
}
}
void
HighFrequencyAudioCurve::setBlockSize(size_t newSize)
HighFrequencyAudioCurve::setWindowSize(size_t newSize)
{
m_blockSize = newSize;
m_windowSize = newSize;
}
float
@@ -51,7 +51,7 @@ HighFrequencyAudioCurve::process(float *mag, size_t increment)
{
float result = 0.0;
for (size_t n = 0; n <= m_blockSize / 2; ++n) {
for (size_t n = 0; n <= m_windowSize / 2; ++n) {
result += mag[n];
}

View File

@@ -24,11 +24,11 @@ namespace RubberBand
class HighFrequencyAudioCurve : public AudioCurve
{
public:
HighFrequencyAudioCurve(size_t sampleRate, size_t blockSize);
HighFrequencyAudioCurve(size_t sampleRate, size_t windowSize);
virtual ~HighFrequencyAudioCurve();
virtual void setBlockSize(size_t newSize);
virtual void setWindowSize(size_t newSize);
virtual float process(float *mag, size_t increment);
virtual void reset();

View File

@@ -19,12 +19,12 @@
namespace RubberBand
{
PercussiveAudioCurve::PercussiveAudioCurve(size_t sampleRate, size_t blockSize) :
AudioCurve(sampleRate, blockSize)
PercussiveAudioCurve::PercussiveAudioCurve(size_t sampleRate, size_t windowSize) :
AudioCurve(sampleRate, windowSize)
{
m_prevMag = new double[m_blockSize/2 + 1];
m_prevMag = new double[m_windowSize/2 + 1];
for (size_t i = 0; i <= m_blockSize/2; ++i) {
for (size_t i = 0; i <= m_windowSize/2; ++i) {
m_prevMag[i] = 0.f;
}
}
@@ -37,18 +37,18 @@ PercussiveAudioCurve::~PercussiveAudioCurve()
void
PercussiveAudioCurve::reset()
{
for (size_t i = 0; i <= m_blockSize/2; ++i) {
for (size_t i = 0; i <= m_windowSize/2; ++i) {
m_prevMag[i] = 0;
}
}
void
PercussiveAudioCurve::setBlockSize(size_t newSize)
PercussiveAudioCurve::setWindowSize(size_t newSize)
{
delete[] m_prevMag;
m_blockSize = newSize;
m_windowSize = newSize;
m_prevMag = new double[m_blockSize/2 + 1];
m_prevMag = new double[m_windowSize/2 + 1];
reset();
}
@@ -62,7 +62,7 @@ PercussiveAudioCurve::process(float *mag, size_t increment)
size_t count = 0;
size_t nonZeroCount = 0;
for (size_t n = 1; n <= m_blockSize / 2; ++n) {
for (size_t n = 1; n <= m_windowSize / 2; ++n) {
//!!! adjust threshold so that this multiplication is unnecessary
float sqrmag = mag[n] * mag[n];
bool above = ((sqrmag / m_prevMag[n]) >= threshold);
@@ -71,7 +71,7 @@ PercussiveAudioCurve::process(float *mag, size_t increment)
m_prevMag[n] = sqrmag;
}
//!!! return float(count) / float(m_blockSize);
//!!! return float(count) / float(m_windowSize);
if (nonZeroCount == 0) return 0;
else return float(count) / float(nonZeroCount);
}

View File

@@ -23,11 +23,11 @@ namespace RubberBand
class PercussiveAudioCurve : public AudioCurve
{
public:
PercussiveAudioCurve(size_t sampleRate, size_t blockSize);
PercussiveAudioCurve(size_t sampleRate, size_t windowSize);
virtual ~PercussiveAudioCurve();
virtual void setBlockSize(size_t newSize);
virtual void setWindowSize(size_t newSize);
virtual float process(float *mag, size_t increment);
virtual void reset();

View File

@@ -88,9 +88,9 @@ RubberBandStretcher::setExpectedInputDuration(size_t samples)
}
void
RubberBandStretcher::setMaxProcessBlockSize(size_t samples)
RubberBandStretcher::setMaxProcessSize(size_t samples)
{
m_d->setMaxProcessBlockSize(samples);
m_d->setMaxProcessSize(samples);
}
size_t

View File

@@ -51,10 +51,6 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
//!!! This description is out of date.
//!!! Rationalise naming -- generally wise to avoid the word
//"frame" and instead use "block" / "sample" for processing frame /
// audio frame.
// 1. Pre-process the df array, and for each (say) one second's
// worth of values, calculate the number of peaks that would
// qualify for phase locking given the default threshold. Then
@@ -74,12 +70,12 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
// ensure that their timing is strictly "correct".
// 4. Calculate how much time is left in the stretch total, after
// each of the locked frames has been allocated its static
// allowance. Also count the non-locked frames.
// each of the locked chunks has been allocated its static
// allowance. Also count the non-locked chunks.
// 5. For each region between two locked frames, calculate the
// 5. For each region between two locked chunks, calculate the
// number of samples to allocate that region given the time
// available for stretch and the number of non-locked frames.
// available for stretch and the number of non-locked chunks.
// Then divvy them up... how exactly?
@@ -109,11 +105,11 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
// size_t stretchable = outputDuration - lockCount * m_increment;
std::vector<size_t> fixedAudioFrames;
std::vector<size_t> fixedAudioChunks;
for (size_t i = 0; i < peaks.size(); ++i) {
fixedAudioFrames.push_back
fixedAudioChunks.push_back
//!!! this should be rounding down, shouldn't it? not lrint?
(lrint((double(peaks[i].frame) * outputDuration) / totalCount));
(lrint((double(peaks[i].chunk) * outputDuration) / totalCount));
}
// size_t lockIndex = 0;
@@ -125,9 +121,9 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
size_t totalInput = 0, totalOutput = 0;
// so for each inter-lock region, we want to take the number of
// output frames to be allocated and the detection function values
// output chunks to be allocated and the detection function values
// within the range, and produce a series of increments that sum
// to the number of output frames, such that each increment is
// to the number of output chunks, such that each increment is
// displaced from the input increment by an amount inversely
// proportional to the magnitude of the detection function at that
// input step. Ideally the detection function would have been
@@ -136,41 +132,41 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
//!!! Actually, we would possibly be better off using a fixed
// smooth curve than the detection function itself.
size_t regionTotalFrames = 0;
size_t regionTotalChunks = 0;
for (size_t i = 0; i <= peaks.size(); ++i) {
size_t regionStart, regionStartBlock, regionEnd, regionEndBlock;
size_t regionStart, regionStartChunk, regionEnd, regionEndChunk;
bool phaseLock = false;
if (i == 0) {
regionStartBlock = 0;
regionStartChunk = 0;
regionStart = 0;
} else {
regionStartBlock = peaks[i-1].frame;
regionStart = fixedAudioFrames[i-1];
regionStartChunk = peaks[i-1].chunk;
regionStart = fixedAudioChunks[i-1];
phaseLock = peaks[i-1].hard;
}
if (i == peaks.size()) {
regionEndBlock = totalCount;
regionEndChunk = totalCount;
regionEnd = outputDuration;
} else {
regionEndBlock = peaks[i].frame;
regionEnd = fixedAudioFrames[i];
regionEndChunk = peaks[i].chunk;
regionEnd = fixedAudioChunks[i];
}
size_t regionDuration = regionEnd - regionStart;
regionTotalFrames += regionDuration;
regionTotalChunks += regionDuration;
std::vector<float> dfRegion;
for (size_t j = regionStartBlock; j != regionEndBlock; ++j) {
for (size_t j = regionStartChunk; j != regionEndChunk; ++j) {
dfRegion.push_back(stretchDf[j]);
}
if (m_debugLevel > 1) {
std::cerr << "distributeRegion from " << regionStartBlock << " to " << regionEndBlock << " (frames " << regionStart << " to " << regionEnd << ")" << std::endl;
std::cerr << "distributeRegion from " << regionStartChunk << " to " << regionEndChunk << " (chunks " << regionStart << " to " << regionEnd << ")" << std::endl;
}
dfRegion = smoothDF(dfRegion);
@@ -201,8 +197,8 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
}
if (m_debugLevel > 0) {
std::cerr << "total input increment = " << totalInput << " (= " << totalInput / m_increment << " blocks), output = " << totalOutput << ", ratio = " << double(totalOutput)/double(totalInput) << ", ideal output " << ceil(totalInput * ratio) << std::endl;
std::cerr << "(region total = " << regionTotalFrames << ")" << std::endl;
std::cerr << "total input increment = " << totalInput << " (= " << totalInput / m_increment << " chunks), output = " << totalOutput << ", ratio = " << double(totalOutput)/double(totalInput) << ", ideal output " << ceil(totalInput * ratio) << std::endl;
std::cerr << "(region total = " << regionTotalChunks << ")" << std::endl;
}
return increments;
}
@@ -215,10 +211,10 @@ StretchCalculator::calculateSingle(double ratio,
bool isTransient = false;
//!!! We want to ensure, as close as possible, that the lock
// points appear at _exactly_ the right frame numbers
// points appear at _exactly_ the right audio frame numbers
//!!! depends on block size. larger block sizes need higher
//thresholds. since block size depends on ratio, I suppose we
//!!! depends on chunk size. larger chunk sizes need higher
//thresholds. since chunk size depends on ratio, I suppose we
//could in theory calculate the threshold from the ratio directly.
//For now we just frig it to work OK for a couple of common cases
float transientThreshold = 0.35;
@@ -306,7 +302,7 @@ StretchCalculator::findPeaks(const std::vector<float> &rawDf)
std::cerr << "hardPeakAmnesty = " << hardPeakAmnesty << std::endl;
for (size_t i = 1; i + 1 < df.size(); ++i) {
//!!! this ratio configurable? dependent on block size and sr?
//!!! this ratio configurable? dependent on chunk size and sr?
if (df[i] < 0.1) continue;
if (df[i] <= df[i-1] * 1.2) continue;
@@ -518,14 +514,14 @@ StretchCalculator::findPeaks(const std::vector<float> &rawDf)
size_t softPeak = (haveSoftPeak ? *softPeakCandidates.begin() : 0);
Peak peak;
peak.hard = false;
peak.frame = softPeak;
peak.chunk = softPeak;
if (haveHardPeak &&
(!haveSoftPeak || hardPeak <= softPeak)) {
if (m_debugLevel > 2) {
std::cerr << "Hard peak: " << hardPeak << std::endl;
}
peak.hard = true;
peak.frame = hardPeak;
peak.chunk = hardPeak;
hardPeakCandidates.erase(hardPeakCandidates.begin());
} else {
if (m_debugLevel > 2) {
@@ -533,7 +529,7 @@ StretchCalculator::findPeaks(const std::vector<float> &rawDf)
}
}
if (haveSoftPeak && peak.frame == softPeak) {
if (haveSoftPeak && peak.chunk == softPeak) {
softPeakCandidates.erase(softPeakCandidates.begin());
}
@@ -616,7 +612,7 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
// bool negative = (toAllot < 0);
if (m_debugLevel > 1) {
std::cerr << "region of " << df.size() << " blocks, output duration " << duration << ", toAllot " << toAllot << std::endl;
std::cerr << "region of " << df.size() << " chunks, output duration " << duration << ", toAllot " << toAllot << std::endl;
}
size_t totalIncrement = 0;

View File

@@ -54,7 +54,7 @@ public:
void setDebugLevel(int level) { m_debugLevel = level; }
struct Peak {
size_t frame;
size_t chunk;
bool hard;
};
std::vector<Peak> getLastCalculatedPeaks() const { return m_lastPeaks; }

View File

@@ -7,39 +7,39 @@
namespace RubberBand
{
RubberBandStretcher::Impl::ChannelData::ChannelData(size_t blockSize,
RubberBandStretcher::Impl::ChannelData::ChannelData(size_t windowSize,
size_t outbufSize)
{
std::set<size_t> s;
construct(s, blockSize, outbufSize);
construct(s, windowSize, outbufSize);
}
RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &blockSizes,
size_t initialBlockSize,
RubberBandStretcher::Impl::ChannelData::ChannelData(const std::set<size_t> &windowSizes,
size_t initialWindowSize,
size_t outbufSize)
{
construct(blockSizes, initialBlockSize, outbufSize);
construct(windowSizes, initialWindowSize, outbufSize);
}
void
RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &blockSizes,
size_t initialBlockSize,
RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &windowSizes,
size_t initialWindowSize,
size_t outbufSize)
{
size_t maxSize = initialBlockSize;
size_t maxSize = initialWindowSize;
if (!blockSizes.empty()) {
if (!windowSizes.empty()) {
// std::set is ordered by value
std::set<size_t>::const_iterator i = blockSizes.end();
std::set<size_t>::const_iterator i = windowSizes.end();
maxSize = *--i;
}
if (blockSizes.find(initialBlockSize) == blockSizes.end()) {
if (initialBlockSize > maxSize) maxSize = initialBlockSize;
if (windowSizes.find(initialWindowSize) == windowSizes.end()) {
if (initialWindowSize > maxSize) maxSize = initialWindowSize;
}
size_t realSize = maxSize/2 + 1; // size of the real "half" of freq data
std::cerr << "ChannelData::construct([" << blockSizes.size() << "], " << maxSize << ", " << outbufSize << ")" << std::endl;
std::cerr << "ChannelData::construct([" << windowSizes.size() << "], " << maxSize << ", " << outbufSize << ")" << std::endl;
if (outbufSize < maxSize) outbufSize = maxSize;
@@ -58,16 +58,16 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &blockS
fltbuf = new float[maxSize];
dblbuf = new double[maxSize];
for (std::set<size_t>::const_iterator i = blockSizes.begin();
i != blockSizes.end(); ++i) {
for (std::set<size_t>::const_iterator i = windowSizes.begin();
i != windowSizes.end(); ++i) {
ffts[*i] = new FFT(*i);
ffts[*i]->initDouble();
}
if (blockSizes.find(initialBlockSize) == blockSizes.end()) {
ffts[initialBlockSize] = new FFT(initialBlockSize);
ffts[initialBlockSize]->initDouble();
if (windowSizes.find(initialWindowSize) == windowSizes.end()) {
ffts[initialWindowSize] = new FFT(initialWindowSize);
ffts[initialWindowSize]->initDouble();
}
fft = ffts[initialBlockSize];
fft = ffts[initialWindowSize];
resampler = 0;
resamplebuf = 0;
@@ -92,14 +92,14 @@ RubberBandStretcher::Impl::ChannelData::construct(const std::set<size_t> &blockS
}
void
RubberBandStretcher::Impl::ChannelData::setBlockSize(size_t blockSize)
RubberBandStretcher::Impl::ChannelData::setWindowSize(size_t windowSize)
{
size_t oldSize = inbuf->getSize();
size_t realSize = blockSize/2 + 1;
size_t realSize = windowSize/2 + 1;
std::cerr << "ChannelData::setBlockSize(" << blockSize << ") [from " << oldSize << "]" << std::endl;
std::cerr << "ChannelData::setWindowSize(" << windowSize << ") [from " << oldSize << "]" << std::endl;
if (oldSize >= blockSize) {
if (oldSize >= windowSize) {
// no need to reallocate buffers, just reselect fft
@@ -107,14 +107,14 @@ RubberBandStretcher::Impl::ChannelData::setBlockSize(size_t blockSize)
//process thread, can we? we need to zero the mag/phase
//buffers without interference
if (ffts.find(blockSize) == ffts.end()) {
if (ffts.find(windowSize) == ffts.end()) {
//!!! this also requires a lock, but it shouldn't occur in
//RT mode with proper initialisation
ffts[blockSize] = new FFT(blockSize);
ffts[blockSize]->initDouble();
ffts[windowSize] = new FFT(windowSize);
ffts[windowSize]->initDouble();
}
fft = ffts[blockSize];
fft = ffts[windowSize];
for (size_t i = 0; i < realSize; ++i) {
mag[i] = 0.0;
@@ -134,7 +134,7 @@ RubberBandStretcher::Impl::ChannelData::setBlockSize(size_t blockSize)
//is unavailable (since this should never normally be the case in
//general use in RT mode)
RingBuffer<float> *newbuf = inbuf->resized(blockSize);
RingBuffer<float> *newbuf = inbuf->resized(windowSize);
delete inbuf;
inbuf = newbuf;
@@ -155,17 +155,17 @@ RubberBandStretcher::Impl::ChannelData::setBlockSize(size_t blockSize)
delete[] fltbuf;
delete[] dblbuf;
fltbuf = new float[blockSize];
dblbuf = new double[blockSize];
fltbuf = new float[windowSize];
dblbuf = new double[windowSize];
// But we do want to preserve data in these
float *newAcc = new float[blockSize];
float *newAcc = new float[windowSize];
for (size_t i = 0; i < oldSize; ++i) newAcc[i] = accumulator[i];
delete[] accumulator;
accumulator = newAcc;
newAcc = new float[blockSize];
newAcc = new float[windowSize];
for (size_t i = 0; i < oldSize; ++i) newAcc[i] = windowAccumulator[i];
delete[] windowAccumulator;
windowAccumulator = newAcc;
@@ -180,22 +180,22 @@ RubberBandStretcher::Impl::ChannelData::setBlockSize(size_t blockSize)
freqPeak[i] = 0;
}
for (size_t i = 0; i < blockSize; ++i) {
for (size_t i = 0; i < windowSize; ++i) {
dblbuf[i] = 0.0;
fltbuf[i] = 0.0;
}
for (size_t i = oldSize; i < blockSize; ++i) {
for (size_t i = oldSize; i < windowSize; ++i) {
accumulator[i] = 0.f;
windowAccumulator[i] = 0.f;
}
if (ffts.find(blockSize) == ffts.end()) {
ffts[blockSize] = new FFT(blockSize);
ffts[blockSize]->initDouble();
if (ffts.find(windowSize) == ffts.end()) {
ffts[windowSize] = new FFT(windowSize);
ffts[windowSize]->initDouble();
}
fft = ffts[blockSize];
fft = ffts[windowSize];
}
void
@@ -253,7 +253,7 @@ RubberBandStretcher::Impl::ChannelData::reset()
accumulatorFill = 0;
prevIncrement = 0;
blockCount = 0;
chunkCount = 0;
inCount = 0;
inputSize = -1;
outCount = 0;

View File

@@ -30,7 +30,7 @@ public:
/**
* Construct a ChannelData structure.
*
* The block size passed in here is the size for the FFT
* The window size passed in here is the size for the FFT
* calculation, and most of the buffer sizes also depend on
* it. In practice it is always a power of two and except for
* very extreme stretches is always either 1024, 2048 or 4096.
@@ -39,22 +39,22 @@ public:
* the pitch scale factor and any maximum processing block
* size specified by the user of the code.
*/
ChannelData(size_t blockSize, size_t outbufSize);
ChannelData(size_t windowSize, size_t outbufSize);
/**
* Construct a ChannelData structure that can process at
* different FFT sizes without requiring reallocation when the
* size changes. The size can subsequently be changed with a
* call to setBlockSize. Reallocation will only be necessary
* if setBlockSize is called with a value not equal to one of
* call to setWindowSize. Reallocation will only be necessary
* if setWindowSize is called with a value not equal to one of
* those passed in to the constructor.
*
* The outbufSize should be the maximum possible outbufSize to
* avoid reallocation, which will happen if setOutbufSize is
* called subsequently.
*/
ChannelData(const std::set<size_t> &blockSizes,
size_t initialBlockSize, size_t outbufSize);
ChannelData(const std::set<size_t> &windowSizes,
size_t initialWindowSize, size_t outbufSize);
~ChannelData();
/**
@@ -64,11 +64,11 @@ public:
/**
* Set the FFT and buffer sizes from the given processing
* block size. If this ChannelData was constructed with a set
* of block sizes and the given block size here was among
* window size. If this ChannelData was constructed with a set
* of window sizes and the given window size here was among
* them, no reallocation will be required.
*/
void setBlockSize(size_t blockSize);
void setWindowSize(size_t windowSize);
/**
* Set the outbufSize for the channel data. Reallocation will
@@ -96,7 +96,7 @@ public:
size_t prevIncrement; // only used in RT mode
size_t blockCount;
size_t chunkCount;
size_t inCount;
long inputSize; // set only after known (when data ended); -1 previously
size_t outCount;
@@ -112,8 +112,8 @@ public:
size_t resamplebufSize;
private:
void construct(const std::set<size_t> &blockSizes,
size_t initialBlockSize, size_t outbufSize);
void construct(const std::set<size_t> &windowSizes,
size_t initialWindowSize, size_t outbufSize);
};
}

View File

@@ -36,7 +36,7 @@ using std::min;
namespace RubberBand {
static const size_t defaultIncrement = 256;
static const size_t defaultBlockSize = 2048;
static const size_t defaultWindowSize = 2048;
RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher,
size_t sampleRate,
@@ -48,10 +48,10 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher,
m_channels(channels),
m_timeRatio(initialTimeRatio),
m_pitchScale(initialPitchScale),
m_blockSize(defaultBlockSize),
m_outbufSize(defaultBlockSize * 2),
m_windowSize(defaultWindowSize),
m_increment(defaultIncrement),
m_maxProcessBlockSize(defaultBlockSize),
m_outbufSize(defaultWindowSize * 2),
m_maxProcessSize(defaultWindowSize),
m_expectedInputDuration(0),
m_threaded(false),
m_realtime(false),
@@ -69,7 +69,7 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher,
m_freq0(600),
m_freq1(1200),
m_freq2(12000),
m_baseBlockSize(defaultBlockSize)
m_baseWindowSize(defaultWindowSize)
{
cerr << "RubberBandStretcher::Impl::Impl: options = " << options << endl;
@@ -77,15 +77,15 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher,
if ((options & OptionWindowShort) && (options & OptionWindowLong)) {
cerr << "RubberBandStretcher::Impl::Impl: Cannot specify OptionWindowLong and OptionWindowShort together; falling back to OptionWindowStandard" << endl;
} else if (options & OptionWindowShort) {
m_baseBlockSize = defaultBlockSize / 2;
cerr << "setting baseBlockSize to " << m_baseBlockSize << endl;
m_baseWindowSize = defaultWindowSize / 2;
cerr << "setting baseWindowSize to " << m_baseWindowSize << endl;
} else if (options & OptionWindowLong) {
m_baseBlockSize = defaultBlockSize * 2;
cerr << "setting baseBlockSize to " << m_baseBlockSize << endl;
m_baseWindowSize = defaultWindowSize * 2;
cerr << "setting baseWindowSize to " << m_baseWindowSize << endl;
}
m_blockSize = m_baseBlockSize;
m_outbufSize = m_baseBlockSize * 2;
m_maxProcessBlockSize = m_baseBlockSize;
m_windowSize = m_baseWindowSize;
m_outbufSize = m_baseWindowSize * 2;
m_maxProcessSize = m_baseWindowSize;
}
if (m_options & OptionProcessRealTime) {
@@ -154,7 +154,7 @@ RubberBandStretcher::Impl::reset()
for (size_t c = 0; c < m_channels; ++c) {
delete m_channelData[c];
m_channelData[c] = new ChannelData(m_blockSize, m_outbufSize);
m_channelData[c] = new ChannelData(m_windowSize, m_outbufSize);
}
m_mode = JustCreated;
if (m_lockAudioCurve) m_lockAudioCurve->reset();
@@ -219,10 +219,10 @@ RubberBandStretcher::Impl::setExpectedInputDuration(size_t samples)
}
void
RubberBandStretcher::Impl::setMaxProcessBlockSize(size_t samples)
RubberBandStretcher::Impl::setMaxProcessSize(size_t samples)
{
if (samples <= m_maxProcessBlockSize) return;
m_maxProcessBlockSize = samples;
if (samples <= m_maxProcessSize) return;
m_maxProcessSize = samples;
reconfigure();
}
@@ -279,7 +279,7 @@ void
RubberBandStretcher::Impl::calculateSizes()
{
size_t inputIncrement = defaultIncrement;
size_t blockSize = m_baseBlockSize;
size_t windowSize = m_baseWindowSize;
size_t outputIncrement;
double r = getEffectiveRatio();
@@ -295,7 +295,7 @@ RubberBandStretcher::Impl::calculateSizes()
if (outputIncrement < 1) {
outputIncrement = 1;
inputIncrement = roundUp(lrint(ceil(outputIncrement / r)));
blockSize = inputIncrement * 4;
windowSize = inputIncrement * 4;
}
} else {
outputIncrement = int(ceil(inputIncrement * r));
@@ -303,8 +303,8 @@ RubberBandStretcher::Impl::calculateSizes()
inputIncrement /= 2;
outputIncrement = lrint(ceil(inputIncrement * r));
}
blockSize = std::max(blockSize, roundUp(outputIncrement * 6));
if (r > 5) while (blockSize < 8192) blockSize *= 2;
windowSize = std::max(windowSize, roundUp(outputIncrement * 6));
if (r > 5) while (windowSize < 8192) windowSize *= 2;
}
} else {
@@ -312,23 +312,23 @@ RubberBandStretcher::Impl::calculateSizes()
// use a variable increment
if (r < 1) {
inputIncrement = blockSize / 4;
inputIncrement = windowSize / 4;
while (inputIncrement >= 512) inputIncrement /= 2;
outputIncrement = int(floor(inputIncrement * r));
if (outputIncrement < 1) {
outputIncrement = 1;
inputIncrement = roundUp(lrint(ceil(outputIncrement / r)));
blockSize = inputIncrement * 4;
windowSize = inputIncrement * 4;
}
} else {
outputIncrement = blockSize / 6;
outputIncrement = windowSize / 6;
inputIncrement = int(outputIncrement / r);
while (outputIncrement > 1024 && inputIncrement > 1) {
outputIncrement /= 2;
inputIncrement = int(outputIncrement / r);
}
blockSize = std::max(blockSize, roundUp(outputIncrement * 6));
if (r > 5) while (blockSize < 8192) blockSize *= 2;
windowSize = std::max(windowSize, roundUp(outputIncrement * 6));
if (r > 5) while (windowSize < 8192) windowSize *= 2;
}
}
@@ -339,10 +339,10 @@ RubberBandStretcher::Impl::calculateSizes()
}
}
// blockSize can be almost anything, but it can't be greater than
// 4 * defaultBlockSize unless ratio is less than 1/1024.
// windowSize can be almost anything, but it can't be greater than
// 4 * defaultWindowSize unless ratio is less than 1/1024.
m_blockSize = blockSize;
m_windowSize = windowSize;
m_increment = inputIncrement;
// When squashing, the greatest theoretically possible output
@@ -350,29 +350,29 @@ RubberBandStretcher::Impl::calculateSizes()
// the sky's the limit in principle, but we expect
// StretchCalculator to restrict itself to using no more than
// twice the basic output increment (i.e. input increment times
// ratio) for any block.
// ratio) for any chunk.
if (m_debugLevel > 0) {
cerr << "configure: effective ratio = " << getEffectiveRatio() << endl;
cerr << "configure: block size = " << m_blockSize << ", increment = " << m_increment << " (approx output increment = " << int(lrint(m_increment * getEffectiveRatio())) << ")" << endl;
cerr << "configure: window size = " << m_windowSize << ", increment = " << m_increment << " (approx output increment = " << int(lrint(m_increment * getEffectiveRatio())) << ")" << endl;
}
static size_t maxBlockSize = 0;
static size_t maxWindowSize = 0;
if (m_blockSize > maxBlockSize) {
if (m_windowSize > maxWindowSize) {
//!!!
cerr << "configure: NOTE: max block size so far increased from "
<< maxBlockSize << " to " << m_blockSize << endl;
maxBlockSize = m_blockSize;
cerr << "configure: NOTE: max window size so far increased from "
<< maxWindowSize << " to " << m_windowSize << endl;
maxWindowSize = m_windowSize;
}
if (m_blockSize > m_maxProcessBlockSize) {
m_maxProcessBlockSize = m_blockSize;
if (m_windowSize > m_maxProcessSize) {
m_maxProcessSize = m_windowSize;
}
m_outbufSize = max
(size_t(ceil(m_maxProcessBlockSize / m_pitchScale)),
m_blockSize);
(size_t(ceil(m_maxProcessSize / m_pitchScale)),
m_windowSize);
if (m_realtime) {
// This headroom is so as to try to avoid reallocation when
@@ -391,7 +391,7 @@ RubberBandStretcher::Impl::calculateSizes()
//!!! for very long stretches (e.g. x5), this is necessary; for
//even longer ones (e.g. x10), even more of an outbuf is
//necessary. clearly something wrong in our calculations... or do
//we just need to ensure client calls setMaxProcessBlockSize?
//we just need to ensure client calls setMaxProcessSize?
if (!m_realtime && !m_threaded) {
m_outbufSize = m_outbufSize * 2;
}
@@ -400,16 +400,16 @@ RubberBandStretcher::Impl::calculateSizes()
void
RubberBandStretcher::Impl::configure()
{
size_t prevBlockSize = m_blockSize;
size_t prevWindowSize = m_windowSize;
size_t prevOutbufSize = m_outbufSize;
if (m_windows.empty()) {
prevBlockSize = 0;
prevWindowSize = 0;
prevOutbufSize = 0;
}
calculateSizes();
bool blockSizeChanged = (prevBlockSize != m_blockSize);
bool windowSizeChanged = (prevWindowSize != m_windowSize);
bool outbufSizeChanged = (prevOutbufSize != m_outbufSize);
// This function may be called at any time in non-RT mode, after a
@@ -420,30 +420,30 @@ RubberBandStretcher::Impl::configure()
// mode. After that reconfigure() does the work in a hopefully
// RT-safe way.
set<size_t> blockSizes;
set<size_t> windowSizes;
if (m_realtime) {
blockSizes.insert(m_baseBlockSize);
blockSizes.insert(m_baseBlockSize * 2);
blockSizes.insert(m_baseBlockSize * 4);
windowSizes.insert(m_baseWindowSize);
windowSizes.insert(m_baseWindowSize * 2);
windowSizes.insert(m_baseWindowSize * 4);
}
blockSizes.insert(m_blockSize);
windowSizes.insert(m_windowSize);
if (blockSizeChanged) {
if (windowSizeChanged) {
for (set<size_t>::const_iterator i = blockSizes.begin();
i != blockSizes.end(); ++i) {
for (set<size_t>::const_iterator i = windowSizes.begin();
i != windowSizes.end(); ++i) {
if (m_windows.find(*i) == m_windows.end()) {
m_windows[*i] = new Window<float>(HanningWindow, *i);
}
}
m_window = m_windows[m_blockSize];
m_window = m_windows[m_windowSize];
if (m_debugLevel > 0) {
cerr << "Window area: " << m_window->getArea() << "; synthesis window area: " << m_window->getArea() << endl;
}
}
if (blockSizeChanged || outbufSizeChanged) {
if (windowSizeChanged || outbufSizeChanged) {
for (size_t c = 0; c < m_channelData.size(); ++c) {
delete m_channelData[c];
@@ -452,13 +452,13 @@ RubberBandStretcher::Impl::configure()
for (size_t c = 0; c < m_channels; ++c) {
m_channelData.push_back
(new ChannelData(blockSizes, m_blockSize, m_outbufSize));
(new ChannelData(windowSizes, m_windowSize, m_outbufSize));
}
}
if (!m_realtime && blockSizeChanged) {
if (!m_realtime && windowSizeChanged) {
delete m_studyFFT;
m_studyFFT = new FFT(m_blockSize);
m_studyFFT = new FFT(m_windowSize);
m_studyFFT->initFloat();
}
@@ -480,7 +480,7 @@ RubberBandStretcher::Impl::configure()
delete m_lockAudioCurve;
m_lockAudioCurve = new PercussiveAudioCurve(m_stretcher->m_sampleRate,
m_blockSize);
m_windowSize);
// stretchAudioCurve unused in RT mode; lockAudioCurve and
// stretchCalculator however are used in all modes
@@ -491,10 +491,10 @@ RubberBandStretcher::Impl::configure()
//!!! probably adaptively-whitened spectral difference curve
//would be better
m_stretchAudioCurve = new HighFrequencyAudioCurve
(m_stretcher->m_sampleRate, m_blockSize);
(m_stretcher->m_sampleRate, m_windowSize);
} else {
m_stretchAudioCurve = new ConstantAudioCurve
(m_stretcher->m_sampleRate, m_blockSize);
(m_stretcher->m_sampleRate, m_windowSize);
}
}
@@ -506,11 +506,11 @@ RubberBandStretcher::Impl::configure()
m_stretchCalculator->setDebugLevel(m_debugLevel);
m_inputDuration = 0;
// Prepare the inbufs with half a block of emptiness. The centre
// point of the first processing block for the onset detector
// Prepare the inbufs with half a chunk of emptiness. The centre
// point of the first processing chunk for the onset detector
// should be the first sample of the audio, and we continue until
// we can no longer centre a block within the input audio. The
// number of onset detector blocks will be the number of audio
// we can no longer centre a chunk within the input audio. The
// number of onset detector chunks will be the number of audio
// samples input, divided by the input increment, plus one.
// In real-time mode, we don't do this prefill -- it's better to
@@ -520,7 +520,7 @@ RubberBandStretcher::Impl::configure()
if (!m_realtime) {
for (size_t c = 0; c < m_channels; ++c) {
m_channelData[c]->reset();
m_channelData[c]->inbuf->zero(m_blockSize/2);
m_channelData[c]->inbuf->zero(m_windowSize/2);
}
}
}
@@ -543,7 +543,7 @@ RubberBandStretcher::Impl::reconfigure()
configure();
}
size_t prevBlockSize = m_blockSize;
size_t prevWindowSize = m_windowSize;
size_t prevOutbufSize = m_outbufSize;
calculateSizes();
@@ -553,18 +553,18 @@ RubberBandStretcher::Impl::reconfigure()
// where not all of the things we need were correctly created when
// we first configured (for whatever reason). This is intended to
// be "effectively" realtime safe. The same goes for
// ChannelData::setOutbufSize and setBlockSize.
// ChannelData::setOutbufSize and setWindowSize.
if (m_blockSize != prevBlockSize) {
if (m_windowSize != prevWindowSize) {
if (m_windows.find(m_blockSize) == m_windows.end()) {
std::cerr << "WARNING: reconfigure(): window allocation (size " << m_blockSize << ") required in RT mode" << std::endl;
m_windows[m_blockSize] = new Window<float>(HanningWindow, m_blockSize);
if (m_windows.find(m_windowSize) == m_windows.end()) {
std::cerr << "WARNING: reconfigure(): window allocation (size " << m_windowSize << ") required in RT mode" << std::endl;
m_windows[m_windowSize] = new Window<float>(HanningWindow, m_windowSize);
}
m_window = m_windows[m_blockSize];
m_window = m_windows[m_windowSize];
for (size_t c = 0; c < m_channels; ++c) {
m_channelData[c]->setBlockSize(m_blockSize);
m_channelData[c]->setWindowSize(m_windowSize);
}
}
@@ -582,7 +582,7 @@ RubberBandStretcher::Impl::reconfigure()
std::cerr << "WARNING: reconfigure(): resampler construction required in RT mode" << std::endl;
m_channelData[c]->resampler =
new Resampler(Resampler::FastestTolerable, 1, m_blockSize);
new Resampler(Resampler::FastestTolerable, 1, m_windowSize);
m_channelData[c]->resamplebufSize =
lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale));
@@ -591,8 +591,8 @@ RubberBandStretcher::Impl::reconfigure()
}
}
if (m_blockSize != prevBlockSize) {
m_lockAudioCurve->setBlockSize(m_blockSize);
if (m_windowSize != prevWindowSize) {
m_lockAudioCurve->setWindowSize(m_windowSize);
}
}
@@ -600,7 +600,7 @@ size_t
RubberBandStretcher::Impl::getLatency() const
{
if (!m_realtime) return 0;
return int((m_blockSize/2) / m_pitchScale + 1);
return int((m_windowSize/2) / m_pitchScale + 1);
}
void
@@ -684,22 +684,19 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
consumed += writable;
}
while ((inbuf.getReadSpace() >= m_blockSize) ||
(final && (inbuf.getReadSpace() >= m_blockSize/2))) {
while ((inbuf.getReadSpace() >= m_windowSize) ||
(final && (inbuf.getReadSpace() >= m_windowSize/2))) {
//!!! inconsistency throughout -- we are using "blocksize",
// but "chunk" instead of "block"
// We know we have at least m_blockSize samples available
// in m_inbuf. We need to peek m_blockSize of them for
// We know we have at least m_windowSize samples available
// in m_inbuf. We need to peek m_windowSize of them for
// processing, and then skip m_increment to advance the
// read pointer.
// cd.accumulator is not otherwise used during studying,
// so we can use it as a temporary buffer here
size_t got = inbuf.peek(cd.accumulator, m_blockSize);
assert(final || got == m_blockSize);
size_t got = inbuf.peek(cd.accumulator, m_windowSize);
assert(final || got == m_windowSize);
m_window->cut(cd.accumulator);
@@ -718,8 +715,8 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
// cout << df << endl;
// We have augmented the input by m_blockSize/2 so
// that the first block is centred on the first audio
// We have augmented the input by m_windowSize/2 so
// that the first chunk is centred on the first audio
// sample. We want to ensure that m_inputDuration
// contains the exact input duration without including
// this extra bit. We just add up all the increments
@@ -736,8 +733,8 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
m_inputDuration += rs;
// cerr << "incr input duration by read space: " << rs << " -> " << m_inputDuration << endl;
if (m_inputDuration > m_blockSize/2) { // deducting the extra
m_inputDuration -= m_blockSize/2;
if (m_inputDuration > m_windowSize/2) { // deducting the extra
m_inputDuration -= m_windowSize/2;
}
}
@@ -780,7 +777,7 @@ RubberBandStretcher::Impl::getExactTimePoints() const
std::vector<StretchCalculator::Peak> peaks =
m_stretchCalculator->getLastCalculatedPeaks();
for (size_t i = 0; i < peaks.size(); ++i) {
points.push_back(peaks[i].frame);
points.push_back(peaks[i].chunk);
}
}
return points;
@@ -828,16 +825,16 @@ RubberBandStretcher::Impl::getSamplesRequired() const
// See notes in testInbufReadSpace below
if (rs < m_blockSize && !cd.draining) {
if (rs < m_windowSize && !cd.draining) {
if (cd.inputSize == -1) {
reqdHere = m_blockSize - rs;
reqdHere = m_windowSize - rs;
if (reqdHere > reqd) reqd = reqdHere;
continue;
}
if (rs == 0) {
reqdHere = m_blockSize;
reqdHere = m_windowSize;
if (reqdHere > reqd) reqd = reqdHere;
continue;
}
@@ -851,7 +848,7 @@ void
RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bool final)
{
if (m_mode == Finished) {
cerr << "RubberBandStretcher::Impl::process: Cannot process again after final block" << endl;
cerr << "RubberBandStretcher::Impl::process: Cannot process again after final chunk" << endl;
return;
}
@@ -866,7 +863,7 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo
for (size_t c = 0; c < m_channels; ++c) {
m_channelData[c]->reset();
m_channelData[c]->inbuf->zero(m_blockSize/2);
m_channelData[c]->inbuf->zero(m_windowSize/2);
}
if (m_threaded) {
@@ -945,7 +942,7 @@ RubberBandStretcher::Impl::process(const float *const *input, size_t samples, bo
/*
} else {
if (!allConsumed) {
cerr << "RubberBandStretcher::Impl::process: ERROR: Too much data provided to process() call -- either call setMaxProcessBlockSize() beforehand, or provide only getSamplesRequired() frames at a time" << endl;
cerr << "RubberBandStretcher::Impl::process: ERROR: Too much data provided to process() call -- either call setMaxProcessSize() beforehand, or provide only getSamplesRequired() frames at a time" << endl;
for (size_t c = 0; c < m_channels; ++c) {
cerr << "channel " << c << ": " << samples << " provided, " << consumed[c] << " consumed" << endl;
}

View File

@@ -52,7 +52,7 @@ public:
void setPhaseOption(Options);
void setExpectedInputDuration(size_t samples);
void setMaxProcessBlockSize(size_t samples);
void setMaxProcessSize(size_t samples);
size_t getSamplesRequired() const;
@@ -111,11 +111,11 @@ protected:
double m_timeRatio;
double m_pitchScale;
size_t m_blockSize;
size_t m_outbufSize;
size_t m_windowSize;
size_t m_increment;
size_t m_outbufSize;
size_t m_maxProcessBlockSize;
size_t m_maxProcessSize;
size_t m_expectedInputDuration;
bool m_threaded;
@@ -173,7 +173,7 @@ protected:
float m_freq1;
float m_freq2;
size_t m_baseBlockSize;
size_t m_baseWindowSize;
void writeOutput(RingBuffer<float> &to, float *from,
size_t qty, size_t &outCount, size_t theoreticalOut);

View File

@@ -83,8 +83,8 @@ RubberBandStretcher::Impl::processChunks(size_t c)
if (!testInbufReadSpace(c)) break;
if (!cd.draining) {
size_t got = cd.inbuf->peek(cd.fltbuf, m_blockSize);
assert(got == m_blockSize || cd.inputSize >= 0);
size_t got = cd.inbuf->peek(cd.fltbuf, m_windowSize);
assert(got == m_windowSize || cd.inputSize >= 0);
cd.inbuf->skip(m_increment);
analyseChunk(c);
}
@@ -94,9 +94,9 @@ RubberBandStretcher::Impl::processChunks(size_t c)
getIncrements(c, phaseIncrement, shiftIncrement, lock);
last = processChunkForChannel(c, phaseIncrement, shiftIncrement, lock);
cd.blockCount++;
cd.chunkCount++;
if (m_debugLevel > 2) {
cerr << "channel " << c << ": last = " << last << ", blockCount = " << cd.blockCount << endl;
cerr << "channel " << c << ": last = " << last << ", chunkCount = " << cd.chunkCount << endl;
}
}
@@ -114,8 +114,8 @@ RubberBandStretcher::Impl::processOneChunk()
if (!testInbufReadSpace(c)) return false;
ChannelData &cd = *m_channelData[c];
if (!cd.draining) {
size_t got = cd.inbuf->peek(cd.fltbuf, m_blockSize);
assert(got == m_blockSize || cd.inputSize >= 0);
size_t got = cd.inbuf->peek(cd.fltbuf, m_windowSize);
assert(got == m_windowSize || cd.inputSize >= 0);
cd.inbuf->skip(m_increment);
analyseChunk(c);
}
@@ -130,7 +130,7 @@ RubberBandStretcher::Impl::processOneChunk()
bool last = false;
for (size_t c = 0; c < m_channels; ++c) {
last = processChunkForChannel(c, phaseIncrement, shiftIncrement, lock);
m_channelData[c]->blockCount++;
m_channelData[c]->chunkCount++;
}
return last;
@@ -144,20 +144,20 @@ RubberBandStretcher::Impl::testInbufReadSpace(size_t c)
size_t rs = inbuf.getReadSpace();
if (rs < m_blockSize && !cd.draining) {
if (rs < m_windowSize && !cd.draining) {
if (cd.inputSize == -1) {
// Not all the input data has been written to the inbuf
// (that's why the input size is not yet set). We can't
// process, because we don't have a full block of data, so
// our process block would contain some empty padding in
// process, because we don't have a full chunk of data, so
// our process chunk would contain some empty padding in
// its input -- and that would give incorrect output, as
// we know there is more input to come.
if (!m_threaded) {
// cerr << "WARNING: RubberBandStretcher: read space < block size ("
// << inbuf.getReadSpace() << " < " << m_blockSize
// cerr << "WARNING: RubberBandStretcher: read space < chunk size ("
// << inbuf.getReadSpace() << " < " << m_windowSize
// << ") when not all input written, on processChunks for channel " << c << endl;
}
return false;
@@ -170,7 +170,7 @@ RubberBandStretcher::Impl::testInbufReadSpace(size_t c)
}
return false;
} else if (rs < m_blockSize/2) {
} else if (rs < m_windowSize/2) {
if (m_debugLevel > 1) {
cerr << "read space = " << rs << ", setting draining true" << endl;
@@ -208,12 +208,12 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
// to write from the existing accumulator into the output.
// We know we have enough samples available in m_inbuf --
// this is usually m_blockSize, but we know that if fewer
// this is usually m_windowSize, but we know that if fewer
// are available, it's OK to use zeroes for the rest
// (which the ring buffer will provide) because we've
// reached the true end of the data.
// We need to peek m_blockSize samples for processing, and
// We need to peek m_windowSize samples for processing, and
// then skip m_increment to advance the read pointer.
modifyChunk(c, phaseIncrement, lock);
@@ -285,7 +285,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
// basis that both channels are in sync. This is in contrast to
// getIncrements, which requires that all the increments have been
// calculated in advance but can then return increments
// corresponding to different blocks in different channels.
// corresponding to different chunks in different channels.
// Requires frequency domain representations of channel data in
// the mag and phase buffers in the channel.
@@ -300,9 +300,9 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
ChannelData &cd = *m_channelData[0];
size_t bc = cd.blockCount;
size_t bc = cd.chunkCount;
for (size_t c = 1; c < m_channels; ++c) {
if (m_channelData[c]->blockCount != bc) {
if (m_channelData[c]->chunkCount != bc) {
cerr << "ERROR: RubberBandStretcher::Impl::calculateIncrements: Channels are not in sync" << endl;
return;
}
@@ -318,12 +318,12 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
// phases to cancel each other, and broadband effects will still
// be apparent.
for (size_t i = 0; i <= m_blockSize/2; ++i) {
for (size_t i = 0; i <= m_windowSize/2; ++i) {
cd.fltbuf[i] = 0.0;
}
for (size_t c = 0; c < m_channels; ++c) {
for (size_t i = 0; i <= m_blockSize/2; ++i) {
for (size_t i = 0; i <= m_windowSize/2; ++i) {
cd.fltbuf[i] += m_channelData[c]->mag[i];
}
}
@@ -351,7 +351,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
// This implies we should use this increment for the shift
// increment, and make the following phase increment the same as
// it. This means in RT mode we'll be one block later with our
// it. This means in RT mode we'll be one chunk later with our
// phase lock than we would be in non-RT mode. The sensitivity of
// the broadband onset detector may mean that this isn't a problem
// -- test it and see.
@@ -399,9 +399,9 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
ChannelData &cd = *m_channelData[channel];
bool gotData = true;
if (cd.blockCount >= m_outputIncrements.size()) {
if (cd.chunkCount >= m_outputIncrements.size()) {
//!!! this is an error if in non-realtime mode
// cerr << "*** ERROR: block count " << cd.blockCount << " >= "
// cerr << "*** ERROR: chunk count " << cd.chunkCount << " >= "
// << m_outputIncrements.size() << endl;
if (m_outputIncrements.size() == 0) {
phaseIncrementRtn = m_increment;
@@ -409,16 +409,16 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
lock = false;
return false;
} else {
cd.blockCount = m_outputIncrements.size()-1;
cd.chunkCount = m_outputIncrements.size()-1;
gotData = false;
}
}
int phaseIncrement = m_outputIncrements[cd.blockCount];
int phaseIncrement = m_outputIncrements[cd.chunkCount];
int shiftIncrement = phaseIncrement;
if (cd.blockCount + 1 < m_outputIncrements.size()) {
shiftIncrement = m_outputIncrements[cd.blockCount + 1];
if (cd.chunkCount + 1 < m_outputIncrements.size()) {
shiftIncrement = m_outputIncrements[cd.chunkCount + 1];
}
if (phaseIncrement < 0) {
@@ -430,14 +430,14 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
shiftIncrement = -shiftIncrement;
}
if (shiftIncrement >= int(m_blockSize)) {
cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= blockSize " << m_blockSize << " at " << cd.blockCount << " (of " << m_outputIncrements.size() << ")" << endl;
shiftIncrement = m_blockSize;
if (shiftIncrement >= int(m_windowSize)) {
cerr << "*** ERROR: RubberBandStretcher::Impl::processChunks: shiftIncrement " << shiftIncrement << " >= windowSize " << m_windowSize << " at " << cd.chunkCount << " (of " << m_outputIncrements.size() << ")" << endl;
shiftIncrement = m_windowSize;
}
phaseIncrementRtn = phaseIncrement;
shiftIncrementRtn = shiftIncrement;
if (cd.blockCount == 0) lock = true; // don't mess with the first block
if (cd.chunkCount == 0) lock = true; // don't mess with the first chunk
return gotData;
}
@@ -448,13 +448,13 @@ RubberBandStretcher::Impl::analyseChunk(size_t channel)
ChannelData &cd = *m_channelData[channel];
// cd.fltbuf is known to contain m_blockSize samples
// cd.fltbuf is known to contain m_windowSize samples
m_window->cut(cd.fltbuf);
for (i = 0; i < m_blockSize/2; ++i) {
cd.dblbuf[i] = cd.fltbuf[i + m_blockSize/2];
cd.dblbuf[i + m_blockSize/2] = cd.fltbuf[i];
for (i = 0; i < m_windowSize/2; ++i) {
cd.dblbuf[i] = cd.fltbuf[i + m_windowSize/2];
cd.dblbuf[i + m_windowSize/2] = cd.fltbuf[i];
}
cd.fft->forwardPolar(cd.dblbuf, cd.mag, cd.phase);
@@ -473,7 +473,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement,
cerr << "lock: leaving phases unmodified" << endl;
}
size_t count = m_blockSize/2;
size_t count = m_windowSize/2;
size_t pfp = 0;
double rate = m_stretcher->m_sampleRate;
@@ -498,9 +498,9 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement,
freq0 = std::max(freq0, rf0);
}
size_t limit0 = lrint((freq0 * m_blockSize) / rate);
size_t limit1 = lrint((m_freq1 * m_blockSize) / rate);
size_t limit2 = lrint((m_freq2 * m_blockSize) / rate);
size_t limit0 = lrint((freq0 * m_windowSize) / rate);
size_t limit1 = lrint((m_freq1 * m_windowSize) / rate);
size_t limit2 = lrint((m_freq2 * m_windowSize) / rate);
size_t range = 0;
@@ -590,8 +590,8 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement,
if (!(m_options & OptionTransientsSmooth) &&
!(m_options & OptionTransientsCrisp)) {
// must be OptionTransientsMixed
size_t low = lrint((150 * m_blockSize) / rate);
size_t high = lrint((1000 * m_blockSize) / rate);
size_t low = lrint((150 * m_windowSize) / rate);
size_t high = lrint((1000 * m_windowSize) / rate);
if (lockThis) {
if (i > low && i < high) lockThis = false;
}
@@ -601,7 +601,7 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement,
if (i == 0 || p != pp) {
double omega = (2 * M_PI * m_increment * p) / m_blockSize;
double omega = (2 * M_PI * m_increment * p) / m_windowSize;
double expectedPhase = cd.prevPhase[p] + omega;
double phaseError = princarg(cd.phase[p] - expectedPhase);
double phaseIncrement = (omega + phaseError) / m_increment;
@@ -641,29 +641,29 @@ RubberBandStretcher::Impl::synthesiseChunk(size_t channel)
cd.fft->inversePolar(cd.mag, cd.phase, cd.dblbuf);
for (size_t i = 0; i < m_blockSize/2; ++i) {
cd.fltbuf[i] = cd.dblbuf[i + m_blockSize/2];
cd.fltbuf[i + m_blockSize/2] = cd.dblbuf[i];
for (size_t i = 0; i < m_windowSize/2; ++i) {
cd.fltbuf[i] = cd.dblbuf[i + m_windowSize/2];
cd.fltbuf[i + m_windowSize/2] = cd.dblbuf[i];
}
// our ffts produced unscaled results
for (size_t i = 0; i < m_blockSize; ++i) {
cd.fltbuf[i] = cd.fltbuf[i] / m_blockSize;
for (size_t i = 0; i < m_windowSize; ++i) {
cd.fltbuf[i] = cd.fltbuf[i] / m_windowSize;
}
m_window->cut(cd.fltbuf);
for (size_t i = 0; i < m_blockSize; ++i) {
for (size_t i = 0; i < m_windowSize; ++i) {
cd.accumulator[i] += cd.fltbuf[i];
}
cd.accumulatorFill = m_blockSize;
cd.accumulatorFill = m_windowSize;
//!!! not much cop, this bit
float area = m_window->getArea();
for (size_t i = 0; i < m_blockSize; ++i) {
for (size_t i = 0; i < m_windowSize; ++i) {
float val = m_window->getValue(i);
cd.windowAccumulator[i] += val * area;
}
@@ -718,11 +718,6 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
cd.resamplebuf = new float[cd.resamplebufSize];
}
#ifdef HAVE_IPP
if (m_threaded) {
m_resamplerMutex.lock();
}
#endif
size_t outframes = cd.resampler->resample(&cd.accumulator,
&cd.resamplebuf,
@@ -730,11 +725,6 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
1.0 / m_pitchScale,
last);
#ifdef HAVE_IPP
if (m_threaded) {
m_resamplerMutex.unlock();
}
#endif
writeOutput(*cd.outbuf, cd.resamplebuf,
outframes, cd.outCount, theoreticalOut);
@@ -744,19 +734,19 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
shiftIncrement, cd.outCount, theoreticalOut);
}
for (size_t i = 0; i < m_blockSize - shiftIncrement; ++i) {
for (size_t i = 0; i < m_windowSize - shiftIncrement; ++i) {
cd.accumulator[i] = cd.accumulator[i + shiftIncrement];
}
for (size_t i = m_blockSize - shiftIncrement; i < m_blockSize; ++i) {
for (size_t i = m_windowSize - shiftIncrement; i < m_windowSize; ++i) {
cd.accumulator[i] = 0.0f;
}
for (size_t i = 0; i < m_blockSize - shiftIncrement; ++i) {
for (size_t i = 0; i < m_windowSize - shiftIncrement; ++i) {
cd.windowAccumulator[i] = cd.windowAccumulator[i + shiftIncrement];
}
for (size_t i = m_blockSize - shiftIncrement; i < m_blockSize; ++i) {
for (size_t i = m_windowSize - shiftIncrement; i < m_windowSize; ++i) {
cd.windowAccumulator[i] = 0.0f;
}
@@ -777,13 +767,13 @@ void
RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_t qty, size_t &outCount, size_t theoreticalOut)
{
// In non-RT mode, we don't want to write the first startSkip
// samples, because the first block is centred on the start of the
// samples, because the first chunk is centred on the start of the
// output. In RT mode we didn't apply any pre-padding in
// configure(), so we don't want to remove any here.
size_t startSkip = 0;
if (!m_realtime) {
startSkip = lrintf((m_blockSize/2) / m_pitchScale);
startSkip = lrintf((m_windowSize/2) / m_pitchScale);
}
if (outCount > startSkip) {