48aeda402d20 — Chris Cannam 12 days ago
Experiment with small crossfade on resampler rate change
1 files changed, 76 insertions(+), 15 deletions(-)

M src/dsp/Resampler.cpp
M src/dsp/Resampler.cpp +76 -15
@@ 609,6 609,10 @@ D_SRC::resample(const float *const R__ *
 {
     SRC_DATA data;
 
+    static size_t n_in = 0, n_out = 0;
+
+    std::cerr << "Resampler::process: at input sample " << n_in << ", output sample " << n_out << ", incount = " << incount << ", ratio = " << ratio << ", incount * ratio = " << incount * ratio << std::endl;
+
     int outcount = lrintf(ceilf(incount * ratio));
 
     if (m_channels == 1) {

          
@@ 628,12 632,57 @@ D_SRC::resample(const float *const R__ *
         data.data_out = m_iout;
     }
 
-    data.input_frames = incount;
-    data.output_frames = outcount;
     data.src_ratio = ratio;
-    data.end_of_input = (final ? 1 : 0);
+
+#ifdef PERFORM_LIBSAMPLERATE_XFADE
+    const int xfade = 10;
+    int err = 0;
+    if (ratio != m_lastRatio && outcount > xfade) {
+        int xin = lrintf(ceilf(xfade / ratio));
+        SRC_STATE *xsrc = src_clone(m_src, &err);
+        float *xbuf = 0;
+        if (err) {
+            std::cerr << "Resampler::process: libsamplerate error: "
+                      << src_strerror(err) << ", skipping xfade" << std::endl;
+        } else {
 
-    int err = src_process(m_src, &data);
+            data.input_frames = xin;
+            data.output_frames = xfade;
+            data.end_of_input = false;
+            
+            err = src_process(xsrc, &data);
+            xbuf = allocate<float>(xfade * m_channels);
+            v_copy(xbuf, data.data_out, xfade * m_channels);
+            src_delete(xsrc);
+        }
+        
+        data.input_frames = incount;
+        data.output_frames = outcount;
+        data.end_of_input = (final ? 1 : 0);
+        
+        src_set_ratio(m_src, ratio);
+        err = src_process(m_src, &data);
+
+        if (xbuf) {
+            for (int i = 0; i < xfade; ++i) {
+                for (int c = 0; c < m_channels; ++c) {
+                    float g = float(i+1) / float(xfade);
+                    float f = data.data_out[i * m_channels + c] * g +
+                        xbuf[i * m_channels + c] * (1.f - g);
+                    data.data_out[i * m_channels + c] = f;
+                }
+            }
+            deallocate<float>(xbuf);
+        }
+    } else {
+#endif
+        data.input_frames = incount;
+        data.output_frames = outcount;
+        data.end_of_input = (final ? 1 : 0);
+        err = src_process(m_src, &data);
+#ifdef PERFORM_LIBSAMPLERATE_XFADE
+    }
+#endif
 
     if (err) {
         std::cerr << "Resampler::process: libsamplerate error: "

          
@@ 649,6 698,13 @@ D_SRC::resample(const float *const R__ *
 
     m_lastRatio = ratio;
 
+    n_in += incount;
+    n_out += data.output_frames_gen;
+
+    std::cerr << "outcount = " << data.output_frames_gen << std::endl;
+
+//    out[0][0] = 1.0;
+    
     return data.output_frames_gen;
 }
 

          
@@ 670,7 726,7 @@ D_SRC::resampleInterleaved(const float *
     data.output_frames = outcount;
     data.src_ratio = ratio;
     data.end_of_input = (final ? 1 : 0);
-
+    
     int err = src_process(m_src, &data);
 
     if (err) {

          
@@ 942,6 998,8 @@ D_Speex::D_Speex(Resampler::Quality qual
                   << std::endl;
     }
 
+    q = 10; //!!!
+    
     int err = 0;
     m_resampler = speex_resampler_init_frac(m_channels,
                                             1, 1,

          
@@ 1030,7 1088,10 @@ D_Speex::resample(const float *const R__
     }
 
     unsigned int uincount = incount;
-    unsigned int outcount = lrintf(ceilf(incount * ratio)); //!!! inexact now
+
+    // This doesn't have to be exact, but it does have to be
+    // sufficient, hence going over by one
+    unsigned int outcount = lrintf(ceilf((incount + 1) * ratio));
 
     float *data_in, *data_out;
 

          
@@ 1057,16 1118,16 @@ D_Speex::resample(const float *const R__
                                                         data_out,
                                                         &outcount);
 
-//    if (incount != int(uincount)) {
-//        std::cerr << "Resampler: NOTE: Consumed " << uincount
-//                  << " of " << incount << " frames" << std::endl;
-//    }
+    if (incount != int(uincount)) {
+        std::cerr << "Resampler: NOTE: Consumed " << uincount
+                  << " of " << incount << " frames" << std::endl;
+    }
 
-//    if (outcount != lrintf(ceilf(incount * ratio))) {
-//        std::cerr << "Resampler: NOTE: Obtained " << outcount
-//                  << " of " << lrintf(ceilf(incount * ratio)) << " frames"
-//                  << std::endl;
-//    }
+    if (outcount != lrintf(ceilf(incount * ratio))) {
+        std::cerr << "Resampler: NOTE: Obtained " << outcount
+                  << " of " << lrintf(ceilf(incount * ratio)) << " frames"
+                  << std::endl;
+    }
         
     //!!! check err, respond appropriately