692a8ef9f678 — Chris Cannam 2 months ago
Measure rather than guess resampler delay
2 files changed, 33 insertions(+), 9 deletions(-)

M src/finer/R3LiveShifter.cpp
M src/finer/R3LiveShifter.h
M src/finer/R3LiveShifter.cpp +31 -9
@@ 42,6 42,7 @@ R3LiveShifter::R3LiveShifter(Parameters 
             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<Resampler>
         (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<float> 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() co
 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
     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
          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 *out
             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,

          
M src/finer/R3LiveShifter.h +2 -0
@@ 317,6 317,7 @@ protected:
     ChannelAssembly m_channelAssembly;
     std::unique_ptr<Resampler> m_inResampler;
     std::unique_ptr<Resampler> 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);