Mercurial > hg > silvet
diff constant-q-cpp/test/TestCQTime.cpp @ 366:5d0a2ebb4d17
Bring dependent libraries in to repo
author | Chris Cannam |
---|---|
date | Fri, 24 Jun 2016 14:47:45 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/constant-q-cpp/test/TestCQTime.cpp Fri Jun 24 14:47:45 2016 +0100 @@ -0,0 +1,120 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "cq/CQSpectrogram.h" + +#include "dsp/Window.h" + +#include <cmath> +#include <vector> +#include <iostream> + +using std::vector; +using std::cerr; +using std::endl; + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN + +#include <boost/test/unit_test.hpp> + +BOOST_AUTO_TEST_SUITE(TestCQTime) + +// Principle: Run a Dirac impulse through the CQ transform and check +// that its output has all the peak bins aligned correctly in time. + +// Set up fs/2 = 50, frequency range 10 -> 40 i.e. 2 octaves, fixed +// duration of 2 seconds +static const double sampleRate = 100; +static const double cqmin = 10; +static const double cqmax = 40; +static const double bpo = 4; +static const int duration = sampleRate * 2; + +// Threshold below which to ignore a column completely +static const double threshold = 0.08; + +void +testCQTime(double t) +{ + vector<CQSpectrogram::Interpolation> interpolationTypes; + interpolationTypes.push_back(CQSpectrogram::InterpolateZeros); + interpolationTypes.push_back(CQSpectrogram::InterpolateHold); + interpolationTypes.push_back(CQSpectrogram::InterpolateLinear); + + for (int k = 0; k < int(interpolationTypes.size()); ++k) { + + CQSpectrogram::Interpolation interp = interpolationTypes[k]; + + CQParameters params(sampleRate, cqmin, cqmax, bpo); + CQSpectrogram cq(params, interp); + + BOOST_CHECK_EQUAL(cq.getBinsPerOctave(), bpo); + BOOST_CHECK_EQUAL(cq.getOctaves(), 2); + + vector<double> input(duration, 0.0); + int ix = int(floor(t * sampleRate)); + if (ix >= duration) ix = duration-1; + input[ix] = 1.0; + + CQSpectrogram::RealBlock output = cq.process(input); + CQSpectrogram::RealBlock rest = cq.getRemainingOutput(); + output.insert(output.end(), rest.begin(), rest.end()); + + BOOST_CHECK_EQUAL(output[0].size(), + cq.getBinsPerOctave() * cq.getOctaves()); + + vector<int> peaks; + double eps = 1e-8; + + for (int j = 0; j < int(output[0].size()); ++j) { + + int maxidx = -1; + double max = 0.0; + for (int i = 0; i < int(output.size()); ++i) { + double value = output[i][j]; + if (i == 0 || value + eps > max) { + max = value; + maxidx = i; + } + } + + peaks.push_back(maxidx); + } + + for (int j = 1; j < int(peaks.size()); ++j) { + int oct = j / bpo; + int spacing = (1 << oct); + int actual = peaks[j]/spacing; + int expected = int(round(double(peaks[0])/spacing)); + if (actual != expected) { + cerr << "ERROR: In row " << j << " (bin freq " + << cq.getBinFrequency(j) << "), interpolation " << interp + << ", maximum value for time " << t + << "\n found at index " << peaks[j] + << " of " << output.size() << " which does not align with" + << " highest frequency\n bin peak at " << peaks[0] + << " given octave spacing of " << spacing + << "\n [latency = " << cq.getLatency() + << ", hop = " << cq.getColumnHop() << ", duration = " + << duration << ", ix = " << ix << "]" << endl; + cerr << "row contains: "; + for (int i = 0; i < int(output.size()); ++i) { + if (i == expected * spacing) cerr << "*"; + if (i == peaks[j]) cerr << "**"; + cerr << output[i][j] << " "; + } + cerr << endl; + + BOOST_CHECK_EQUAL(actual, expected); + } + } + } +} + +BOOST_AUTO_TEST_CASE(time_zero) { testCQTime(0); } +BOOST_AUTO_TEST_CASE(time_half) { testCQTime(0.5); } +BOOST_AUTO_TEST_CASE(time_one) { testCQTime(1.0); } +BOOST_AUTO_TEST_CASE(time_two) { testCQTime(2.0); } + +BOOST_AUTO_TEST_SUITE_END() +