changeset 138:e89d489af128

Add one-shot resample function
author Chris Cannam
date Sun, 13 Oct 2013 12:47:50 +0100
parents dce8337a83c8
children 7fe0da91e9c3
files dsp/rateconversion/Resampler.cpp dsp/rateconversion/Resampler.h dsp/rateconversion/TestResampler.cpp
diffstat 3 files changed, 51 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/dsp/rateconversion/Resampler.cpp	Fri Oct 11 18:00:51 2013 +0100
+++ b/dsp/rateconversion/Resampler.cpp	Sun Oct 13 12:47:50 2013 +0100
@@ -7,6 +7,9 @@
 #include "qm-dsp/base/SincWindow.h"
 
 #include <iostream>
+#include <vector>
+
+using std::vector;
 
 Resampler::Resampler(int sourceRate, int targetRate) :
     m_sourceRate(sourceRate),
@@ -145,3 +148,23 @@
     return m;
 }
 
+std::vector<double>
+Resampler::resample(int sourceRate, int targetRate, const double *data, int n)
+{
+    Resampler r(sourceRate, targetRate);
+
+    int latency = r.getLatency();
+
+    int m = int(ceil((n * targetRate) / sourceRate));
+    int m1 = m + latency;
+    int n1 = int((m1 * sourceRate) / targetRate);
+
+    vector<double> pad(n1 - n, 0.0);
+    vector<double> out(m1, 0.0);
+
+    int got = r.process(data, out.data(), n);
+    got += r.process(pad.data(), out.data() + got, pad.size());
+
+    return vector<double>(out.begin() + latency, out.begin() + got);
+}
+
--- a/dsp/rateconversion/Resampler.h	Fri Oct 11 18:00:51 2013 +0100
+++ b/dsp/rateconversion/Resampler.h	Sun Oct 13 12:47:50 2013 +0100
@@ -31,6 +31,13 @@
      */
     int getLatency() const { return m_latency; }
 
+    /**
+     * Carry out a one-off resample of a single block of n
+     * samples. The output is latency-compensated.
+     */
+    static std::vector<double> resample
+    (int sourceRate, int targetRate, const double *data, int n);
+
 private:
     int m_sourceRate;
     int m_targetRate;
--- a/dsp/rateconversion/TestResampler.cpp	Fri Oct 11 18:00:51 2013 +0100
+++ b/dsp/rateconversion/TestResampler.cpp	Sun Oct 13 12:47:50 2013 +0100
@@ -15,6 +15,23 @@
 
 using std::cout;
 using std::endl;
+using std::vector;
+
+void
+testResamplerOneShot(int sourceRate,
+		     int targetRate,
+		     int n,
+		     double *in,
+		     int m,
+		     double *expected)
+{
+    vector<double> resampled = Resampler::resample(sourceRate, targetRate,
+						   in, n);
+    BOOST_CHECK_EQUAL(resampled.size(), m);
+    for (int i = 0; i < m; ++i) {
+	BOOST_CHECK_SMALL(resampled[i] - expected[i], 1e-8);
+    }
+}
 
 void
 testResampler(int sourceRate,
@@ -24,6 +41,8 @@
 	      int m,
 	      double *expected)
 {
+//!!! to be useful, this should provide the input in varying-size chunks
+
     Resampler r(sourceRate, targetRate);
     int latency = r.getLatency();
     std::cerr << "latency = " << latency << std::endl;
@@ -57,7 +76,7 @@
     std::cerr << "\n";
 
     for (int i = latency; i < m1; ++i) {
-	BOOST_CHECK_CLOSE(outPadded[i], expected[i-latency], 1e-8);
+	BOOST_CHECK_SMALL(outPadded[i] - expected[i-latency], 1e-8);
     }
     delete[] outPadded;
     delete[] inPadded;
@@ -66,6 +85,7 @@
 BOOST_AUTO_TEST_CASE(sameRate)
 {
     double d[] = { 0, 0.1, -0.3, -0.4, -0.3, 0, 0.5, 0.2, 0.8, -0.1 };
+    testResamplerOneShot(4, 4, 10, d, 10, d);
     testResampler(4, 4, 10, d, 10, d);
 }