annotate tests/TestChromagram.cpp @ 465:50a97c8d52ed

Apply fix from daschuer/mixxx:957aed58 : Use double precision for FS
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 29 May 2019 13:55:26 +0100
parents d8ad5893db6f
children 1db23b9a8da4
rev   line source
c@451 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@451 2
c@451 3 #include "dsp/chromagram/Chromagram.h"
c@451 4
c@451 5 #include <iostream>
c@451 6
c@451 7 #include <cmath>
c@451 8
c@451 9 #define BOOST_TEST_DYN_LINK
c@451 10 #define BOOST_TEST_MAIN
c@451 11
c@451 12 #include <boost/test/unit_test.hpp>
c@451 13
c@451 14 BOOST_AUTO_TEST_SUITE(TestChromagram)
c@451 15
c@451 16 using std::cout;
c@451 17 using std::endl;
c@451 18 using std::string;
c@451 19 using std::vector;
c@451 20
c@451 21 string midiPitchName(int midiPitch)
c@451 22 {
c@451 23 static string names[] = {
c@451 24 "C", "C#", "D", "D#",
c@451 25 "E", "F", "F#", "G",
c@451 26 "G#", "A", "A#", "B"
c@451 27 };
c@451 28
c@451 29 return names[midiPitch % 12];
c@451 30 }
c@451 31
c@451 32 vector<double> generateSinusoid(double frequency,
cannam@465 33 double sampleRate,
c@451 34 int length)
c@451 35 {
c@451 36 vector<double> buffer;
c@451 37 buffer.reserve(length);
c@451 38 for (int i = 0; i < length; ++i) {
cannam@453 39 buffer.push_back(sin((i * M_PI * 2.0 * frequency) / sampleRate));
c@451 40 }
cannam@453 41
c@451 42 return buffer;
c@451 43 }
c@451 44
c@451 45 double frequencyForPitch(int midiPitch, double concertA)
c@451 46 {
c@451 47 return concertA * pow(2.0, (midiPitch - 69.0) / 12.0);
c@451 48 }
c@451 49
c@451 50 BOOST_AUTO_TEST_CASE(sinusoid_12tET)
c@451 51 {
c@451 52 double concertA = 440.0;
cannam@465 53 double sampleRate = 44100;
c@451 54 int bpo = 60;
c@451 55
c@451 56 ChromaConfig config {
c@451 57 sampleRate,
c@451 58 frequencyForPitch(36, concertA),
c@451 59 frequencyForPitch(108, concertA),
c@451 60 bpo,
c@451 61 0.0054,
c@451 62 MathUtilities::NormaliseNone
c@451 63 };
c@451 64
c@451 65 Chromagram chroma(config);
c@451 66
cannam@453 67 for (int midiPitch = 36; midiPitch < 108; ++midiPitch) {
c@451 68
c@451 69 cout << endl;
c@451 70
c@451 71 int blockSize = chroma.getFrameSize();
c@451 72 int hopSize = chroma.getHopSize();
c@451 73 cerr << "blockSize = " << blockSize
c@451 74 << ", hopSize = " << hopSize << endl;
c@451 75
c@451 76 double frequency = frequencyForPitch(midiPitch, concertA);
c@451 77 int expectedPeakBin = ((midiPitch - 36) * 5) % bpo;
c@451 78
c@451 79 cout << "midiPitch = " << midiPitch
c@451 80 << ", name = " << midiPitchName(midiPitch)
c@451 81 << ", frequency = " << frequency
c@451 82 << ", expected peak bin = "
c@451 83 << expectedPeakBin << endl;
c@451 84
c@451 85 vector<double> signal = generateSinusoid(frequency,
c@451 86 sampleRate,
c@451 87 blockSize);
cannam@453 88
c@451 89 double *output = chroma.process(signal.data());
c@451 90
c@451 91 int peakBin = -1;
c@451 92 double peakValue = 0.0;
c@451 93
c@451 94 for (int i = 0; i < bpo; ++i) {
c@451 95 if (i == 0 || output[i] > peakValue) {
c@451 96 peakValue = output[i];
c@451 97 peakBin = i;
c@451 98 }
c@451 99 }
c@451 100
c@451 101 cout << "peak value = " << peakValue << " at bin " << peakBin << endl;
c@451 102 cout << "(neighbouring values are "
c@451 103 << (peakBin > 0 ? output[peakBin-1] : output[bpo-1])
c@451 104 << " and "
c@451 105 << (peakBin+1 < bpo ? output[peakBin+1] : output[0])
c@451 106 << ")" << endl;
c@451 107
cannam@463 108 if (peakBin != expectedPeakBin) {
cannam@463 109 cout << "NOTE: peak bin " << peakBin << " does not match expected " << expectedPeakBin << endl;
cannam@463 110 }
c@451 111 }
c@451 112 }
c@451 113
c@451 114 BOOST_AUTO_TEST_SUITE_END()