comparison plugins/MFCCPlugin.cpp @ 45:5d7ce1d87301

* Add MFCC plugin * Add means output to Chromagram plugin * Update similarity plugin for MFCC changes
author Chris Cannam <c.cannam@qmul.ac.uk>
date Fri, 18 Jan 2008 13:30:56 +0000
parents
children df7a0bc46592
comparison
equal deleted inserted replaced
44:1dc00e4dbae6 45:5d7ce1d87301
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 QM Vamp Plugin Set
5
6 Centre for Digital Music, Queen Mary, University of London.
7 All rights reserved.
8 */
9
10 #include "MFCCPlugin.h"
11
12 #include <dsp/mfcc/MFCC.h>
13
14 using std::string;
15 using std::vector;
16 using std::cerr;
17 using std::endl;
18
19 MFCCPlugin::MFCCPlugin(float inputSampleRate) :
20 Vamp::Plugin(inputSampleRate),
21 m_config(lrintf(inputSampleRate)),
22 m_mfcc(0),
23 m_step(1024),
24 m_block(2048)
25 {
26 m_bins = 20;
27 m_wantC0 = true;
28 m_logpower = 1;
29
30 setupConfig();
31 }
32
33 void
34 MFCCPlugin::setupConfig()
35 {
36 m_config.FS = lrintf(m_inputSampleRate);
37 m_config.fftsize = m_block;
38 m_config.nceps = (m_wantC0 ? m_bins-1 : m_bins);
39 m_config.want_c0 = m_wantC0;
40 m_config.logpower = m_logpower;
41 }
42
43 MFCCPlugin::~MFCCPlugin()
44 {
45 delete m_mfcc;
46 }
47
48 string
49 MFCCPlugin::getIdentifier() const
50 {
51 return "qm-mfcc";
52 }
53
54 string
55 MFCCPlugin::getName() const
56 {
57 return "Mel-Frequency Cepstral Coefficients";
58 }
59
60 string
61 MFCCPlugin::getDescription() const
62 {
63 //!!!
64 return "";
65 }
66
67 string
68 MFCCPlugin::getMaker() const
69 {
70 return "Queen Mary, University of London";
71 }
72
73 int
74 MFCCPlugin::getPluginVersion() const
75 {
76 return 1;
77 }
78
79 string
80 MFCCPlugin::getCopyright() const
81 {
82 //!!! update
83 return "Copyright (c) 2008 - All Rights Reserved";
84 }
85
86 MFCCPlugin::ParameterList
87 MFCCPlugin::getParameterDescriptors() const
88 {
89 ParameterList list;
90
91 ParameterDescriptor desc;
92 desc.identifier = "nceps";
93 desc.name = "Number of Coefficients";
94 desc.unit = "";
95 //!!! descriptions -- "including C0 if requested"
96 desc.minValue = 1;
97 desc.maxValue = 40;
98 desc.defaultValue = 20;
99 desc.isQuantized = true;
100 desc.quantizeStep = 1;
101 list.push_back(desc);
102
103 desc.identifier = "logpower";
104 desc.name = "Power for Mel Amplitude Logs";
105 desc.unit = "";
106 desc.minValue = 0;
107 desc.maxValue = 5;
108 desc.defaultValue = 1;
109 desc.isQuantized = false;
110 desc.quantizeStep = 0;
111 list.push_back(desc);
112
113 desc.identifier = "wantc0";
114 desc.name = "Include C0";
115 desc.unit = "";
116 //!!! description
117 desc.minValue = 0;
118 desc.maxValue = 1;
119 desc.defaultValue = 1;
120 desc.isQuantized = true;
121 desc.quantizeStep = 1;
122 list.push_back(desc);
123
124 return list;
125 }
126
127 float
128 MFCCPlugin::getParameter(std::string param) const
129 {
130 if (param == "nceps") {
131 return m_bins;
132 }
133 if (param == "logpower") {
134 return m_logpower;
135 }
136 if (param == "wantc0") {
137 return m_wantC0 ? 1 : 0;
138 }
139 std::cerr << "WARNING: MFCCPlugin::getParameter: unknown parameter \""
140 << param << "\"" << std::endl;
141 return 0.0;
142 }
143
144 void
145 MFCCPlugin::setParameter(std::string param, float value)
146 {
147 if (param == "nceps") {
148 m_bins = lrintf(value);
149 } else if (param == "logpower") {
150 m_logpower = lrintf(value);
151 } else if (param == "wantc0") {
152 m_wantC0 = (value > 0.5);
153 } else {
154 std::cerr << "WARNING: MFCCPlugin::setParameter: unknown parameter \""
155 << param << "\"" << std::endl;
156 }
157
158 setupConfig();
159 }
160
161 bool
162 MFCCPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize)
163 {
164 if (m_mfcc) {
165 delete m_mfcc;
166 m_mfcc = 0;
167 }
168
169 if (channels < getMinChannelCount() ||
170 channels > getMaxChannelCount()) return false;
171
172 std::cerr << "MFCCPlugin::initialise: step " << stepSize << ", block "
173 << blockSize << std::endl;
174
175 m_step = stepSize;
176 m_block = blockSize;
177 setupConfig();
178
179 m_mfcc = new MFCC(m_config);
180
181 m_binsums = vector<double>(m_bins);
182 for (int i = 0; i < m_bins; ++i) {
183 m_binsums[i] = 0.0;
184 }
185
186 return true;
187 }
188
189 void
190 MFCCPlugin::reset()
191 {
192 if (m_mfcc) {
193 delete m_mfcc;
194 m_mfcc = new MFCC(m_config);
195 for (int i = 0; i < m_bins; ++i) {
196 m_binsums[i] = 0.0;
197 }
198 }
199 }
200
201 size_t
202 MFCCPlugin::getPreferredStepSize() const
203 {
204 return 1024;
205 }
206
207 size_t
208 MFCCPlugin::getPreferredBlockSize() const
209 {
210 return 2048;
211 }
212
213 MFCCPlugin::OutputList
214 MFCCPlugin::getOutputDescriptors() const
215 {
216 OutputList list;
217
218 OutputDescriptor d;
219 d.identifier = "coefficients";
220 d.name = "Coefficients";
221 d.unit = "";
222 d.hasFixedBinCount = true;
223 d.binCount = m_bins;
224 d.hasKnownExtents = false;
225 d.isQuantized = false;
226 d.sampleType = OutputDescriptor::OneSamplePerStep;
227 list.push_back(d);
228
229 d.identifier = "means";
230 d.name = "Means of Coefficients";
231 //!!! descriptions
232 d.sampleType = OutputDescriptor::FixedSampleRate;
233 d.sampleRate = 1;
234 list.push_back(d);
235
236 return list;
237 }
238
239 MFCCPlugin::FeatureSet
240 MFCCPlugin::process(const float *const *inputBuffers,
241 Vamp::RealTime /* timestamp */)
242 {
243 if (!m_mfcc) {
244 cerr << "ERROR: MFCCPlugin::process: "
245 << "MFCC has not been initialised"
246 << endl;
247 return FeatureSet();
248 }
249
250 double *real = new double[m_block];
251 double *imag = new double[m_block];
252
253 for (size_t i = 0; i < m_block/2; ++i) {
254 real[i] = inputBuffers[0][i*2];
255 if (i > 0) real[m_block - i] = real[i];
256 imag[i] = inputBuffers[0][i*2+1];
257 if (i > 0) imag[m_block - i] = imag[i];
258 }
259
260 double *output = new double[m_bins];
261
262 m_mfcc->process(real, imag, output);
263
264 delete[] real;
265 delete[] imag;
266
267 Feature feature;
268 feature.hasTimestamp = false;
269 for (size_t i = 0; i < m_bins; ++i) {
270 double value = output[i];
271 if (isnan(value)) value = 0.0;
272 m_binsums[i] += value;
273 feature.values.push_back(value);
274 }
275 feature.label = "";
276 ++m_count;
277
278 FeatureSet returnFeatures;
279 returnFeatures[0].push_back(feature);
280 return returnFeatures;
281 }
282
283 MFCCPlugin::FeatureSet
284 MFCCPlugin::getRemainingFeatures()
285 {
286 Feature feature;
287 feature.hasTimestamp = true;
288 feature.timestamp = Vamp::RealTime::zeroTime;
289
290 for (size_t i = 0; i < m_bins; ++i) {
291 double v = m_binsums[i];
292 if (m_count > 0) v /= m_count;
293 feature.values.push_back(v);
294 }
295 feature.label = "Coefficient means";
296
297 FeatureSet returnFeatures;
298 returnFeatures[1].push_back(feature);
299 return returnFeatures;
300 }
301