fd02eb4cde6c — Chris Cannam 4 months ago
Account for stretch-dependent offset (constant within stretch ratio) due to gap between likely early-detection location of transient (needed for proper phase reset) and perceived transient location
3 files changed, 17 insertions(+), 6 deletions(-)

M src/StretchCalculator.cpp
M src/StretchCalculator.h
M src/StretcherImpl.cpp
M src/StretchCalculator.cpp +13 -4
@@ 37,7 37,8 @@
 	
 StretchCalculator::StretchCalculator(size_t sampleRate,
                                      size_t inputIncrement,
-                                     bool useHardPeaks) :
+                                     bool useHardPeaks,
+                                     int curveFrameSize) :
     m_sampleRate(sampleRate),
     m_increment(inputIncrement),
     m_prevDf(0),

          
@@ 46,7 47,8 @@
     m_prevRatio(1.0),
     m_transientAmnesty(0),
     m_debugLevel(0),
-    m_useHardPeaks(useHardPeaks)
+    m_useHardPeaks(useHardPeaks),
+    m_curveFrameSize(curveFrameSize)
 {
 //    std::cerr << "StretchCalculator::StretchCalculator: useHardPeaks = " << useHardPeaks << std::endl;
 }    

          
@@ 205,9 207,16 @@
         // "normal" behaviour -- fixed points are strictly in
         // proportion
         peaks = m_peaks;
+        double perChunk = double(outputDuration) / double(totalCount);
+        double ratio = perChunk / m_increment;
+        int hardPeakOffset = lrint((m_curveFrameSize/2 - m_increment) *
+                                   (ratio - 1.0));
         for (size_t i = 0; i < peaks.size(); ++i) {
-            targets.push_back
-                (lrint((double(peaks[i].chunk) * outputDuration) / totalCount));
+            size_t target = lrint(double(peaks[i].chunk) * perChunk);
+            if (peaks[i].hard && target > 0) {
+                target += hardPeakOffset;
+            }
+            targets.push_back(target);
         }
         return;
     }

          
M src/StretchCalculator.h +3 -1
@@ 35,7 35,8 @@
 class StretchCalculator
 {
 public:
-    StretchCalculator(size_t sampleRate, size_t inputIncrement, bool useHardPeaks);
+    StretchCalculator(size_t sampleRate, size_t inputIncrement,
+                      bool useHardPeaks, int curveFrameSize);
     virtual ~StretchCalculator();
 
     /**

          
@@ 110,6 111,7 @@
     int m_transientAmnesty; // only in RT mode; handled differently offline
     int m_debugLevel;
     bool m_useHardPeaks;
+    int m_curveFrameSize;
 
     std::map<size_t, size_t> m_keyFrameMap;
     std::vector<Peak> m_peaks;

          
M src/StretcherImpl.cpp +1 -1
@@ 707,7 707,7 @@
     delete m_stretchCalculator;
     m_stretchCalculator = new StretchCalculator
         (m_sampleRate, m_increment,
-         !(m_options & OptionTransientsSmooth));
+         !(m_options & OptionTransientsSmooth), m_fftSize);
 
     m_stretchCalculator->setDebugLevel(m_debugLevel);
     m_inputDuration = 0;