Mercurial > hg > qm-dsp
diff tests/TestChromagram.cpp @ 222:0990c1cb4049 chroma-key-tuning-review
(Incomplete) unit tests for chroma and key estimation
author | Chris Cannam |
---|---|
date | Thu, 23 May 2019 13:29:02 +0100 |
parents | |
children | 1b89d1916cd5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/TestChromagram.cpp Thu May 23 13:29:02 2019 +0100 @@ -0,0 +1,111 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +#include "dsp/chromagram/Chromagram.h" + +#include <iostream> + +#include <cmath> + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN + +#include <boost/test/unit_test.hpp> + +BOOST_AUTO_TEST_SUITE(TestChromagram) + +using std::cout; +using std::endl; +using std::string; +using std::vector; + +string midiPitchName(int midiPitch) +{ + static string names[] = { + "C", "C#", "D", "D#", + "E", "F", "F#", "G", + "G#", "A", "A#", "B" + }; + + return names[midiPitch % 12]; +} + +vector<double> generateSinusoid(double frequency, + int sampleRate, + int length) +{ + vector<double> buffer; + buffer.reserve(length); + for (int i = 0; i < length; ++i) { + buffer.push_back(sin(i * M_PI * 2.0 * frequency / sampleRate)); + } + return buffer; +} + +double frequencyForPitch(int midiPitch, double concertA) +{ + return concertA * pow(2.0, (midiPitch - 69.0) / 12.0); +} + +BOOST_AUTO_TEST_CASE(sinusoid_12tET) +{ + double concertA = 440.0; + int sampleRate = 44100; + int bpo = 60; + + ChromaConfig config { + sampleRate, + frequencyForPitch(36, concertA), + frequencyForPitch(108, concertA), + bpo, + 0.0054, + MathUtilities::NormaliseNone + }; + + Chromagram chroma(config); + + for (int midiPitch = 48; midiPitch < 96; ++midiPitch) { + + cout << endl; + + int blockSize = chroma.getFrameSize(); + int hopSize = chroma.getHopSize(); + cerr << "blockSize = " << blockSize + << ", hopSize = " << hopSize << endl; + + double frequency = frequencyForPitch(midiPitch, concertA); + int expectedPeakBin = ((midiPitch - 36) * 5) % bpo; + + cout << "midiPitch = " << midiPitch + << ", name = " << midiPitchName(midiPitch) + << ", frequency = " << frequency + << ", expected peak bin = " + << expectedPeakBin << endl; + + vector<double> signal = generateSinusoid(frequency, + sampleRate, + blockSize); + + double *output = chroma.process(signal.data()); + + int peakBin = -1; + double peakValue = 0.0; + + for (int i = 0; i < bpo; ++i) { + if (i == 0 || output[i] > peakValue) { + peakValue = output[i]; + peakBin = i; + } + } + + cout << "peak value = " << peakValue << " at bin " << peakBin << endl; + cout << "(neighbouring values are " + << (peakBin > 0 ? output[peakBin-1] : output[bpo-1]) + << " and " + << (peakBin+1 < bpo ? output[peakBin+1] : output[0]) + << ")" << endl; + + BOOST_CHECK_EQUAL(peakBin, expectedPeakBin); + } +} + +BOOST_AUTO_TEST_SUITE_END()