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

This commit is contained in:
Chris Cannam
2022-06-13 17:16:03 +01:00
parent ac4072937e
commit 9dbf53026a
4 changed files with 33 additions and 13 deletions

View File

@@ -142,9 +142,15 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
size_t nchunks = regionEndChunk - regionStartChunk; 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) { if (nchunks == 0) {
//!!! if (m_debugLevel > 1) {
break; std::cerr << "note: nchunks == 0" << std::endl;
}
continue;
} }
double per = double(regionDuration) / double(nchunks); double per = double(regionDuration) / double(nchunks);
@@ -335,7 +341,8 @@ StretchCalculator::calculateSingle(double timeRatio,
float df, float df,
size_t inIncrement, size_t inIncrement,
size_t analysisWindowSize, size_t analysisWindowSize,
size_t synthesisWindowSize) size_t synthesisWindowSize,
bool alignFrameStarts)
{ {
double ratio = timeRatio / effectivePitchRatio; double ratio = timeRatio / effectivePitchRatio;
@@ -414,10 +421,17 @@ StretchCalculator::calculateSingle(double timeRatio,
std::cerr << "The next sample out is input sample " << m_inFrameCounter << std::endl; std::cerr << "The next sample out is input sample " << m_inFrameCounter << std::endl;
} }
int64_t intended = expectedOutFrame int64_t intended, projected;
(m_inFrameCounter + analysisWindowSize/4, timeRatio); if (alignFrameStarts) { // R3
int64_t projected = int64_t intended = expectedOutFrame(m_inFrameCounter, timeRatio);
(round(m_outFrameCounter + (synthesisWindowSize/4 * effectivePitchRatio))); 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; int64_t divergence = projected - intended;

View File

@@ -71,7 +71,8 @@ public:
float curveValue, float curveValue,
size_t increment, size_t increment,
size_t analysisWindowSize, size_t analysisWindowSize,
size_t synthesisWindowSize); size_t synthesisWindowSize,
bool alignFrameStarts);
void setUseHardPeaks(bool use) { m_useHardPeaks = use; } void setUseHardPeaks(bool use) { m_useHardPeaks = use; }

View File

@@ -626,7 +626,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
int incr = m_stretchCalculator->calculateSingle int incr = m_stretchCalculator->calculateSingle
(m_timeRatio, effectivePitchRatio, df, m_increment, (m_timeRatio, effectivePitchRatio, df, m_increment,
m_aWindowSize, m_sWindowSize); m_aWindowSize, m_sWindowSize, false);
if (m_lastProcessPhaseResetDf.getWriteSpace() > 0) { if (m_lastProcessPhaseResetDf.getWriteSpace() > 0) {
m_lastProcessPhaseResetDf.write(&df, 1); m_lastProcessPhaseResetDf.write(&df, 1);

View File

@@ -128,12 +128,15 @@ R3StretcherImpl::R3StretcherImpl(Parameters parameters,
// changes. // changes.
if (!isRealTime()) { if (!isRealTime()) {
m_parameters.logger("Offline mode: pre-padding");
int pad = m_guideConfiguration.longestFftSize / 2; int pad = m_guideConfiguration.longestFftSize / 2;
for (int c = 0; c < m_parameters.channels; ++c) { for (int c = 0; c < m_parameters.channels; ++c) {
m_channelData[c]->inbuf->zero(pad); m_channelData[c]->inbuf->zero(pad);
} }
// By the time we skip this later we will have resampled // By the time we skip this later we will have resampled
m_startSkip = int(round(pad / m_pitchScale)); 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 longest = m_guideConfiguration.longestFftSize;
int channels = m_parameters.channels; int channels = m_parameters.channels;
//!!! todo: wire debug level & logger throughout
// m_calculator->setDebugLevel(3); // m_calculator->setDebugLevel(3);
int inhop = m_inhop; int inhop = m_inhop;
@@ -466,7 +470,8 @@ R3StretcherImpl::consume()
1.f, 1.f,
inhop, inhop,
longest, longest,
longest); longest,
true);
// Now inhop is the distance by which the input stream will be // Now inhop is the distance by which the input stream will be
// advanced after our current frame has been read, and outhop is // advanced after our current frame has been read, and outhop is