From fe9dc561ef9a5c3e261f06c3b477ef7976514dc4 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Wed, 21 Nov 2007 21:48:16 +0000 Subject: [PATCH] * Fix outbuf size issues, and other misc troubles --- src/StretchCalculator.cpp | 2 +- src/StretcherChannelData.cpp | 4 --- src/StretcherImpl.cpp | 28 +++++++++++------ src/StretcherProcess.cpp | 61 ++++++++++++++++++++---------------- 4 files changed, 54 insertions(+), 41 deletions(-) diff --git a/src/StretchCalculator.cpp b/src/StretchCalculator.cpp index 1c378f9..77d1c50 100644 --- a/src/StretchCalculator.cpp +++ b/src/StretchCalculator.cpp @@ -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; } diff --git a/src/StretcherChannelData.cpp b/src/StretcherChannelData.cpp index d0b12e7..e431a80 100644 --- a/src/StretcherChannelData.cpp +++ b/src/StretcherChannelData.cpp @@ -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 *newbuf = outbuf->resized(outbufSize); delete outbuf; outbuf = newbuf; diff --git a/src/StretcherImpl.cpp b/src/StretcherImpl.cpp index c7a4074..f3c5d3e 100644 --- a/src/StretcherImpl.cpp +++ b/src/StretcherImpl.cpp @@ -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]; } } diff --git a/src/StretcherProcess.cpp b/src/StretcherProcess.cpp index 75b4dfa..85b1421 100644 --- a/src/StretcherProcess.cpp +++ b/src/StretcherProcess.cpp @@ -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 &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 &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 &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;