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