Mercurial > hg > silvet
comparison constant-q-cpp/src/Chromagram.cpp @ 366:5d0a2ebb4d17
Bring dependent libraries in to repo
author | Chris Cannam |
---|---|
date | Fri, 24 Jun 2016 14:47:45 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
365:112766f4c34b | 366:5d0a2ebb4d17 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 /* | |
3 Constant-Q library | |
4 Copyright (c) 2013-2015 Queen Mary, University of London | |
5 | |
6 Permission is hereby granted, free of charge, to any person | |
7 obtaining a copy of this software and associated documentation | |
8 files (the "Software"), to deal in the Software without | |
9 restriction, including without limitation the rights to use, copy, | |
10 modify, merge, publish, distribute, sublicense, and/or sell copies | |
11 of the Software, and to permit persons to whom the Software is | |
12 furnished to do so, subject to the following conditions: | |
13 | |
14 The above copyright notice and this permission notice shall be | |
15 included in all copies or substantial portions of the Software. | |
16 | |
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
22 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
24 | |
25 Except as contained in this notice, the names of the Centre for | |
26 Digital Music; Queen Mary, University of London; and Chris Cannam | |
27 shall not be used in advertising or otherwise to promote the sale, | |
28 use or other dealings in this Software without prior written | |
29 authorization. | |
30 */ | |
31 | |
32 #include "Chromagram.h" | |
33 #include "CQSpectrogram.h" | |
34 #include "Pitch.h" | |
35 | |
36 #include <cstdio> | |
37 | |
38 using namespace std; | |
39 | |
40 Chromagram::Chromagram(Parameters params) : | |
41 m_params(params), | |
42 m_cq(0) | |
43 { | |
44 int highestOctave = m_params.lowestOctave + m_params.octaveCount - 1; | |
45 | |
46 int midiPitchLimit = (1 + highestOctave) * 12 + 12; // C just beyond top | |
47 double midiPitchLimitFreq = Pitch::getFrequencyForPitch | |
48 (midiPitchLimit, 0, m_params.tuningFrequency); | |
49 | |
50 // Max frequency is frequency of the MIDI pitch just beyond the | |
51 // top octave range (midiPitchLimit) minus one bin, then minus | |
52 // floor(bins per semitone / 2) | |
53 int bps = m_params.binsPerOctave / 12; | |
54 m_maxFrequency = midiPitchLimitFreq / | |
55 pow(2.0, (1.0 + floor(bps/2)) / m_params.binsPerOctave); | |
56 | |
57 // Min frequency is frequency of midiPitchLimit lowered by the | |
58 // appropriate number of octaveCount. | |
59 m_minFrequency = midiPitchLimitFreq / | |
60 pow(2.0, m_params.octaveCount + 1); | |
61 | |
62 CQParameters p | |
63 (params.sampleRate, m_minFrequency, m_maxFrequency, params.binsPerOctave); | |
64 | |
65 p.q = params.q; | |
66 p.atomHopFactor = params.atomHopFactor; | |
67 p.threshold = params.threshold; | |
68 p.window = params.window; | |
69 | |
70 m_cq = new CQSpectrogram(p, CQSpectrogram::InterpolateLinear); | |
71 } | |
72 | |
73 Chromagram::~Chromagram() | |
74 { | |
75 delete m_cq; | |
76 } | |
77 | |
78 bool | |
79 Chromagram::isValid() const | |
80 { | |
81 return m_cq->isValid(); | |
82 } | |
83 | |
84 int | |
85 Chromagram::getColumnHop() const | |
86 { | |
87 return m_cq->getColumnHop(); | |
88 } | |
89 | |
90 int | |
91 Chromagram::getLatency() const | |
92 { | |
93 return m_cq->getLatency(); | |
94 } | |
95 | |
96 string | |
97 Chromagram::getBinName(int bin) const | |
98 { | |
99 static const char *names[] = { | |
100 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" | |
101 }; | |
102 | |
103 float freq = m_cq->getBinFrequency(m_params.binsPerOctave - bin - 1); | |
104 int note = Pitch::getPitchForFrequency(freq, 0, m_params.tuningFrequency); | |
105 float nearestFreq = | |
106 Pitch::getFrequencyForPitch(note, 0, m_params.tuningFrequency); | |
107 | |
108 char name[40]; | |
109 sprintf(name, "%d", bin); | |
110 if (fabs(freq - nearestFreq) < 0.01) { | |
111 return (name + std::string(" ") + names[note % 12]); | |
112 } else { | |
113 return (name); | |
114 } | |
115 } | |
116 | |
117 CQBase::RealBlock | |
118 Chromagram::process(const CQBase::RealSequence &data) | |
119 { | |
120 return convert(m_cq->process(data)); | |
121 } | |
122 | |
123 CQBase::RealBlock | |
124 Chromagram::getRemainingOutput() | |
125 { | |
126 return convert(m_cq->getRemainingOutput()); | |
127 } | |
128 | |
129 CQBase::RealBlock | |
130 Chromagram::convert(const CQBase::RealBlock &cqout) | |
131 { | |
132 CQBase::RealBlock chroma; | |
133 | |
134 int width = cqout.size(); | |
135 | |
136 for (int i = 0; i < width; ++i) { | |
137 | |
138 CQBase::RealSequence column(m_params.binsPerOctave, 0.); | |
139 | |
140 // fold and invert to put low frequencies at the start | |
141 | |
142 int thisHeight = cqout[i].size(); | |
143 | |
144 for (int j = 0; j < thisHeight; ++j) { | |
145 column[m_params.binsPerOctave - (j % m_params.binsPerOctave) - 1] | |
146 += cqout[i][j]; | |
147 } | |
148 | |
149 chroma.push_back(column); | |
150 } | |
151 | |
152 return chroma; | |
153 } | |
154 |