annotate vamp/CQChromaVamp.cpp @ 196:da283326bcd3 tip master

Update plugin versions in RDF
author Chris Cannam <cannam@all-day-breakfast.com>
date Fri, 28 Feb 2020 09:43:02 +0000
parents 8e64d3da52f5
children
rev   line source
c@110 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
c@110 2 /*
c@110 3 Constant-Q library
c@110 4 Copyright (c) 2013-2014 Queen Mary, University of London
c@110 5
c@110 6 Permission is hereby granted, free of charge, to any person
c@110 7 obtaining a copy of this software and associated documentation
c@110 8 files (the "Software"), to deal in the Software without
c@110 9 restriction, including without limitation the rights to use, copy,
c@110 10 modify, merge, publish, distribute, sublicense, and/or sell copies
c@110 11 of the Software, and to permit persons to whom the Software is
c@110 12 furnished to do so, subject to the following conditions:
c@110 13
c@110 14 The above copyright notice and this permission notice shall be
c@110 15 included in all copies or substantial portions of the Software.
c@110 16
c@110 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
c@110 18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
c@110 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
c@110 20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
c@110 21 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
c@110 22 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
c@110 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
c@110 24
c@110 25 Except as contained in this notice, the names of the Centre for
c@110 26 Digital Music; Queen Mary, University of London; and Chris Cannam
c@110 27 shall not be used in advertising or otherwise to promote the sale,
c@110 28 use or other dealings in this Software without prior written
c@110 29 authorization.
c@110 30 */
c@110 31
c@110 32 #include "CQChromaVamp.h"
c@110 33
c@170 34 #include "cq/Chromagram.h"
c@110 35
c@110 36 #include <algorithm>
c@110 37
c@110 38 using std::string;
c@110 39 using std::vector;
c@110 40 using std::cerr;
c@110 41 using std::endl;
c@110 42
c@113 43 static const int defaultLowestOctave = 0;
c@113 44 static const int defaultOctaveCount = 7;
c@110 45 static const int defaultBPO = 36;
c@110 46 static const float defaultTuningFrequency = 440.f;
c@110 47
c@110 48 CQChromaVamp::CQChromaVamp(float inputSampleRate) :
c@110 49 Vamp::Plugin(inputSampleRate),
c@110 50 m_lowestOctave(defaultLowestOctave),
c@110 51 m_octaveCount(defaultOctaveCount),
c@110 52 m_tuningFrequency(defaultTuningFrequency),
c@110 53 m_bpo(defaultBPO),
c@170 54 m_chroma(0),
c@110 55 m_haveStartTime(false),
c@110 56 m_columnCount(0)
c@110 57 {
c@110 58 }
c@110 59
c@110 60 CQChromaVamp::~CQChromaVamp()
c@110 61 {
c@170 62 delete m_chroma;
c@110 63 }
c@110 64
c@110 65 string
c@110 66 CQChromaVamp::getIdentifier() const
c@110 67 {
c@110 68 return "cqchromavamp";
c@110 69 }
c@110 70
c@110 71 string
c@110 72 CQChromaVamp::getName() const
c@110 73 {
c@169 74 return "CQ Chromagram";
c@110 75 }
c@110 76
c@110 77 string
c@110 78 CQChromaVamp::getDescription() const
c@110 79 {
c@155 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.";
c@110 81 }
c@110 82
c@110 83 string
c@110 84 CQChromaVamp::getMaker() const
c@110 85 {
c@110 86 return "Queen Mary, University of London";
c@110 87 }
c@110 88
c@110 89 int
c@110 90 CQChromaVamp::getPluginVersion() const
c@110 91 {
c@182 92 return 2;
c@110 93 }
c@110 94
c@110 95 string
c@110 96 CQChromaVamp::getCopyright() const
c@110 97 {
c@182 98 return "Plugin by Chris Cannam. Method by Christian Schörkhuber and Anssi Klapuri. Copyright (c) 2015 QMUL. BSD/MIT licence.";
c@110 99 }
c@110 100
c@110 101 CQChromaVamp::ParameterList
c@110 102 CQChromaVamp::getParameterDescriptors() const
c@110 103 {
c@110 104 ParameterList list;
c@110 105
c@110 106 ParameterDescriptor desc;
c@110 107
c@110 108 desc.identifier = "lowestoct";
c@110 109 desc.name = "Lowest Contributing Octave";
c@110 110 desc.unit = "";
c@110 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.";
c@110 112 desc.minValue = -1;
c@110 113 desc.maxValue = 12;
c@110 114 desc.defaultValue = defaultLowestOctave;
c@110 115 desc.isQuantized = true;
c@110 116 desc.quantizeStep = 1;
c@110 117 list.push_back(desc);
c@110 118
c@110 119 desc.identifier = "octaves";
c@110 120 desc.name = "Contributing Octave Count";
c@110 121 desc.unit = "octaves";
c@110 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.";
c@110 123 desc.minValue = 1;
c@110 124 desc.maxValue = 12;
c@110 125 desc.defaultValue = defaultOctaveCount;
c@110 126 desc.isQuantized = true;
c@110 127 desc.quantizeStep = 1;
c@110 128 list.push_back(desc);
c@110 129
c@110 130 desc.identifier = "tuning";
c@110 131 desc.name = "Tuning Frequency";
c@110 132 desc.unit = "Hz";
c@110 133 desc.description = "Frequency of concert A";
c@110 134 desc.minValue = 360;
c@110 135 desc.maxValue = 500;
c@151 136 desc.defaultValue = defaultTuningFrequency;
c@110 137 desc.isQuantized = false;
c@110 138 list.push_back(desc);
c@110 139
c@110 140 desc.identifier = "bpo";
c@110 141 desc.name = "Bins per Octave";
c@110 142 desc.unit = "bins";
c@110 143 desc.description = "Number of constant-Q transform bins per octave";
c@110 144 desc.minValue = 2;
c@110 145 desc.maxValue = 480;
c@110 146 desc.defaultValue = defaultBPO;
c@110 147 desc.isQuantized = true;
c@110 148 desc.quantizeStep = 1;
c@110 149 list.push_back(desc);
c@110 150
c@110 151 return list;
c@110 152 }
c@110 153
c@110 154 float
c@110 155 CQChromaVamp::getParameter(std::string param) const
c@110 156 {
c@110 157 if (param == "lowestoct") {
c@110 158 return m_lowestOctave;
c@110 159 }
c@110 160 if (param == "octaves") {
c@110 161 return m_octaveCount;
c@110 162 }
c@110 163 if (param == "tuning") {
c@110 164 return m_tuningFrequency;
c@110 165 }
c@110 166 if (param == "bpo") {
c@110 167 return m_bpo;
c@110 168 }
c@110 169 std::cerr << "WARNING: CQChromaVamp::getParameter: unknown parameter \""
c@110 170 << param << "\"" << std::endl;
c@110 171 return 0.0;
c@110 172 }
c@110 173
c@110 174 void
c@110 175 CQChromaVamp::setParameter(std::string param, float value)
c@110 176 {
c@110 177 if (param == "lowestoct") {
c@164 178 m_lowestOctave = int(value + 0.5f);
c@110 179 } else if (param == "octaves") {
c@164 180 m_octaveCount = int(value + 0.5f);
c@110 181 } else if (param == "tuning") {
c@110 182 m_tuningFrequency = value;
c@110 183 } else if (param == "bpo") {
c@164 184 m_bpo = int(value + 0.5f);
c@110 185 } else {
c@110 186 std::cerr << "WARNING: CQChromaVamp::setParameter: unknown parameter \""
c@110 187 << param << "\"" << std::endl;
c@110 188 }
c@110 189 }
c@110 190
c@110 191 bool
c@110 192 CQChromaVamp::initialise(size_t channels, size_t stepSize, size_t blockSize)
c@110 193 {
c@170 194 if (m_chroma) {
c@170 195 delete m_chroma;
c@170 196 m_chroma = 0;
c@110 197 }
c@110 198
c@110 199 if (channels < getMinChannelCount() ||
c@110 200 channels > getMaxChannelCount()) return false;
c@110 201
c@110 202 m_stepSize = stepSize;
c@110 203 m_blockSize = blockSize;
c@110 204
c@147 205 reset();
c@147 206
c@170 207 if (!m_chroma || !m_chroma->isValid()) {
c@147 208 cerr << "CQVamp::initialise: Constant-Q parameters not valid! Not initialising" << endl;
c@147 209 return false;
c@147 210 }
c@110 211
c@110 212 return true;
c@110 213 }
c@110 214
c@110 215 void
c@110 216 CQChromaVamp::reset()
c@110 217 {
c@170 218 delete m_chroma;
c@170 219 Chromagram::Parameters p(m_inputSampleRate);
c@170 220 p.lowestOctave = m_lowestOctave;
c@171 221 p.octaveCount = m_octaveCount;
c@171 222 p.binsPerOctave = m_bpo;
c@170 223 p.tuningFrequency = m_tuningFrequency;
c@170 224
c@170 225 m_chroma = new Chromagram(p);
c@147 226
c@110 227 m_haveStartTime = false;
c@147 228 m_startTime = Vamp::RealTime::zeroTime;
c@110 229 m_columnCount = 0;
c@110 230 }
c@110 231
c@110 232 size_t
c@110 233 CQChromaVamp::getPreferredStepSize() const
c@110 234 {
c@110 235 return 0;
c@110 236 }
c@110 237
c@110 238 size_t
c@110 239 CQChromaVamp::getPreferredBlockSize() const
c@110 240 {
c@110 241 return 0;
c@110 242 }
c@110 243
c@110 244 CQChromaVamp::OutputList
c@110 245 CQChromaVamp::getOutputDescriptors() const
c@110 246 {
c@110 247 OutputList list;
c@110 248
c@110 249 OutputDescriptor d;
c@110 250 d.identifier = "chromagram";
c@110 251 d.name = "Chromagram";
c@110 252 d.unit = "";
c@110 253 d.description = "Chromagram obtained from output of constant-Q transform, folding over each process block into a single-octave vector";
c@110 254 d.hasFixedBinCount = true;
c@110 255 d.binCount = m_bpo;
c@110 256
c@170 257 if (m_chroma) {
c@110 258 for (int i = 0; i < (int)d.binCount; ++i) {
c@170 259 d.binNames.push_back(m_chroma->getBinName(i));
c@110 260 }
c@110 261 }
c@110 262
c@110 263 d.hasKnownExtents = false;
c@110 264 d.isQuantized = false;
c@110 265 d.sampleType = OutputDescriptor::FixedSampleRate;
c@170 266 d.sampleRate = m_inputSampleRate / (m_chroma ? m_chroma->getColumnHop() : 256);
c@110 267 list.push_back(d);
c@110 268
c@110 269 return list;
c@110 270 }
c@110 271
c@110 272 CQChromaVamp::FeatureSet
c@110 273 CQChromaVamp::process(const float *const *inputBuffers,
c@110 274 Vamp::RealTime timestamp)
c@110 275 {
c@170 276 if (!m_chroma) {
c@110 277 cerr << "ERROR: CQChromaVamp::process: "
c@110 278 << "Plugin has not been initialised"
c@110 279 << endl;
c@110 280 return FeatureSet();
c@110 281 }
c@110 282
c@110 283 if (!m_haveStartTime) {
c@110 284 m_startTime = timestamp;
c@110 285 m_haveStartTime = true;
c@110 286 }
c@110 287
c@110 288 vector<double> data;
c@110 289 for (int i = 0; i < m_blockSize; ++i) data.push_back(inputBuffers[0][i]);
c@110 290
c@170 291 vector<vector<double> > chromaout = m_chroma->process(data);
c@170 292 return convertToFeatures(chromaout);
c@110 293 }
c@110 294
c@110 295 CQChromaVamp::FeatureSet
c@110 296 CQChromaVamp::getRemainingFeatures()
c@110 297 {
c@170 298 vector<vector<double> > chromaout = m_chroma->getRemainingOutput();
c@170 299 return convertToFeatures(chromaout);
c@110 300 }
c@110 301
c@110 302 CQChromaVamp::FeatureSet
c@170 303 CQChromaVamp::convertToFeatures(const vector<vector<double> > &chromaout)
c@110 304 {
c@110 305 FeatureSet returnFeatures;
c@110 306
c@170 307 int width = chromaout.size();
c@110 308
c@110 309 for (int i = 0; i < width; ++i) {
c@110 310
c@170 311 vector<float> column(chromaout[i].begin(), chromaout[i].end());
c@110 312
c@110 313 Feature feature;
c@110 314 feature.hasTimestamp = true;
c@110 315 feature.timestamp = m_startTime + Vamp::RealTime::frame2RealTime
c@170 316 (m_columnCount * m_chroma->getColumnHop() - m_chroma->getLatency(),
c@110 317 m_inputSampleRate);
c@110 318 feature.values = column;
c@110 319 feature.label = "";
c@110 320
c@110 321 if (feature.timestamp >= m_startTime) {
c@110 322 returnFeatures[0].push_back(feature);
c@110 323 }
c@110 324
c@110 325 ++m_columnCount;
c@110 326 }
c@110 327
c@110 328 return returnFeatures;
c@110 329 }
c@110 330