From 53ccb1d60edd55ca7ec01b11d77e59fc5aed5ea7 Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Fri, 19 Apr 2024 15:12:25 +0100 Subject: [PATCH] Measure rather than guess resampler delay --- src/finer/R3LiveShifter.cpp | 40 ++++++++++++++++++++++++++++--------- src/finer/R3LiveShifter.h | 2 ++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/finer/R3LiveShifter.cpp b/src/finer/R3LiveShifter.cpp index 20c73e7..ce119a5 100644 --- a/src/finer/R3LiveShifter.cpp +++ b/src/finer/R3LiveShifter.cpp @@ -42,6 +42,7 @@ R3LiveShifter::R3LiveShifter(Parameters parameters, Log log) : m_log), m_guideConfiguration(m_guide.getConfiguration()), m_channelAssembly(m_parameters.channels), + m_resamplerDelay(32), m_useReadahead(false), m_prevInhop(m_limits.maxInhopWithReadahead / 2), m_prevOuthop(m_prevInhop), @@ -222,6 +223,30 @@ R3LiveShifter::createResamplers() m_outResampler = std::unique_ptr (new Resampler(resamplerParameters, m_parameters.channels)); + + measureResamplerDelay(); +} + +void +R3LiveShifter::measureResamplerDelay() +{ + // Delay in the sense that the resampler at first returns fewer + // samples than requested, not that the samples are delayed within + // the returned buffer relative to their positions at input. We + // actually add the delay ourselves in the first block because we + // need a fixed block size and the resampler doesn't return one. + + int bs = getBlockSize(); + std::vector inbuf(bs * m_parameters.channels, 0.f); + auto outbuf = inbuf; + + int outcount = m_inResampler->resampleInterleaved + (outbuf.data(), bs, inbuf.data(), bs, 1.0, false); + + m_inResampler->reset(); + + m_resamplerDelay = bs - outcount; + m_log.log(1, "R3LiveShifter::measureResamplerDelay: measured delay and outcount ", m_resamplerDelay, outcount); } double @@ -245,12 +270,7 @@ R3LiveShifter::getPreferredStartPad() const size_t R3LiveShifter::getStartDelay() const { - //!!! need a principled way - measure it in ctor perhaps - int resamplerDelay = 32; -#ifdef HAVE_LIBSAMPLERATE - resamplerDelay = 47; -#endif - int fixed = getWindowSourceSize() / 2 + resamplerDelay * 2; + int fixed = getWindowSourceSize() / 2 + m_resamplerDelay * 2 - 1; int variable = getWindowSourceSize() / 2; if (m_contractThenExpand) { if (m_pitchScale < 1.0) { @@ -292,6 +312,8 @@ R3LiveShifter::reset() for (auto &cd : m_channelData) { cd->reset(); } + + measureResamplerDelay(); } size_t @@ -414,7 +436,7 @@ R3LiveShifter::readIn(const float *const *input) m_log.log(2, "R3LiveShifter::readIn: ratio", inRatio); int resampleBufSize = int(m_channelData.at(0)->resampled.size()); - + int resampleOutput = m_inResampler->resample (m_channelAssembly.resampled.data(), resampleBufSize, @@ -422,7 +444,7 @@ R3LiveShifter::readIn(const float *const *input) incount, inRatio, false); - + m_log.log(2, "R3LiveShifter::readIn: writing to inbuf from resampled data, former read space and samples being added", m_channelData[0]->inbuf->getReadSpace(), resampleOutput); if (m_firstProcess) { @@ -652,7 +674,7 @@ R3LiveShifter::readOut(float *const *output, int outcount) m_channelAssembly.resampled[c] = cd->resampled.data(); m_channelAssembly.mixdown[c] = output[c] + resampledCount; } - + auto resampledHere = m_outResampler->resample (m_channelAssembly.mixdown.data(), outcount - resampledCount, diff --git a/src/finer/R3LiveShifter.h b/src/finer/R3LiveShifter.h index a9224ef..d2fed52 100644 --- a/src/finer/R3LiveShifter.h +++ b/src/finer/R3LiveShifter.h @@ -317,6 +317,7 @@ protected: ChannelAssembly m_channelAssembly; std::unique_ptr m_inResampler; std::unique_ptr m_outResampler; + int m_resamplerDelay; bool m_useReadahead; int m_prevInhop; int m_prevOuthop; @@ -331,6 +332,7 @@ protected: int readOut(float *const *output, int outcount); void createResamplers(); + void measureResamplerDelay(); void analyseChannel(int channel, int inhop, int prevInhop, int prevOuthop); void analyseFormant(int channel); void adjustFormant(int channel);