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

Statistics Download as Zip
| Branch: | Revision:

root / onsetsdsplugin.cpp @ 0:635e8745ccc9

History | View | Annotate | Download (7.4 KB)

1
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2
/*
3
    Vamp feature extraction plugin using the OnsetsDS onset detector.
4
    This file copyright (c) 2008 Chris Cannam.
5

6
    OnsetsDS - real time musical onset detection library.
7
    Copyright (c) 2007 Dan Stowell. All rights reserved.
8

9
    This program is free software; you can redistribute it and/or modify
10
    it under the terms of the GNU General Public License as published by
11
    the Free Software Foundation; either version 2 of the License, or
12
    (at your option) any later version.
13

14
    This program is distributed in the hope that it will be useful,
15
    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
    GNU General Public License for more details.
18

19
    You should have received a copy of the GNU General Public License
20
    along with this program; if not, write to the Free Software
21
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
*/
23

    
24
#include "onsetsdsplugin.h"
25
#include <vamp-sdk/PluginAdapter.h>
26

    
27
using std::string;
28
using std::vector;
29
using std::cerr;
30
using std::endl;
31

    
32

    
33
OnsetsDSPlugin::OnsetsDSPlugin(float inputSampleRate) :
34
    Vamp::Plugin(inputSampleRate),
35
    m_ods(0),
36
    m_odsdata(0),
37
    m_dfType(ODS_ODF_RCOMPLEX),
38
    m_medspan(11),
39
    m_stepSize(512),
40
    m_fftSize(1024)
41
{
42
}
43

    
44
OnsetsDSPlugin::~OnsetsDSPlugin()
45
{
46
    delete[] m_odsdata;
47
    delete m_ods;
48
}
49

    
50
string
51
OnsetsDSPlugin::getIdentifier() const
52
{
53
    return "onsetsds";
54
}
55

    
56
string
57
OnsetsDSPlugin::getName() const
58
{
59
    return "OnsetsDS Onset Detector";
60
}
61

    
62
string
63
OnsetsDSPlugin::getDescription() const
64
{
65
    return "Detect note onsets";
66
}
67

    
68
string
69
OnsetsDSPlugin::getMaker() const
70
{
71
    return "Dan Stowell";
72
}
73

    
74
int
75
OnsetsDSPlugin::getPluginVersion() const
76
{
77
    return 1;
78
}
79

    
80
string
81
OnsetsDSPlugin::getCopyright() const
82
{
83
    return "Copyright (c) 2007-2008 Dan Stowell";
84
}
85

    
86
OnsetsDSPlugin::ParameterList
87
OnsetsDSPlugin::getParameterDescriptors() const
88
{
89
    ParameterList list;
90

    
91
    ParameterDescriptor desc;
92
    desc.identifier = "dftype";
93
    desc.name = "Onset detection function";
94
    desc.description = "Method used to calculate the onset detection function";
95
    desc.minValue = 0;
96
    desc.maxValue = 6;
97
    desc.defaultValue = 3;
98
    desc.isQuantized = true;
99
    desc.quantizeStep = 1;
100
    desc.valueNames.push_back("Power");
101
    desc.valueNames.push_back("Sum of magnitudes");
102
    desc.valueNames.push_back("Complex-domain deviation");
103
    desc.valueNames.push_back("Rectified complex-domain deviation");
104
    desc.valueNames.push_back("Phase deviation");
105
    desc.valueNames.push_back("Weighted phase deviation");
106
    desc.valueNames.push_back("Modified Kullback-Liebler deviation");
107
    list.push_back(desc);
108

    
109
    desc.identifier = "medspan";
110
    desc.name = "Median frame span";
111
    desc.description = "Number of past frames used in median calculation";
112
    desc.minValue = 5;
113
    desc.maxValue = 21;
114
    desc.defaultValue = 11;
115
    desc.isQuantized = true;
116
    desc.quantizeStep = 2;
117
    desc.valueNames.clear();
118
    list.push_back(desc);
119

    
120
    return list;
121
}
122

    
123
float
124
OnsetsDSPlugin::getParameter(std::string name) const
125
{
126
    if (name == "dftype") {
127
        switch (m_dfType) {
128
        case ODS_ODF_POWER:    return 0;
129
        case ODS_ODF_MAGSUM:   return 1;
130
        case ODS_ODF_COMPLEX:  return 2;
131
        case ODS_ODF_RCOMPLEX: return 3;
132
        case ODS_ODF_PHASE:    return 4;
133
        case ODS_ODF_WPHASE:   return 5;
134
        case ODS_ODF_MKL:      return 6;
135
        }
136
    } else if (name == "medspan") {
137
        return m_medspan;
138
    }
139
    return 0.0;
140
}
141

    
142
void
143
OnsetsDSPlugin::setParameter(std::string name, float value)
144
{
145
    if (name == "dftype") {
146
        onsetsds_odf_types dfType = m_dfType;
147
        switch (lrintf(value)) {
148
        case 0: dfType = ODS_ODF_POWER; break;
149
        case 1: dfType = ODS_ODF_MAGSUM; break;
150
        case 2: dfType = ODS_ODF_COMPLEX; break;
151
        case 3: dfType = ODS_ODF_RCOMPLEX; break;
152
        case 4: dfType = ODS_ODF_PHASE; break;
153
        case 5: dfType = ODS_ODF_WPHASE; break;
154
        case 6: dfType = ODS_ODF_MKL; break;
155
        }
156
        if (dfType == m_dfType) return;
157
        m_dfType = dfType;
158
    } else if (name == "medspan") {
159
        m_medspan = lrintf(value);
160
    }
161
}
162

    
163
bool
164
OnsetsDSPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
165
{
166
    if (channels < getMinChannelCount() ||
167
        channels > getMaxChannelCount()) {
168
        std::cerr << "OnsetsDSPlugin::initialise: Unsupported channel count: "
169
                  << channels << std::endl;
170
        return false;
171
    }
172

    
173
    if (stepSize != getPreferredStepSize()) {
174
        std::cerr << "WARNING: OnsetsDSPlugin::initialise: Using unusual step size: "
175
                  << stepSize << " (wanted " << (getPreferredStepSize()) << ")" << std::endl;
176
    }
177

    
178
    if (blockSize != getPreferredBlockSize()) {
179
        std::cerr << "WARNING: OnsetsDSPlugin::initialise: Using unusual block size: "
180
                  << blockSize << " (wanted " << (getPreferredBlockSize()) << ")" << std::endl;
181
    }
182

    
183
    m_stepSize = stepSize;
184
    m_fftSize = blockSize;
185

    
186
    delete[] m_odsdata;
187
    delete m_ods;
188

    
189
    m_odsdata = new float[onsetsds_memneeded(m_dfType, m_fftSize, m_medspan)];
190
    m_ods = new OnsetsDS;
191
    memset(m_ods, 0, sizeof(OnsetsDS));
192
    onsetsds_init(m_ods, m_odsdata, ODS_FFT_FFTW3_R2C, m_dfType, m_fftSize,
193
                  m_medspan, m_inputSampleRate);
194

    
195
    return true;
196
}
197

    
198
void
199
OnsetsDSPlugin::reset()
200
{
201
    if (!m_ods) {
202
        std::cerr << "ERROR: OnsetsDSPlugin::reset: Plugin has not been initialised" << std::endl;
203
        return;
204
    }
205
    onsetsds_init(m_ods, m_odsdata, ODS_FFT_FFTW3_R2C, m_dfType, m_fftSize,
206
                  m_medspan, m_inputSampleRate);
207
}
208

    
209
size_t
210
OnsetsDSPlugin::getPreferredStepSize() const
211
{
212
    return 512;
213
}
214

    
215
size_t
216
OnsetsDSPlugin::getPreferredBlockSize() const
217
{
218
    return 1024;
219
}
220

    
221
OnsetsDSPlugin::OutputList
222
OnsetsDSPlugin::getOutputDescriptors() const
223
{
224
    OutputList list;
225

    
226
    OutputDescriptor onsets;
227
    onsets.identifier = "onsets";
228
    onsets.name = "Note Onsets";
229
    onsets.description = "Note onset positions";
230
    onsets.unit = "";
231
    onsets.hasFixedBinCount = true;
232
    onsets.binCount = 0;
233
    onsets.sampleType = OutputDescriptor::VariableSampleRate;
234
    onsets.sampleRate = (m_inputSampleRate / m_stepSize);
235

    
236
    list.push_back(onsets);
237

    
238
    return list;
239
}
240

    
241
OnsetsDSPlugin::FeatureSet
242
OnsetsDSPlugin::process(const float *const *inputBuffers,
243
                       Vamp::RealTime timestamp)
244
{
245
    if (!m_ods) {
246
        cerr << "ERROR: OnsetsDSPlugin::process: Plugin has not been initialised"
247
             << endl;
248
        return FeatureSet();
249
    }
250

    
251
    // We can const_cast because we happen to know onsetsds_process
252
    // does not modify this buffer
253
    bool result = onsetsds_process(m_ods, const_cast<float *>(inputBuffers[0]));
254

    
255
    FeatureSet returnFeatures;
256

    
257
    if (result) {
258
        Feature feature;
259
        feature.hasTimestamp = true;
260
        feature.timestamp = timestamp;
261
        returnFeatures[0].push_back(feature); // onsets are output 0
262
    }
263

    
264
    return returnFeatures;
265
}
266

    
267
OnsetsDSPlugin::FeatureSet
268
OnsetsDSPlugin::getRemainingFeatures()
269
{
270
    return FeatureSet();
271
}
272

    
273

    
274
static Vamp::PluginAdapter<OnsetsDSPlugin> adapter;
275

    
276
const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
277
                                                    unsigned int index)
278
{
279
    if (version < 1) return 0;
280

    
281
    switch (index) {
282
    case  0: return adapter.getDescriptor();
283
    default: return 0;
284
    }
285
}
286