To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

The primary repository for this project is hosted at https://github.com/cannam/constant-q-cpp/ .
This repository is a read-only copy which is updated automatically every hour.

Statistics Download as Zip
| Branch: | Revision:

root / vamp / CQChromaVamp.cpp

History | View | Annotate | Download (8.71 KB)

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