changeset 172:17a7d6bb9af6

Construct a currently-failing test on exact frequency in resampler (tracking down error in CQ)
author Chris Cannam
date Sat, 10 May 2014 13:41:06 +0100
parents 5f720340b0dd
children 6a820c2a3eb2
files tests/TestResampler.cpp
diffstat 1 files changed, 82 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/tests/TestResampler.cpp	Sat May 10 13:40:44 2014 +0100
+++ b/tests/TestResampler.cpp	Sat May 10 13:41:06 2014 +0100
@@ -150,6 +150,88 @@
     testResamplerOneShot(16, 8, 2000, in, 200, out, 256);
 }
 
+double
+measureSinFreq(const vector<double> &v, int rate, int countCycles)
+{
+    int n = v.size();
+    int firstCrossing = -1;
+    int lastCrossing = -1;
+    int nCrossings = 0;
+    // count -ve -> +ve transitions
+    for (int i = 0; i + 1 < n; ++i) {
+        if (v[i] <= 0.0 && v[i+1] > 0.0) {
+            if (firstCrossing < 0) firstCrossing = i;
+            lastCrossing = i;
+            ++nCrossings;
+            if (nCrossings == countCycles) break;
+        }
+    }
+    int nCycles = nCrossings - 1;
+    if (nCycles <= 0) return 0.0;
+    cout << "lastCrossing = " << lastCrossing << ", firstCrossing = " << firstCrossing << ", dist = " << lastCrossing - firstCrossing << ", nCycles = " << nCycles << endl;
+    double cycle = double(lastCrossing - firstCrossing) / nCycles;
+    return rate / cycle;
+}
+
+void
+testSinFrequency(int freq,
+                 int sourceRate,
+                 int targetRate)
+{
+    // Resampling a sinusoid and then resampling back should give us a
+    // sinusoid of the same frequency as we started with. Let's start
+    // with a few thousand cycles of it
+
+    int nCycles = 5000;
+
+    int duration = int(nCycles * float(sourceRate) / float(freq));
+    cout << "freq = " << freq << ", sourceRate = " << sourceRate << ", targetRate = " << targetRate << ", duration = " << duration << endl;
+
+    vector<double> in(duration, 0);
+    for (int i = 0; i < duration; ++i) {
+        in[i] = sin(i * M_PI * 2.0 * freq / sourceRate);
+    }
+
+    vector<double> out = Resampler::resample(sourceRate, targetRate,
+                                             in.data(), in.size());
+
+    vector<double> back = Resampler::resample(targetRate, sourceRate,
+                                              out.data(), out.size());
+
+    BOOST_CHECK_EQUAL(in.size(), back.size());
+
+    double inFreq = measureSinFreq(in, sourceRate, nCycles - 2);
+    double backFreq = measureSinFreq(back, sourceRate, nCycles - 2);
+    
+    cout << "inFreq = " << inFreq << ", backFreq = " << backFreq << endl;
+
+    BOOST_CHECK_SMALL(inFreq - backFreq, 1e-8);
+
+    //    for (int i = 0; i < int(in.size()); ++i) {
+//	BOOST_CHECK_SMALL(in[i] - back[i], 1e-6);
+//    }
+}
+
+BOOST_AUTO_TEST_CASE(downUp2)
+{
+    testSinFrequency(440, 44100, 22050);
+}
+
+BOOST_AUTO_TEST_CASE(downUp16)
+{
+    testSinFrequency(440, 48000, 3000);
+}
+
+BOOST_AUTO_TEST_CASE(upDown2)
+{
+    testSinFrequency(440, 44100, 88200);
+}
+
+BOOST_AUTO_TEST_CASE(upDown16)
+{
+    testSinFrequency(440, 3000, 48000);
+}
+
 vector<double>
 squareWave(int rate, double freq, int n)
 {