comparison constant-q-cpp/vamp/CQChromaVamp.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-2014 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 "CQChromaVamp.h"
33
34 #include "cq/Chromagram.h"
35
36 #include <algorithm>
37
38 using std::string;
39 using std::vector;
40 using std::cerr;
41 using std::endl;
42
43 static const int defaultLowestOctave = 0;
44 static const int defaultOctaveCount = 7;
45 static const int defaultBPO = 36;
46 static const float defaultTuningFrequency = 440.f;
47
48 CQChromaVamp::CQChromaVamp(float inputSampleRate) :
49 Vamp::Plugin(inputSampleRate),
50 m_lowestOctave(defaultLowestOctave),
51 m_octaveCount(defaultOctaveCount),
52 m_tuningFrequency(defaultTuningFrequency),
53 m_bpo(defaultBPO),
54 m_chroma(0),
55 m_haveStartTime(false),
56 m_columnCount(0)
57 {
58 }
59
60 CQChromaVamp::~CQChromaVamp()
61 {
62 delete m_chroma;
63 }
64
65 string
66 CQChromaVamp::getIdentifier() const
67 {
68 return "cqchromavamp";
69 }
70
71 string
72 CQChromaVamp::getName() const
73 {
74 return "CQ Chromagram";
75 }
76
77 string
78 CQChromaVamp::getDescription() const
79 {
80 return "Extract a Constant-Q spectrogram with constant ratio of centre frequency to resolution from the audio, then wrap it around into a single-octave chromagram.";
81 }
82
83 string
84 CQChromaVamp::getMaker() const
85 {
86 return "Queen Mary, University of London";
87 }
88
89 int
90 CQChromaVamp::getPluginVersion() const
91 {
92 return 2;
93 }
94
95 string
96 CQChromaVamp::getCopyright() const
97 {
98 return "Plugin by Chris Cannam. Method by Christian Schörkhuber and Anssi Klapuri. Copyright (c) 2015 QMUL. BSD/MIT licence.";
99 }
100
101 CQChromaVamp::ParameterList
102 CQChromaVamp::getParameterDescriptors() const
103 {
104 ParameterList list;
105
106 ParameterDescriptor desc;
107
108 desc.identifier = "lowestoct";
109 desc.name = "Lowest Contributing Octave";
110 desc.unit = "";
111 desc.description = "Octave number of the lowest octave to include in the chromagram. Octave numbering is ASA standard, with -1 as the first octave in the MIDI range and middle-C being C4. The octave starts at C.";
112 desc.minValue = -1;
113 desc.maxValue = 12;
114 desc.defaultValue = defaultLowestOctave;
115 desc.isQuantized = true;
116 desc.quantizeStep = 1;
117 list.push_back(desc);
118
119 desc.identifier = "octaves";
120 desc.name = "Contributing Octave Count";
121 desc.unit = "octaves";
122 desc.description = "Number of octaves to use when generating the Constant-Q transform. All octaves are wrapped around and summed to produce a single octave chromagram as output.";
123 desc.minValue = 1;
124 desc.maxValue = 12;
125 desc.defaultValue = defaultOctaveCount;
126 desc.isQuantized = true;
127 desc.quantizeStep = 1;
128 list.push_back(desc);
129
130 desc.identifier = "tuning";
131 desc.name = "Tuning Frequency";
132 desc.unit = "Hz";
133 desc.description = "Frequency of concert A";
134 desc.minValue = 360;
135 desc.maxValue = 500;
136 desc.defaultValue = defaultTuningFrequency;
137 desc.isQuantized = false;
138 list.push_back(desc);
139
140 desc.identifier = "bpo";
141 desc.name = "Bins per Octave";
142 desc.unit = "bins";
143 desc.description = "Number of constant-Q transform bins per octave";
144 desc.minValue = 2;
145 desc.maxValue = 480;
146 desc.defaultValue = defaultBPO;
147 desc.isQuantized = true;
148 desc.quantizeStep = 1;
149 list.push_back(desc);
150
151 return list;
152 }
153
154 float
155 CQChromaVamp::getParameter(std::string param) const
156 {
157 if (param == "lowestoct") {
158 return m_lowestOctave;
159 }
160 if (param == "octaves") {
161 return m_octaveCount;
162 }
163 if (param == "tuning") {
164 return m_tuningFrequency;
165 }
166 if (param == "bpo") {
167 return m_bpo;
168 }
169 std::cerr << "WARNING: CQChromaVamp::getParameter: unknown parameter \""
170 << param << "\"" << std::endl;
171 return 0.0;
172 }
173
174 void
175 CQChromaVamp::setParameter(std::string param, float value)
176 {
177 if (param == "lowestoct") {
178 m_lowestOctave = int(value + 0.5f);
179 } else if (param == "octaves") {
180 m_octaveCount = int(value + 0.5f);
181 } else if (param == "tuning") {
182 m_tuningFrequency = value;
183 } else if (param == "bpo") {
184 m_bpo = int(value + 0.5f);
185 } else {
186 std::cerr << "WARNING: CQChromaVamp::setParameter: unknown parameter \""
187 << param << "\"" << std::endl;
188 }
189 }
190
191 bool
192 CQChromaVamp::initialise(size_t channels, size_t stepSize, size_t blockSize)
193 {
194 if (m_chroma) {
195 delete m_chroma;
196 m_chroma = 0;
197 }
198
199 if (channels < getMinChannelCount() ||
200 channels > getMaxChannelCount()) return false;
201
202 m_stepSize = stepSize;
203 m_blockSize = blockSize;
204
205 reset();
206
207 if (!m_chroma || !m_chroma->isValid()) {
208 cerr << "CQVamp::initialise: Constant-Q parameters not valid! Not initialising" << endl;
209 return false;
210 }
211
212 return true;
213 }
214
215 void
216 CQChromaVamp::reset()
217 {
218 delete m_chroma;
219 Chromagram::Parameters p(m_inputSampleRate);
220 p.lowestOctave = m_lowestOctave;
221 p.octaveCount = m_octaveCount;
222 p.binsPerOctave = m_bpo;
223 p.tuningFrequency = m_tuningFrequency;
224
225 m_chroma = new Chromagram(p);
226
227 m_haveStartTime = false;
228 m_startTime = Vamp::RealTime::zeroTime;
229 m_columnCount = 0;
230 }
231
232 size_t
233 CQChromaVamp::getPreferredStepSize() const
234 {
235 return 0;
236 }
237
238 size_t
239 CQChromaVamp::getPreferredBlockSize() const
240 {
241 return 0;
242 }
243
244 CQChromaVamp::OutputList
245 CQChromaVamp::getOutputDescriptors() const
246 {
247 OutputList list;
248
249 OutputDescriptor d;
250 d.identifier = "chromagram";
251 d.name = "Chromagram";
252 d.unit = "";
253 d.description = "Chromagram obtained from output of constant-Q transform, folding over each process block into a single-octave vector";
254 d.hasFixedBinCount = true;
255 d.binCount = m_bpo;
256
257 if (m_chroma) {
258 for (int i = 0; i < (int)d.binCount; ++i) {
259 d.binNames.push_back(m_chroma->getBinName(i));
260 }
261 }
262
263 d.hasKnownExtents = false;
264 d.isQuantized = false;
265 d.sampleType = OutputDescriptor::FixedSampleRate;
266 d.sampleRate = m_inputSampleRate / (m_chroma ? m_chroma->getColumnHop() : 256);
267 list.push_back(d);
268
269 return list;
270 }
271
272 CQChromaVamp::FeatureSet
273 CQChromaVamp::process(const float *const *inputBuffers,
274 Vamp::RealTime timestamp)
275 {
276 if (!m_chroma) {
277 cerr << "ERROR: CQChromaVamp::process: "
278 << "Plugin has not been initialised"
279 << endl;
280 return FeatureSet();
281 }
282
283 if (!m_haveStartTime) {
284 m_startTime = timestamp;
285 m_haveStartTime = true;
286 }
287
288 vector<double> data;
289 for (int i = 0; i < m_blockSize; ++i) data.push_back(inputBuffers[0][i]);
290
291 vector<vector<double> > chromaout = m_chroma->process(data);
292 return convertToFeatures(chromaout);
293 }
294
295 CQChromaVamp::FeatureSet
296 CQChromaVamp::getRemainingFeatures()
297 {
298 vector<vector<double> > chromaout = m_chroma->getRemainingOutput();
299 return convertToFeatures(chromaout);
300 }
301
302 CQChromaVamp::FeatureSet
303 CQChromaVamp::convertToFeatures(const vector<vector<double> > &chromaout)
304 {
305 FeatureSet returnFeatures;
306
307 int width = chromaout.size();
308
309 for (int i = 0; i < width; ++i) {
310
311 vector<float> column(chromaout[i].begin(), chromaout[i].end());
312
313 Feature feature;
314 feature.hasTimestamp = true;
315 feature.timestamp = m_startTime + Vamp::RealTime::frame2RealTime
316 (m_columnCount * m_chroma->getColumnHop() - m_chroma->getLatency(),
317 m_inputSampleRate);
318 feature.values = column;
319 feature.label = "";
320
321 if (feature.timestamp >= m_startTime) {
322 returnFeatures[0].push_back(feature);
323 }
324
325 ++m_columnCount;
326 }
327
328 return returnFeatures;
329 }
330