Chris@222: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@222: Chris@222: #include "dsp/chromagram/Chromagram.h" Chris@222: Chris@222: #include Chris@222: Chris@222: #include Chris@222: Chris@222: #define BOOST_TEST_DYN_LINK Chris@222: #define BOOST_TEST_MAIN Chris@222: Chris@222: #include Chris@222: Chris@222: BOOST_AUTO_TEST_SUITE(TestChromagram) Chris@222: Chris@222: using std::cout; Chris@222: using std::endl; Chris@222: using std::string; Chris@222: using std::vector; Chris@222: Chris@222: string midiPitchName(int midiPitch) Chris@222: { Chris@222: static string names[] = { Chris@222: "C", "C#", "D", "D#", Chris@222: "E", "F", "F#", "G", Chris@222: "G#", "A", "A#", "B" Chris@222: }; Chris@222: Chris@222: return names[midiPitch % 12]; Chris@222: } Chris@222: Chris@222: vector generateSinusoid(double frequency, Chris@222: int sampleRate, Chris@222: int length) Chris@222: { Chris@222: vector buffer; Chris@222: buffer.reserve(length); Chris@222: for (int i = 0; i < length; ++i) { Chris@222: buffer.push_back(sin(i * M_PI * 2.0 * frequency / sampleRate)); Chris@222: } Chris@222: return buffer; Chris@222: } Chris@222: Chris@222: double frequencyForPitch(int midiPitch, double concertA) Chris@222: { Chris@222: return concertA * pow(2.0, (midiPitch - 69.0) / 12.0); Chris@222: } Chris@222: Chris@222: BOOST_AUTO_TEST_CASE(sinusoid_12tET) Chris@222: { Chris@222: double concertA = 440.0; Chris@222: int sampleRate = 44100; Chris@222: int bpo = 60; Chris@222: Chris@222: ChromaConfig config { Chris@222: sampleRate, Chris@222: frequencyForPitch(36, concertA), Chris@222: frequencyForPitch(108, concertA), Chris@222: bpo, Chris@222: 0.0054, Chris@222: MathUtilities::NormaliseNone Chris@222: }; Chris@222: Chris@222: Chromagram chroma(config); Chris@222: Chris@222: for (int midiPitch = 48; midiPitch < 96; ++midiPitch) { Chris@222: Chris@222: cout << endl; Chris@222: Chris@222: int blockSize = chroma.getFrameSize(); Chris@222: int hopSize = chroma.getHopSize(); Chris@222: cerr << "blockSize = " << blockSize Chris@222: << ", hopSize = " << hopSize << endl; Chris@222: Chris@222: double frequency = frequencyForPitch(midiPitch, concertA); Chris@222: int expectedPeakBin = ((midiPitch - 36) * 5) % bpo; Chris@222: Chris@222: cout << "midiPitch = " << midiPitch Chris@222: << ", name = " << midiPitchName(midiPitch) Chris@222: << ", frequency = " << frequency Chris@222: << ", expected peak bin = " Chris@222: << expectedPeakBin << endl; Chris@222: Chris@222: vector signal = generateSinusoid(frequency, Chris@222: sampleRate, Chris@222: blockSize); Chris@222: Chris@222: double *output = chroma.process(signal.data()); Chris@222: Chris@222: int peakBin = -1; Chris@222: double peakValue = 0.0; Chris@222: Chris@222: for (int i = 0; i < bpo; ++i) { Chris@222: if (i == 0 || output[i] > peakValue) { Chris@222: peakValue = output[i]; Chris@222: peakBin = i; Chris@222: } Chris@222: } Chris@222: Chris@222: cout << "peak value = " << peakValue << " at bin " << peakBin << endl; Chris@222: cout << "(neighbouring values are " Chris@222: << (peakBin > 0 ? output[peakBin-1] : output[bpo-1]) Chris@222: << " and " Chris@222: << (peakBin+1 < bpo ? output[peakBin+1] : output[0]) Chris@222: << ")" << endl; Chris@222: Chris@222: BOOST_CHECK_EQUAL(peakBin, expectedPeakBin); Chris@222: } Chris@222: } Chris@222: Chris@222: BOOST_AUTO_TEST_SUITE_END()