# HG changeset patch # User Chris Cannam # Date 1710521962 0 # Fri Mar 15 16:59:22 2024 +0000 # Branch rblive # Node ID 7f8c02147225b523f205eeaeedaf1eb62d0849ad # Parent 8e573c29d898a663bf1bb4c8cd34d3f2853dd9fd Rework output resampler handling to deal with case where fewer samples are consumed than available diff --git a/src/common/BQResampler.cpp b/src/common/BQResampler.cpp --- a/src/common/BQResampler.cpp +++ b/src/common/BQResampler.cpp @@ -201,13 +201,6 @@ } } - if (i < incount_samples) { - std::cerr << "only used " << i << " of " << incount_samples - << " samples to generate output count " << o - << " (outspace_samples was " << outspace_samples << ")" - << std::endl; - } - int fbufsize = m_fade->buffer.size(); int fi = 0, fo = 0; while (fo < o && m_fade_count > 0) { diff --git a/src/finer/R3LiveShifter.cpp b/src/finer/R3LiveShifter.cpp --- a/src/finer/R3LiveShifter.cpp +++ b/src/finer/R3LiveShifter.cpp @@ -344,7 +344,7 @@ int requiredInOutbuf = 1 + int(ceil(incount / outRatio)); generate(requiredInOutbuf); - int got = readOut(output, incount, 0); + int got = readOut(output, incount); if (got < incount) { m_log.log(0, "R3LiveShifter::shift: ERROR: internal error: insufficient data at output (wanted, got)", incount, got); @@ -597,7 +597,7 @@ } int -R3LiveShifter::readOut(float *const *output, int outcount, int origin) +R3LiveShifter::readOut(float *const *output, int outcount) { double outRatio = 1.0; @@ -613,79 +613,86 @@ m_log.log(2, "R3LiveShifter::readOut: outcount and ratio", outcount, outRatio); - int fromOutbuf = int(floor(outcount / outRatio)); + int resampledCount = 0; + bool fillingTail = true; - m_log.log(2, "R3LiveShifter::readOut: origin and fromOutbuf", origin, fromOutbuf); - - if (fromOutbuf == 0) { - fromOutbuf = 1; - } + while (resampledCount < outcount) { + + int fromOutbuf; - int got = fromOutbuf; + if (fillingTail) { + fromOutbuf = 1; + } else { + fromOutbuf = int(floor(outcount / outRatio)); + if (fromOutbuf == 0) { + fromOutbuf = 1; + } + } + + m_log.log(2, "R3LiveShifter::readOut: fromOutbuf", fromOutbuf); + + int got = fromOutbuf; - for (int c = 0; c < m_parameters.channels; ++c) { - auto &cd = m_channelData.at(c); - int gotHere = cd->outbuf->read(cd->resampled.data(), got); - if (gotHere < got) { - if (c > 0) { - m_log.log(0, "R3LiveShifter::readOut: WARNING: channel imbalance detected"); + for (int c = 0; c < m_parameters.channels; ++c) { + auto &cd = m_channelData.at(c); + int gotHere = cd->outbuf->read(cd->resampled.data(), got); + if (gotHere < got) { + if (c > 0) { + m_log.log(0, "R3LiveShifter::readOut: WARNING: channel imbalance detected"); + } } got = std::min(got, std::max(gotHere, 0)); } - } - m_log.log(2, "R3LiveShifter::readOut: requested and got from outbufs", fromOutbuf, got); - m_log.log(2, "R3LiveShifter::readOut: leaving behind", m_channelData.at(0)->outbuf->getReadSpace()); - - int resampledCount = 0; - - if (got > 0) { + m_log.log(2, "R3LiveShifter::readOut: requested and got from outbufs", fromOutbuf, got); + m_log.log(2, "R3LiveShifter::readOut: leaving behind", m_channelData.at(0)->outbuf->getReadSpace()); for (int c = 0; c < m_parameters.channels; ++c) { auto &cd = m_channelData.at(c); m_channelAssembly.resampled[c] = cd->resampled.data(); - m_channelAssembly.mixdown[c] = output[c] + origin; + m_channelAssembly.mixdown[c] = output[c] + resampledCount; } - resampledCount = m_outResampler->resample + auto resampledHere = m_outResampler->resample (m_channelAssembly.mixdown.data(), - outcount, + outcount - resampledCount, m_channelAssembly.resampled.data(), got, outRatio, false); + + m_log.log(2, "R3LiveShifter::readOut: resampledHere", resampledHere); + + if (got == 0 && resampledHere == 0) { + m_log.log(2, "R3LiveShifter::readOut: made no progress, finishing"); + break; + } + + resampledCount += resampledHere; + + fillingTail = true; + } - if (useMidSide()) { - for (int i = 0; i < resampledCount; ++i) { - float m = output[0][origin + i]; - float s = output[1][origin + i]; - float l = m + s; - float r = m - s; - output[0][origin + i] = l; - output[1][origin + i] = r; - } + if (useMidSide()) { + for (int i = 0; i < resampledCount; ++i) { + float m = output[0][i]; + float s = output[1][i]; + float l = m + s; + float r = m - s; + output[0][i] = l; + output[1][i] = r; } } m_log.log(2, "R3LiveShifter::readOut: resampled to", resampledCount); - if (resampledCount < outcount && - m_channelData.at(0)->outbuf->getReadSpace() > 0) { - int remaining = outcount - resampledCount; - m_log.log(2, "R3LiveShifter::readOut: recursing to try to get the remaining", - remaining); - resampledCount += readOut(output, remaining, origin + resampledCount); - } - if (resampledCount < outcount) { if (m_firstProcess) { m_log.log(2, "R3LiveShifter::readOut: resampler left us short on first process, pre-padding output: expected and obtained", outcount, resampledCount); int prepad = outcount - resampledCount; for (int c = 0; c < m_parameters.channels; ++c) { - v_move(output[c] + origin + prepad, - output[c] + origin, - resampledCount); - v_zero(output[c] + origin, prepad); + v_move(output[c] + prepad, output[c], resampledCount); + v_zero(output[c], prepad); } resampledCount = outcount; } else { diff --git a/src/finer/R3LiveShifter.h b/src/finer/R3LiveShifter.h --- a/src/finer/R3LiveShifter.h +++ b/src/finer/R3LiveShifter.h @@ -328,7 +328,7 @@ void readIn(const float *const *input); void generate(int required); - int readOut(float *const *output, int outcount, int origin); + int readOut(float *const *output, int outcount); void createResamplers(); void analyseChannel(int channel, int inhop, int prevInhop, int prevOuthop); diff --git a/src/test/TestLiveShifter.cpp b/src/test/TestLiveShifter.cpp --- a/src/test/TestLiveShifter.cpp +++ b/src/test/TestLiveShifter.cpp @@ -52,7 +52,7 @@ RubberBandLiveShifter shifter(rate, 1, options); - shifter.setPitchScale(2.66968); +// shifter.setPitchScale(2.66968); int blocksize = shifter.getBlockSize(); BOOST_TEST(blocksize == 512); @@ -120,7 +120,7 @@ RubberBandLiveShifter::OptionPitchModeA; int n = 100000; - check_sinusoid_unchanged(n, 44100, 440.f, options, true); + check_sinusoid_unchanged(n, 44100, 440.f, options, false); check_sinusoid_unchanged(n, 48000, 260.f, options, false); }