# HG changeset patch # User Chris Cannam # Date 1715356362 -3600 # Fri May 10 16:52:42 2024 +0100 # Branch rblive # Node ID 7f48814edf3a0c15f3ea2dcdccf89e264aebc6a1 # Parent e90d8a37403bae964a6c87092419a90167ba4e2a Delay calculations diff --git a/src/finer/R3LiveShifter.cpp b/src/finer/R3LiveShifter.cpp --- a/src/finer/R3LiveShifter.cpp +++ b/src/finer/R3LiveShifter.cpp @@ -41,7 +41,7 @@ m_log), m_guideConfiguration(m_guide.getConfiguration()), m_channelAssembly(m_parameters.channels), - m_resamplerDelay(32), + m_initialResamplerDelays(32, 32), m_useReadahead(false), m_prevInhop(m_limits.maxInhopWithReadahead / 2), m_prevOuthop(m_prevInhop), @@ -240,19 +240,18 @@ std::vector inbuf(bs * m_parameters.channels, 0.f); auto outbuf = inbuf; - double inRatio = 1.0; - if (m_pitchScale > 1.0) { - inRatio = 1.0 / m_pitchScale; - } - - int outcount = m_inResampler->resampleInterleaved - (outbuf.data(), bs, inbuf.data(), bs, inRatio, false); - + int incount = m_inResampler->resampleInterleaved + (outbuf.data(), bs, inbuf.data(), bs, getInRatio(), false); m_inResampler->reset(); - m_resamplerDelay = bs - outcount; + int outcount = m_outResampler->resampleInterleaved + (outbuf.data(), bs, inbuf.data(), bs, getOutRatio(), false); + m_outResampler->reset(); + + m_initialResamplerDelays = { bs - incount, bs - outcount }; - m_log.log(1, "R3LiveShifter::measureResamplerDelay: measured delay and outcount ", m_resamplerDelay, outcount); + m_log.log(1, "R3LiveShifter::measureResamplerDelay: inRatio, outRatio ", getInRatio(), getOutRatio()); + m_log.log(1, "R3LiveShifter::measureResamplerDelay: measured delays ", m_initialResamplerDelays.first, m_initialResamplerDelays.second); } double @@ -276,13 +275,21 @@ size_t R3LiveShifter::getStartDelay() const { - int fixed = getWindowSourceSize() / 2 + m_resamplerDelay * 2; - int variable = getWindowSourceSize() / 2; - if (m_pitchScale < 1.0) { - return size_t(fixed + ceil(variable / m_pitchScale)); - } else { - return size_t(fixed + ceil(variable * m_pitchScale)); + int inDelay = getWindowSourceSize() + m_initialResamplerDelays.first; + int outDelay = int(floor(inDelay * getOutRatio())) + m_initialResamplerDelays.second; + + int total = outDelay; + int bs = getBlockSize(); + if (m_pitchScale > 1.0) { + total += bs - 1; + } else if (m_pitchScale < 1.0) { + int scaled = int(ceil(bs / m_pitchScale)); + total -= bs * (scaled - bs) / bs; } + + m_log.log(2, "R3LiveShifter::getStartDelay: inDelay, outDelay", inDelay, outDelay); + m_log.log(1, "R3LiveShifter::getStartDelay", total); + return total; } size_t @@ -345,12 +352,7 @@ readIn(input); - double outRatio = 1.0; - - if (m_pitchScale < 1.0) { - outRatio = 1.0 / m_pitchScale; - } - + double outRatio = getOutRatio(); int requiredInOutbuf = int(ceil(incount / outRatio)); generate(requiredInOutbuf); @@ -409,11 +411,7 @@ } } - double inRatio = 1.0; - if (m_pitchScale > 1.0) { - inRatio = 1.0 / m_pitchScale; - } - + double inRatio = getInRatio(); m_log.log(2, "R3LiveShifter::readIn: ratio", inRatio); int resampleBufSize = int(m_channelData.at(0)->resampled.size()); @@ -601,11 +599,7 @@ int R3LiveShifter::readOut(float *const *output, int outcount) { - double outRatio = 1.0; - if (m_pitchScale < 1.0) { - outRatio = 1.0 / m_pitchScale; - } - + double outRatio = getOutRatio(); m_log.log(2, "R3LiveShifter::readOut: outcount and ratio", outcount, outRatio); int resampledCount = 0; diff --git a/src/finer/R3LiveShifter.h b/src/finer/R3LiveShifter.h --- a/src/finer/R3LiveShifter.h +++ b/src/finer/R3LiveShifter.h @@ -311,7 +311,7 @@ ChannelAssembly m_channelAssembly; std::unique_ptr m_inResampler; std::unique_ptr m_outResampler; - int m_resamplerDelay; + std::pair m_initialResamplerDelays; bool m_useReadahead; int m_prevInhop; int m_prevOuthop; @@ -387,6 +387,22 @@ return true; } + double getInRatio() const { + if (m_pitchScale > 1.0) { + return 1.0 / m_pitchScale; + } else { + return 1.0; + } + } + + double getOutRatio() const { + if (m_pitchScale < 1.0) { + return 1.0 / m_pitchScale; + } else { + return 1.0; + } + } + int getWindowSourceSize() const { if (m_useReadahead) { int sz = m_guideConfiguration.classificationFftSize + diff --git a/src/test/TestLiveShifter.cpp b/src/test/TestLiveShifter.cpp --- a/src/test/TestLiveShifter.cpp +++ b/src/test/TestLiveShifter.cpp @@ -182,8 +182,6 @@ int delay = shifter.getStartDelay(); - std::cerr << "delay reported as " << delay << std::endl; - // We now have n samples of a simple sinusoid with stretch factor // 1.0; obviously we expect the output to be essentially the same // thing. It will have lower precision for a while at the start, @@ -240,7 +238,28 @@ BOOST_AUTO_TEST_CASE(sinusoid_down_octave) { int n = 20000; - check_sinusoid_shifted(n, 44100, 440.f, 0.5f, 0, true); + check_sinusoid_shifted(n, 44100, 440.f, 0.5f, 0, false); +// check_sinusoid_shifted(n, 48000, 260.f, 0.5f, 0, false); +} + +BOOST_AUTO_TEST_CASE(sinusoid_down_2octave) +{ + int n = 20000; + check_sinusoid_shifted(n, 44100, 440.f, 0.25f, 0, false); +// check_sinusoid_shifted(n, 48000, 260.f, 0.5f, 0, false); +} + +BOOST_AUTO_TEST_CASE(sinusoid_up_octave) +{ + int n = 20000; + check_sinusoid_shifted(n, 44100, 440.f, 2.0f, 0, false); +// check_sinusoid_shifted(n, 48000, 260.f, 0.5f, 0, false); +} + +BOOST_AUTO_TEST_CASE(sinusoid_up_2octave) +{ + int n = 20000; + check_sinusoid_shifted(n, 44100, 440.f, 4.0f, 0, false); // check_sinusoid_shifted(n, 48000, 260.f, 0.5f, 0, false); }