comparison tests/TestChromagram.cpp @ 451:3f913390bcf2

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