From 9dbf53026a10738888c0c7fd2d2e5c9f323ac650 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Mon, 13 Jun 2022 17:16:03 +0100 Subject: [PATCH] Fix failure to calculate offline stretch correctly when a zero-chunk region is found; provide alternate projection calculation method for R3 without stop-the-world phase resets --- src/common/StretchCalculator.cpp | 30 ++++++++++++++++++++++-------- src/common/StretchCalculator.h | 3 ++- src/faster/StretcherProcess.cpp | 2 +- src/finer/R3StretcherImpl.cpp | 11 ++++++++--- 4 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/common/StretchCalculator.cpp b/src/common/StretchCalculator.cpp index 2ad0eea..1f3948e 100644 --- a/src/common/StretchCalculator.cpp +++ b/src/common/StretchCalculator.cpp @@ -141,10 +141,16 @@ StretchCalculator::calculate(double ratio, size_t inputDuration, size_t regionDuration = regionEnd - regionStart; size_t nchunks = regionEndChunk - regionStartChunk; + + if (m_debugLevel > 1) { + std::cerr << "region from " << regionStartChunk << " to " << regionEndChunk << " (samples " << regionStart << " to " << regionEnd << ")" << std::endl; + } if (nchunks == 0) { - //!!! - break; + if (m_debugLevel > 1) { + std::cerr << "note: nchunks == 0" << std::endl; + } + continue; } double per = double(regionDuration) / double(nchunks); @@ -335,7 +341,8 @@ StretchCalculator::calculateSingle(double timeRatio, float df, size_t inIncrement, size_t analysisWindowSize, - size_t synthesisWindowSize) + size_t synthesisWindowSize, + bool alignFrameStarts) { double ratio = timeRatio / effectivePitchRatio; @@ -413,11 +420,18 @@ StretchCalculator::calculateSingle(double timeRatio, std::cerr << "The next sample out is input sample " << m_inFrameCounter << std::endl; } - - int64_t intended = expectedOutFrame - (m_inFrameCounter + analysisWindowSize/4, timeRatio); - int64_t projected = int64_t - (round(m_outFrameCounter + (synthesisWindowSize/4 * effectivePitchRatio))); + + int64_t intended, projected; + if (alignFrameStarts) { // R3 + intended = expectedOutFrame(m_inFrameCounter, timeRatio); + projected = m_outFrameCounter; + } else { // R2 + intended = expectedOutFrame + (m_inFrameCounter + analysisWindowSize/4, timeRatio); + projected = + int64_t(round(m_outFrameCounter + + (synthesisWindowSize/4 * effectivePitchRatio))); + } int64_t divergence = projected - intended; diff --git a/src/common/StretchCalculator.h b/src/common/StretchCalculator.h index f7a8112..e1f91fc 100644 --- a/src/common/StretchCalculator.h +++ b/src/common/StretchCalculator.h @@ -71,7 +71,8 @@ public: float curveValue, size_t increment, size_t analysisWindowSize, - size_t synthesisWindowSize); + size_t synthesisWindowSize, + bool alignFrameStarts); void setUseHardPeaks(bool use) { m_useHardPeaks = use; } diff --git a/src/faster/StretcherProcess.cpp b/src/faster/StretcherProcess.cpp index 1a4e823..c870bef 100644 --- a/src/faster/StretcherProcess.cpp +++ b/src/faster/StretcherProcess.cpp @@ -626,7 +626,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, int incr = m_stretchCalculator->calculateSingle (m_timeRatio, effectivePitchRatio, df, m_increment, - m_aWindowSize, m_sWindowSize); + m_aWindowSize, m_sWindowSize, false); if (m_lastProcessPhaseResetDf.getWriteSpace() > 0) { m_lastProcessPhaseResetDf.write(&df, 1); diff --git a/src/finer/R3StretcherImpl.cpp b/src/finer/R3StretcherImpl.cpp index 50ec3f2..36b8509 100644 --- a/src/finer/R3StretcherImpl.cpp +++ b/src/finer/R3StretcherImpl.cpp @@ -128,12 +128,15 @@ R3StretcherImpl::R3StretcherImpl(Parameters parameters, // changes. if (!isRealTime()) { + m_parameters.logger("Offline mode: pre-padding"); int pad = m_guideConfiguration.longestFftSize / 2; for (int c = 0; c < m_parameters.channels; ++c) { m_channelData[c]->inbuf->zero(pad); } // By the time we skip this later we will have resampled m_startSkip = int(round(pad / m_pitchScale)); + } else { + m_parameters.logger("RT mode: no internal pre-pad"); } } @@ -452,6 +455,7 @@ R3StretcherImpl::consume() int longest = m_guideConfiguration.longestFftSize; int channels = m_parameters.channels; + //!!! todo: wire debug level & logger throughout // m_calculator->setDebugLevel(3); int inhop = m_inhop; @@ -466,8 +470,9 @@ R3StretcherImpl::consume() 1.f, inhop, longest, - longest); - + longest, + true); + // Now inhop is the distance by which the input stream will be // advanced after our current frame has been read, and outhop is // the distance by which the output will be advanced after it has @@ -489,7 +494,7 @@ R3StretcherImpl::consume() std::cout << "Note: outhop has changed from " << m_prevOuthop << " to " << outhop << std::endl; } -*/ +*/ while (m_channelData.at(0)->outbuf->getWriteSpace() >= outhop) { // NB our ChannelData, ScaleData, and ChannelScaleData maps