0aed42878801 — Chris Cannam 3 years ago
Refactor e2e tests, add another one
M .hgignore +1 -0
@@ 7,4 7,5 @@ example/resample
 test/e2e/halve
 test/e2e/random
 test/e2e/undulating
+test/e2e/oversample
 test/e2e/out

          
M build/Makefile.inc +9 -4
@@ 11,7 11,7 @@ HEADERS	:= $(wildcard $(HEADER_DIR)/*.h)
 OBJECTS	:= $(SOURCES:.cpp=.o)
 OBJECTS	:= $(OBJECTS:.c=.o)
 
-TEST_SOURCES	:= $(wildcard $(TEST_DIR)/*.cpp)
+TEST_SOURCES	:= $(wildcard $(TEST_DIR)/*.cpp) $(wildcard $(TEST_DIR)/e2e/*.cpp)
 TEST_OBJECTS	:= $(TEST_SOURCES:.cpp=.o)
 
 EXAMPLE_SOURCES	:= $(wildcard $(EXAMPLE_DIR)/*.cpp)

          
@@ 27,10 27,11 @@ LIBRARY	:= libbqresample.a
 
 all:	$(LIBRARY)
 
-test:	$(LIBRARY) test-resampler test/e2e/halve test/e2e/random test/e2e/undulating
+test:	$(LIBRARY) test-resampler test/e2e/halve test/e2e/oversample test/e2e/random test/e2e/undulating
 	./test-resampler
 	mkdir -p ./test/e2e/out
 	./test/e2e/halve ./test/e2e/sweep-log.wav ./test/e2e/out/halve.wav
+	./test/e2e/oversample ./test/e2e/sweep-log.wav ./test/e2e/out/oversample.wav
 	./test/e2e/random ./test/e2e/sweep-log.wav ./test/e2e/out/random.wav
 	./test/e2e/undulating ./test/e2e/sweep-log.wav ./test/e2e/out/undulating.wav
 

          
@@ 55,15 56,19 @@ clean:
 	rm -f $(OBJECTS) $(TEST_OBJECTS) $(EXAMPLE_OBJECTS)
 
 distclean:	clean
-	rm -f $(LIBRARY) test-resampler test/e2e/halve test/e2e/random test/e2e/undulating
+	rm -f $(LIBRARY) test-resampler test/e2e/halve test/e2e/oversample test/e2e/oversample test/e2e/random test/e2e/undulating
 
 depend:
 	makedepend $(RESAMPLE_DEFINES) -Y -fbuild/Makefile.inc $(SOURCES) $(HEADERS) $(TEST_SOURCES) $(EXAMPLE_SOURCES)
 
 
 # DO NOT DELETE
- 
+
 src/BQResampler.o: src/BQResampler.h
 src/Resampler.o: bqresample/Resampler.h src/BQResampler.h
 test/TestResampler.o: bqresample/Resampler.h
+test/e2e/halve.o: bqresample/Resampler.h test/e2e/e2e.cpp
+test/e2e/oversample.o: bqresample/Resampler.h test/e2e/e2e.cpp
+test/e2e/random.o: bqresample/Resampler.h test/e2e/e2e.cpp
+test/e2e/undulating.o: bqresample/Resampler.h test/e2e/e2e.cpp
 example/resample.o: bqresample/Resampler.h

          
M example/resample.cpp +17 -6
@@ 15,6 15,7 @@ void usage()
 {
     cerr << "Usage: resample [-v] [-c <converter>] -to <rate> <infile> <outfile>" << endl;
     cerr << "where <converter> may be 0, 1, or 2, for best, medium, or fastest respectively." << endl;
+    cerr << "The default converter is 0, best." << endl;
     cerr << "Supply -v for verbose output." << endl;
     exit(2);
 }

          
@@ 71,25 72,35 @@ int main(int argc, char **argv)
     int output_rate = round(target);
     int channels = info_in.channels;
     
-    cerr << "input rate = " << info_in.samplerate << endl;
-    cerr << "output rate = " << output_rate << endl;
+    if (verbose) {
+        cerr << "input rate = " << info_in.samplerate << endl;
+        cerr << "output rate = " << output_rate << endl;
+    }
 
     double ratio = target / info_in.samplerate;
-    cerr << "ratio = " << ratio << endl;
+    if (verbose) {
+        cerr << "ratio = " << ratio << endl;
+    }
 
     breakfastquay::Resampler::Parameters parameters;
     switch (quality)  {
     case 0:
         parameters.quality = breakfastquay::Resampler::Best;
-        cerr << "quality = best" << endl;
+        if (verbose) {
+            cerr << "quality = best" << endl;
+        }
         break;
     case 1:
         parameters.quality = breakfastquay::Resampler::FastestTolerable;
-        cerr << "quality = middling" << endl;
+        if (verbose) {
+            cerr << "quality = middling" << endl;
+        }
         break;
     case 2:
         parameters.quality = breakfastquay::Resampler::Fastest;
-        cerr << "quality = worst" << endl;
+        if (verbose) {
+            cerr << "quality = worst" << endl;
+        }
         break;
     }        
 

          
A => test/e2e/e2e.cpp +149 -0
@@ 0,0 1,149 @@ 
+
+// Not a standalone source file
+
+void usage()
+{
+    cerr << "This is a test program for bqresample. Please do not try to use it in earnest." << endl;
+    cerr << "Usage: " << programName << " [-v] [-c <converter>] <infile> <outfile>" << endl;
+    cerr << "where <converter> may be 0, 1, or 2, for best, medium, or fastest respectively." << endl;
+    cerr << "The default converter is 0, best." << endl;
+    cerr << "Supply -v for verbose output." << endl;
+    exit(2);
+}
+
+int main(int argc, char **argv)
+{
+    int quality = 0;
+    int arg;
+    bool verbose = false;
+
+    for (arg = 1; arg + 2 < argc; ++arg) {
+        if (!strcmp(argv[arg], "-c")) {
+            char *e = argv[arg+1];
+            quality = strtol(argv[arg+1], &e, 10);
+            if (*e || (quality < 0) || (quality > 2)) {
+                cerr << "error: invalid converter \""
+                     << argv[arg+1] << "\" (must be 0, 1, 2)" << endl;
+                usage();
+            }
+            ++arg;
+            continue;
+        } else if (!strcmp(argv[arg], "-v")) {
+            verbose = true;
+        } else {
+            cerr << "error: unexpected option \"" << argv[arg] << "\"" << endl;
+            usage();
+        }
+    }
+
+    if (arg + 2 != argc) {
+        usage();
+    }
+
+    string infilename = argv[arg];
+    string outfilename = argv[arg+1];
+    
+    SF_INFO info_in;
+    SNDFILE *file_in = sf_open(infilename.c_str(), SFM_READ, &info_in);
+    if (!file_in) {
+        cerr << "failed to open " << infilename << endl;
+        return 1;
+    }
+
+    int channels = info_in.channels;
+
+    if (verbose) {
+        cerr << "input rate = " << info_in.samplerate << endl;
+    }
+
+    double ratio = initialRatio;
+        
+    SF_INFO info_out;
+    memset(&info_out, 0, sizeof(SF_INFO));
+    info_out.channels = channels;
+    info_out.format = info_in.format;
+    info_out.samplerate = info_in.samplerate;
+    SNDFILE *file_out = sf_open(outfilename.c_str(), SFM_WRITE, &info_out);
+    if (!file_out) {
+        cerr << "failed to open " << outfilename << endl;
+        return 1;
+    }
+
+    int ibs = 1024;
+    int obs = ceil(ibs * ratio * 10);
+    float *ibuf = new float[ibs * channels];
+    float *obuf = new float[obs * channels];
+
+    breakfastquay::Resampler::Parameters parameters;
+    switch (quality)  {
+    case 0:
+        parameters.quality = breakfastquay::Resampler::Best;
+        if (verbose) {
+            cerr << "quality = best" << endl;
+        }
+        break;
+    case 1:
+        parameters.quality = breakfastquay::Resampler::FastestTolerable;
+        if (verbose) {
+            cerr << "quality = middling" << endl;
+        }
+        break;
+    case 2:
+        parameters.quality = breakfastquay::Resampler::Fastest;
+        if (verbose) {
+            cerr << "quality = worst" << endl;
+        }
+        break;
+    }        
+
+    if (isRatioChanging()) {
+        parameters.dynamism = breakfastquay::Resampler::RatioOftenChanging;
+        parameters.ratioChange = breakfastquay::Resampler::SmoothRatioChange;
+    } else {
+        parameters.dynamism = breakfastquay::Resampler::RatioMostlyFixed;
+        parameters.ratioChange = breakfastquay::Resampler::SuddenRatioChange;
+    }
+    
+    parameters.initialSampleRate = info_in.samplerate;
+    parameters.debugLevel = (verbose ? 1 : 0);
+    breakfastquay::Resampler resampler(parameters, channels);
+
+    int n = 0;
+    while (true) {
+        int count = sf_readf_float(file_in, ibuf, ibs);
+        if (verbose) {
+            cerr << ".";
+        }
+        if (count < 0) {
+            cerr << "error: count = " << count << endl;
+            break;
+        }
+        
+        bool final = (count < ibs);
+        int got = resampler.resampleInterleaved
+            (obuf, obs, ibuf, count, ratio, final);
+        
+        if (got == 0 && final) {
+            break;
+        } else {
+            for (int i = 0; i < got; ++i) {
+                if (obuf[i] < -1.0) obuf[i] = -1.0;
+                if (obuf[i] > 1.0) obuf[i] = 1.0;
+            }
+            sf_writef_float(file_out, obuf, got);
+        }
+        
+        ratio = nextRatio(ratio);
+        ++n;
+    }
+
+    if (verbose) {
+        cerr << endl;
+    }
+    
+    sf_close(file_in);
+    sf_close(file_out);
+    
+    delete[] ibuf;
+    delete[] obuf;
+}

          
M test/e2e/halve.cpp +8 -86
@@ 9,91 9,13 @@ 
 
 using namespace std;
 
-void usage()
-{
-    cerr << "This is a test program for bqresample. Please do not try to use it in earnest." << endl;
-    cerr << "Usage: halve <infile> <outfile>" << endl;
-    exit(2);
+static const string programName = "halve";
+static const double initialRatio = 0.5;
+static double nextRatio(double ratio) {
+    return ratio;
+}
+static bool isRatioChanging() {
+    return false;
 }
 
-int main(int argc, char **argv)
-{
-    if (argc != 3) {
-        usage();
-    }
-
-    string infilename = argv[1];
-    string outfilename = argv[2];
-    
-    SF_INFO info_in;
-    SNDFILE *file_in = sf_open(infilename.c_str(), SFM_READ, &info_in);
-    if (!file_in) {
-        cerr << "failed to open " << infilename << endl;
-        return 1;
-    }
-
-    int output_rate = info_in.samplerate / 2;
-    int channels = info_in.channels;
-    double ratio = double(output_rate) / info_in.samplerate;
-    
-//    cerr << "input rate = " << info_in.samplerate << endl;
-//    cerr << "output rate = " << output_rate << endl;
-//    cerr << "ratio = " << ratio << endl;
-
-    SF_INFO info_out;
-    memset(&info_out, 0, sizeof(SF_INFO));
-    info_out.channels = channels;
-    info_out.format = info_in.format;
-    info_out.samplerate = output_rate;
-    SNDFILE *file_out = sf_open(outfilename.c_str(), SFM_WRITE, &info_out);
-    if (!file_out) {
-        cerr << "failed to open " << outfilename << endl;
-        return 1;
-    }
-
-    int ibs = 1024;
-    int obs = ceil(ibs * ratio);
-    float *ibuf = new float[ibs * channels];
-    float *obuf = new float[obs * channels];
-
-    breakfastquay::Resampler::Parameters parameters;
-    parameters.quality = breakfastquay::Resampler::Best;
-    parameters.dynamism = breakfastquay::Resampler::RatioMostlyFixed;
-    parameters.ratioChange = breakfastquay::Resampler::SuddenRatioChange;
-    parameters.initialSampleRate = info_in.samplerate;
-//    parameters.debugLevel = 1;
-    breakfastquay::Resampler resampler(parameters, channels);
-
-    int n = 0; 
-    while (true) {
-        int count = sf_readf_float(file_in, ibuf, ibs);
-        cerr << ".";
-        if (count < 0) {
-            cerr << "error: count = " << count << endl;
-            break;
-        }
-
-        bool final = (count < ibs);
-        int got = resampler.resampleInterleaved
-            (obuf, obs, ibuf, count, ratio, final);
-        
-        if (got == 0 && final) {
-            break;
-        } else {
-            for (int i = 0; i < got; ++i) {
-                if (obuf[i] < -1.0) obuf[i] = -1.0;
-                if (obuf[i] > 1.0) obuf[i] = 1.0;
-            }
-            sf_writef_float(file_out, obuf, got);
-        }
-        ++n;
-    }
-
-    cerr << endl;
-    
-    sf_close(file_in);
-    sf_close(file_out);
-
-    delete[] ibuf;
-    delete[] obuf;
-}
+#include "e2e.cpp"

          
A => test/e2e/oversample.cpp +21 -0
@@ 0,0 1,21 @@ 
+
+#include "bqresample/Resampler.h"
+
+#include <sndfile.h>
+#include <cstring>
+#include <cstdlib>
+#include <cmath>
+#include <iostream>
+
+using namespace std;
+
+static const string programName = "oversample";
+static const double initialRatio = 16.0;
+static double nextRatio(double ratio) {
+    return ratio;
+}
+static bool isRatioChanging() {
+    return false;
+}
+
+#include "e2e.cpp"

          
M test/e2e/random.cpp +8 -86
@@ 9,91 9,13 @@ 
 
 using namespace std;
 
-void usage()
-{
-    cerr << "This is a test program for bqresample. Please do not try to use it in earnest." << endl;
-    cerr << "Usage: random <infile> <outfile>" << endl;
-    exit(2);
+static const string programName = "random";
+static const double initialRatio = 0.5;
+static double nextRatio(double) {
+    return drand48() * 2.5 + 0.1;
+}
+static bool isRatioChanging() {
+    return true;
 }
 
-int main(int argc, char **argv)
-{
-    if (argc != 3) {
-        usage();
-    }
-
-    string infilename = argv[1];
-    string outfilename = argv[2];
-    
-    SF_INFO info_in;
-    SNDFILE *file_in = sf_open(infilename.c_str(), SFM_READ, &info_in);
-    if (!file_in) {
-        cerr << "failed to open " << infilename << endl;
-        return 1;
-    }
-
-    int channels = info_in.channels;
-    
-//    cerr << "input rate = " << info_in.samplerate << endl;
-
-    double ratio = 0.5; // initially
-        
-    SF_INFO info_out;
-    memset(&info_out, 0, sizeof(SF_INFO));
-    info_out.channels = channels;
-    info_out.format = info_in.format;
-    info_out.samplerate = info_in.samplerate;
-    SNDFILE *file_out = sf_open(outfilename.c_str(), SFM_WRITE, &info_out);
-    if (!file_out) {
-        cerr << "failed to open " << outfilename << endl;
-        return 1;
-    }
-
-    int ibs = 1024;
-    int obs = ceil(ibs * ratio * 10);
-    float *ibuf = new float[ibs];
-    float *obuf = new float[obs];
-
-    breakfastquay::Resampler::Parameters parameters;
-    parameters.quality = breakfastquay::Resampler::Best;
-    parameters.dynamism = breakfastquay::Resampler::RatioOftenChanging;
-    parameters.ratioChange = breakfastquay::Resampler::SmoothRatioChange;
-    parameters.initialSampleRate = info_in.samplerate;
-//    parameters.debugLevel = 1;
-    breakfastquay::Resampler resampler(parameters, channels);
-
-    int n = 0;
-    while (true) {
-        int count = sf_readf_float(file_in, ibuf, ibs);
-        cerr << ".";
-        if (count < 0) {
-            cerr << "error: count = " << count << endl;
-            break;
-        }
-        
-        bool final = (count < ibs);
-        int got = resampler.resampleInterleaved
-            (obuf, obs, ibuf, count, ratio, final);
-        
-        if (got == 0 && final) {
-            break;
-        } else {
-            for (int i = 0; i < got; ++i) {
-                if (obuf[i] < -1.0) obuf[i] = -1.0;
-                if (obuf[i] > 1.0) obuf[i] = 1.0;
-            }
-            sf_writef_float(file_out, obuf, got);
-        }
-        
-        ratio = drand48() * 2.5 + 0.1;
-        ++n;
-    }
-
-    cerr << endl;
-    
-    sf_close(file_in);
-    sf_close(file_out);
-    
-    delete[] ibuf;
-    delete[] obuf;
-}
+#include "e2e.cpp"

          
M test/e2e/undulating.cpp +12 -90
@@ 9,95 9,17 @@ 
 
 using namespace std;
 
-void usage()
-{
-    cerr << "This is a test program for bqresample. Please do not try to use it in earnest." << endl;
-    cerr << "Usage: undulating <infile> <outfile>" << endl;
-    exit(2);
+static const string programName = "undulating";
+static const double initialRatio = 0.5;
+static double nextRatio(double ratio) {
+    static double factor = 1.01;
+    ratio *= factor;
+    if (ratio > 3.0) factor = 0.99;
+    else if (ratio < 0.3) factor = 1.01;
+    return ratio;
+}
+static bool isRatioChanging() {
+    return true;
 }
 
-int main(int argc, char **argv)
-{
-    if (argc != 3) {
-        usage();
-    }
-
-    string infilename = argv[1];
-    string outfilename = argv[2];
-    
-    SF_INFO info_in;
-    SNDFILE *file_in = sf_open(infilename.c_str(), SFM_READ, &info_in);
-    if (!file_in) {
-        cerr << "failed to open " << infilename << endl;
-        return 1;
-    }
-    
-    int channels = info_in.channels;
-
-//    cerr << "input rate = " << info_in.samplerate << endl;
-        
-    SF_INFO info_out;
-    memset(&info_out, 0, sizeof(SF_INFO));
-    info_out.channels = channels;
-    info_out.format = info_in.format;
-    info_out.samplerate = info_in.samplerate;
-    SNDFILE *file_out = sf_open(outfilename.c_str(), SFM_WRITE, &info_out);
-    if (!file_out) {
-        cerr << "failed to open " << outfilename << endl;
-        return 1;
-    }
-
-    int ibs = 1024;
-    int obs = ceil(ibs * 3);
-    float *ibuf = new float[ibs];
-    float *obuf = new float[obs];
-
-    breakfastquay::Resampler::Parameters parameters;
-    parameters.quality = breakfastquay::Resampler::Best;
-    parameters.dynamism = breakfastquay::Resampler::RatioOftenChanging;
-    parameters.ratioChange = breakfastquay::Resampler::SmoothRatioChange;
-    parameters.initialSampleRate = info_in.samplerate;
-//    parameters.debugLevel = 1;
-    breakfastquay::Resampler resampler(parameters, channels);
-
-    double ratio = 0.5; // initially
-    double factor = 1.01; 
-    
-    int n = 0;
-    while (true) {
-        int count = sf_readf_float(file_in, ibuf, ibs);
-        cerr << ".";
-        if (count < 0) {
-            cerr << "error: count = " << count << endl;
-            break;
-        }
-        
-        bool final = (count < ibs);
-        int got = resampler.resampleInterleaved
-            (obuf, obs, ibuf, count, ratio, final);
-        
-        if (got == 0 && final) {
-            break;
-        } else {
-            for (int i = 0; i < got; ++i) {
-                if (obuf[i] < -1.0) obuf[i] = -1.0;
-                if (obuf[i] > 1.0) obuf[i] = 1.0;
-            }
-            sf_writef_float(file_out, obuf, got);
-        }
-        
-        ratio *= factor;
-        if (ratio > 3.0) factor = 0.99;
-        else if (ratio < 0.3) factor = 1.01;
-        
-        ++n;
-    }
-
-    cerr << endl;
-    
-    sf_close(file_in);
-    sf_close(file_out);
-    
-    delete[] ibuf;
-    delete[] obuf;
-}
+#include "e2e.cpp"