* Fix outbuf size issues, and other misc troubles

This commit is contained in:
Chris Cannam
2007-11-21 21:48:16 +00:00
parent d2fe49c20c
commit fe9dc561ef
4 changed files with 54 additions and 41 deletions

View File

@@ -153,7 +153,7 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
}
if (m_debugLevel > 0) {
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 << "total input increment = " << totalInput << " (= " << totalInput / m_increment << " chunks), output = " << totalOutput << ", ratio = " << double(totalOutput)/double(totalInput) << ", ideal output " << size_t(ceil(totalInput * ratio)) << std::endl;
std::cerr << "(region total = " << regionTotalChunks << ")" << std::endl;
}

View File

@@ -210,10 +210,6 @@ RubberBandStretcher::Impl::ChannelData::setOutbufSize(size_t outbufSize)
//!!! at this point we need a lock in case a different client
//thread is calling process()
//!!! this doesn't do what we want -- we want a locking resize
//that preserves the existing data
// outbuf->resize(outbufSize);
RingBuffer<float> *newbuf = outbuf->resized(outbufSize);
delete outbuf;
outbuf = newbuf;

View File

@@ -380,9 +380,11 @@ RubberBandStretcher::Impl::calculateSizes()
m_maxProcessSize = m_windowSize;
}
m_outbufSize = max
(size_t(ceil(m_maxProcessSize / m_pitchScale)),
m_windowSize);
m_outbufSize =
size_t
(ceil(max
(m_maxProcessSize / m_pitchScale,
m_windowSize * 2 * (m_timeRatio > 1.f ? m_timeRatio : 1.f))));
if (m_realtime) {
// This headroom is so as to try to avoid reallocation when
@@ -398,13 +400,17 @@ RubberBandStretcher::Impl::calculateSizes()
}
}
if (m_debugLevel > 0) {
cerr << "configure: outbuf size = " << m_outbufSize << endl;
}
//!!! 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 setMaxProcessSize?
if (!m_realtime && !m_threaded) {
m_outbufSize = m_outbufSize * 5;
}
// if (!m_realtime && !m_threaded) {
// m_outbufSize = m_outbufSize * 10;
// }
}
void
@@ -481,10 +487,14 @@ RubberBandStretcher::Impl::configure()
m_channelData[c]->resampler =
new Resampler(Resampler::FastestTolerable, 1, 4096 * 16);
m_channelData[c]->resamplebufSize =
// rbs is the amount of buffer space we think we'll need
// for resampling; but allocate a sensible amount in case
// the pitch scale changes during use
size_t rbs =
lrintf(ceil((m_increment * m_timeRatio * 2) / m_pitchScale));
m_channelData[c]->resamplebuf =
new float[m_channelData[c]->resamplebufSize];
if (rbs < m_increment * 16) rbs = m_increment * 16;
m_channelData[c]->resamplebufSize = rbs;
m_channelData[c]->resamplebuf = new float[rbs];
}
}

View File

@@ -257,7 +257,7 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
if (cd.outbuf->getWriteSpace() < required) {
if (m_debugLevel > 0) {
cerr << "buffer overrun on output for channel " << c << endl;
cerr << "Buffer overrun on output for channel " << c << endl;
}
//!!! The only correct thing we can do here is resize the
@@ -400,9 +400,9 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
bool gotData = true;
if (cd.chunkCount >= m_outputIncrements.size()) {
//!!! this is an error if in non-realtime mode
// cerr << "*** ERROR: chunk count " << cd.chunkCount << " >= "
// << m_outputIncrements.size() << endl;
// cerr << "WARNING: RubberBandStretcher::Impl::getIncrements:"
// << " chunk count " << cd.chunkCount << " >= "
// << m_outputIncrements.size() << endl;
if (m_outputIncrements.size() == 0) {
phaseIncrementRtn = m_increment;
shiftIncrementRtn = m_increment;
@@ -659,14 +659,11 @@ RubberBandStretcher::Impl::synthesiseChunk(size_t channel)
cd.accumulatorFill = m_windowSize;
//!!! not much cop, this bit
float area = m_window->getArea() * 1.5;
// float area = 1.f;
float fixed = m_window->getArea() * 1.5;
for (size_t i = 0; i < m_windowSize; ++i) {
float val = m_window->getValue(i);
cd.windowAccumulator[i] += val * area;
cd.windowAccumulator[i] += val * fixed;
}
}
@@ -679,17 +676,9 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
cerr << "writeChunk(" << channel << ", " << shiftIncrement << ", " << last << ")" << endl;
}
static float windowaccmax = 0; //!!!
for (int i = 0; i < shiftIncrement; ++i) {
if (cd.windowAccumulator[i] > 0.f) {
cd.accumulator[i] /= cd.windowAccumulator[i];
if (fabsf(cd.windowAccumulator[i]) > windowaccmax) {
// cerr << "window accumulator max " << windowaccmax
// << " -> " << fabsf(cd.windowAccumulator[i]) << endl;
//!!!
windowaccmax = fabsf(cd.windowAccumulator[i]);
}
}
}
@@ -697,13 +686,10 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
// were running in RT mode)
size_t theoreticalOut = 0;
if (cd.inputSize >= 0) {
// cerr << "cd.inputSize = " << cd.inputSize << endl;
theoreticalOut = lrint(cd.inputSize * m_timeRatio);
// cerr << "theoreticalOut = " << theoreticalOut << endl;
}
if (m_pitchScale != 1.0 && cd.resampler) {
// cerr << "resampler: input " << shiftIncrement << ", output max " << int(shiftIncrement / m_pitchScale) + 1 << endl;
size_t reqSize = int(ceil(shiftIncrement / m_pitchScale));
if (reqSize > cd.resamplebufSize) {
@@ -711,8 +697,8 @@ RubberBandStretcher::Impl::writeChunk(size_t channel, size_t shiftIncrement, boo
// supposed to be initialised with enough space in the
// first place. But we retain this check in case the
// pitch scale has changed since then, or the stretch
// calculator has goneb mad, or something.
cerr << "resampler: resizing buffer from "
// calculator has gone mad, or something.
cerr << "WARNING: RubberBandStretcher::Impl::writeChunk: resizing resampler buffer from "
<< cd.resamplebufSize << " to " << reqSize << endl;
cd.resamplebufSize = reqSize;
if (cd.resamplebuf) delete[] cd.resamplebuf;
@@ -778,9 +764,15 @@ RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_
}
if (outCount > startSkip) {
// this is the normal case
if (theoreticalOut > 0) {
if (m_debugLevel > 1) {
cerr << "theoreticalOut = " << theoreticalOut << ", outCount = " << outCount << ", startSkip = " << startSkip << ", qty = " << qty << endl;
cerr << "theoreticalOut = " << theoreticalOut
<< ", outCount = " << outCount
<< ", startSkip = " << startSkip
<< ", qty = " << qty << endl;
}
if (outCount - startSkip <= theoreticalOut &&
outCount - startSkip + qty > theoreticalOut) {
@@ -794,14 +786,26 @@ RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_
if (m_debugLevel > 2) {
cerr << "writing " << qty << endl;
}
to.write(from, qty);
outCount += qty;
size_t written = to.write(from, qty);
if (written < qty) {
cerr << "WARNING: RubberBandStretcher::Impl::writeOutput: "
<< "Buffer overrun on output: wrote " << written
<< " of " << qty << " samples" << endl;
}
outCount += written;
return;
}
// the rest of this is only used during the first startSkip samples
if (outCount + qty <= startSkip) {
if (m_debugLevel > 1) {
cerr << "qty = " << qty << ", startSkip = " << startSkip << ", outCount = " << outCount << ", discarding" << endl;
cerr << "qty = " << qty << ", startSkip = "
<< startSkip << ", outCount = " << outCount
<< ", discarding" << endl;
}
outCount += qty;
return;
@@ -809,7 +813,10 @@ RubberBandStretcher::Impl::writeOutput(RingBuffer<float> &to, float *from, size_
size_t off = startSkip - outCount;
if (m_debugLevel > 1) {
cerr << "qty = " << qty << ", startSkip = " << startSkip << ", outCount = " << outCount << ", writing " << qty - off << " from start offset " << off << endl;
cerr << "qty = " << qty << ", startSkip = "
<< startSkip << ", outCount = " << outCount
<< ", writing " << qty - off
<< " from start offset " << off << endl;
}
to.write(from + off, qty - off);
outCount += qty;