Mercurial > hg > svcore
comparison plugin/FeatureExtractionPluginAdapter.cpp @ 60:3086ff194ea0
* More structural work on feature extraction plugin C <-> C++ adapter
* Allow use of LADSPA/DSSI plugins with control outputs as feature extraction
plugins (DSSI with MIDI output still to come)
* Reorder labels on spectrogram status box
* Minor tweaks in doc etc.
author | Chris Cannam |
---|---|
date | Mon, 27 Mar 2006 15:03:02 +0000 |
parents | 0a34d529f8e0 |
children |
comparison
equal
deleted
inserted
replaced
59:9705a1978ecc | 60:3086ff194ea0 |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ |
2 | 2 |
3 /* | 3 /* |
4 Sonic Visualiser | 4 Sonic Visualiser |
5 An audio file viewer and annotation editor. | 5 An audio file viewer and annotation editor. |
6 Centre for Digital Music, Queen Mary, University of London. | 6 Centre for Digital Music, Queen Mary, University of London. |
7 This file copyright 2006 Chris Cannam. | 7 This file copyright 2006 Chris Cannam. |
8 | 8 |
9 This program is free software; you can redistribute it and/or | 9 This program is free software; you can redistribute it and/or |
10 modify it under the terms of the GNU General Public License as | 10 modify it under the terms of the GNU General Public License as |
11 published by the Free Software Foundation; either version 2 of the | 11 published by the Free Software Foundation; either version 2 of the |
12 License, or (at your option) any later version. See the file | 12 License, or (at your option) any later version. See the file |
13 COPYING included with this distribution for more information. | 13 COPYING included with this distribution for more information. |
14 */ | 14 */ |
15 | 15 |
16 #include "FeatureExtractionPluginAdapter.h" | 16 #include "FeatureExtractionPluginAdapter.h" |
17 | 17 |
18 #include "plugins/ChromagramPlugin.h" | 18 FeatureExtractionPluginAdapterBase::FeatureExtractionPluginAdapterBase() : |
19 | 19 m_populated(false) |
20 extern int blah() | 20 { |
21 { | 21 } |
22 FeatureExtractionPluginAdapter<ChromagramPlugin> adapter; | 22 |
23 | 23 const SVPPluginDescriptor * |
24 const SVPPluginDescriptor *desc = adapter.getDescriptor(); | 24 FeatureExtractionPluginAdapterBase::getDescriptor() |
25 | 25 { |
26 SVPPluginHandle handle = desc->instantiate(desc, 48000); | 26 if (m_populated) return &m_descriptor; |
27 | 27 |
28 unsigned int preferredBlockSize = desc->getPreferredBlockSize(handle); | 28 FeatureExtractionPlugin *plugin = createPlugin(48000); |
29 | 29 |
30 SVPOutputDescriptor *od = desc->getOutputDescriptor(handle, 2); | 30 m_parameters = plugin->getParameterDescriptors(); |
31 | 31 m_programs = plugin->getPrograms(); |
32 SVPFeatureList **feature = desc->process(handle, 0, 0, 0); | 32 |
33 } | 33 m_descriptor.name = strdup(plugin->getName().c_str()); |
34 | 34 m_descriptor.description = strdup(plugin->getDescription().c_str()); |
35 m_descriptor.maker = strdup(plugin->getMaker().c_str()); | |
36 m_descriptor.pluginVersion = plugin->getPluginVersion(); | |
37 m_descriptor.copyright = strdup(plugin->getCopyright().c_str()); | |
38 | |
39 m_descriptor.parameterCount = m_parameters.size(); | |
40 m_descriptor.parameters = (const SVPParameterDescriptor **) | |
41 malloc(m_parameters.size() * sizeof(SVPParameterDescriptor)); | |
42 | |
43 for (unsigned int i = 0; i < m_parameters.size(); ++i) { | |
44 SVPParameterDescriptor *desc = (SVPParameterDescriptor *) | |
45 malloc(sizeof(SVPParameterDescriptor)); | |
46 desc->name = strdup(m_parameters[i].name.c_str()); | |
47 desc->description = strdup(m_parameters[i].description.c_str()); | |
48 desc->unit = strdup(m_parameters[i].unit.c_str()); | |
49 desc->minValue = m_parameters[i].minValue; | |
50 desc->maxValue = m_parameters[i].maxValue; | |
51 desc->defaultValue = m_parameters[i].defaultValue; | |
52 desc->isQuantized = m_parameters[i].isQuantized; | |
53 desc->quantizeStep = m_parameters[i].quantizeStep; | |
54 m_descriptor.parameters[i] = desc; | |
55 } | |
56 | |
57 m_descriptor.programCount = m_programs.size(); | |
58 m_descriptor.programs = (const char **) | |
59 malloc(m_programs.size() * sizeof(const char *)); | |
60 | |
61 for (unsigned int i = 0; i < m_programs.size(); ++i) { | |
62 m_descriptor.programs[i] = strdup(m_programs[i].c_str()); | |
63 } | |
64 | |
65 m_descriptor.instantiate = svpInstantiate; | |
66 m_descriptor.cleanup = svpCleanup; | |
67 m_descriptor.initialise = svpInitialise; | |
68 m_descriptor.reset = svpReset; | |
69 m_descriptor.getParameter = svpGetParameter; | |
70 m_descriptor.setParameter = svpSetParameter; | |
71 m_descriptor.getCurrentProgram = svpGetCurrentProgram; | |
72 m_descriptor.selectProgram = svpSelectProgram; | |
73 m_descriptor.getPreferredStepSize = svpGetPreferredStepSize; | |
74 m_descriptor.getPreferredBlockSize = svpGetPreferredBlockSize; | |
75 m_descriptor.getMinChannelCount = svpGetMinChannelCount; | |
76 m_descriptor.getMaxChannelCount = svpGetMaxChannelCount; | |
77 m_descriptor.getOutputCount = svpGetOutputCount; | |
78 m_descriptor.getOutputDescriptor = svpGetOutputDescriptor; | |
79 m_descriptor.releaseOutputDescriptor = svpReleaseOutputDescriptor; | |
80 m_descriptor.process = svpProcess; | |
81 m_descriptor.getRemainingFeatures = svpGetRemainingFeatures; | |
82 m_descriptor.releaseFeatureSet = svpReleaseFeatureSet; | |
83 | |
84 m_adapterMap[&m_descriptor] = this; | |
85 | |
86 delete plugin; | |
87 | |
88 m_populated = true; | |
89 return &m_descriptor; | |
90 } | |
91 | |
92 FeatureExtractionPluginAdapterBase::~FeatureExtractionPluginAdapterBase() | |
93 { | |
94 if (!m_populated) return; | |
95 | |
96 free((void *)m_descriptor.name); | |
97 free((void *)m_descriptor.description); | |
98 free((void *)m_descriptor.maker); | |
99 free((void *)m_descriptor.copyright); | |
100 | |
101 for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) { | |
102 const SVPParameterDescriptor *desc = m_descriptor.parameters[i]; | |
103 free((void *)desc->name); | |
104 free((void *)desc->description); | |
105 free((void *)desc->unit); | |
106 } | |
107 free((void *)m_descriptor.parameters); | |
108 | |
109 for (unsigned int i = 0; i < m_descriptor.programCount; ++i) { | |
110 free((void *)m_descriptor.programs[i]); | |
111 } | |
112 free((void *)m_descriptor.programs); | |
113 | |
114 m_adapterMap.erase(&m_descriptor); | |
115 } | |
116 | |
117 FeatureExtractionPluginAdapterBase * | |
118 FeatureExtractionPluginAdapterBase::lookupAdapter(SVPPluginHandle handle) | |
119 { | |
120 AdapterMap::const_iterator i = m_adapterMap.find(handle); | |
121 if (i == m_adapterMap.end()) return 0; | |
122 return i->second; | |
123 } | |
124 | |
125 SVPPluginHandle | |
126 FeatureExtractionPluginAdapterBase::svpInstantiate(const SVPPluginDescriptor *desc, | |
127 float inputSampleRate) | |
128 { | |
129 if (m_adapterMap.find(desc) == m_adapterMap.end()) return 0; | |
130 FeatureExtractionPluginAdapterBase *adapter = m_adapterMap[desc]; | |
131 if (desc != &adapter->m_descriptor) return 0; | |
132 | |
133 FeatureExtractionPlugin *plugin = adapter->createPlugin(inputSampleRate); | |
134 if (plugin) { | |
135 m_adapterMap[plugin] = adapter; | |
136 } | |
137 | |
138 return plugin; | |
139 } | |
140 | |
141 void | |
142 FeatureExtractionPluginAdapterBase::svpCleanup(SVPPluginHandle handle) | |
143 { | |
144 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
145 if (!adapter) { | |
146 delete ((FeatureExtractionPlugin *)handle); | |
147 return; | |
148 } | |
149 adapter->cleanup(((FeatureExtractionPlugin *)handle)); | |
150 } | |
151 | |
152 int | |
153 FeatureExtractionPluginAdapterBase::svpInitialise(SVPPluginHandle handle, | |
154 unsigned int channels, | |
155 unsigned int stepSize, | |
156 unsigned int blockSize) | |
157 { | |
158 bool result = ((FeatureExtractionPlugin *)handle)->initialise | |
159 (channels, stepSize, blockSize); | |
160 return result ? 1 : 0; | |
161 } | |
162 | |
163 void | |
164 FeatureExtractionPluginAdapterBase::svpReset(SVPPluginHandle handle) | |
165 { | |
166 ((FeatureExtractionPlugin *)handle)->reset(); | |
167 } | |
168 | |
169 float | |
170 FeatureExtractionPluginAdapterBase::svpGetParameter(SVPPluginHandle handle, | |
171 int param) | |
172 { | |
173 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
174 if (!adapter) return 0.0; | |
175 FeatureExtractionPlugin::ParameterList &list = adapter->m_parameters; | |
176 return ((FeatureExtractionPlugin *)handle)->getParameter(list[param].name); | |
177 } | |
178 | |
179 void | |
180 FeatureExtractionPluginAdapterBase::svpSetParameter(SVPPluginHandle handle, | |
181 int param, float value) | |
182 { | |
183 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
184 if (!adapter) return; | |
185 FeatureExtractionPlugin::ParameterList &list = adapter->m_parameters; | |
186 ((FeatureExtractionPlugin *)handle)->setParameter(list[param].name, value); | |
187 } | |
188 | |
189 unsigned int | |
190 FeatureExtractionPluginAdapterBase::svpGetCurrentProgram(SVPPluginHandle handle) | |
191 { | |
192 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
193 if (!adapter) return 0; | |
194 FeatureExtractionPlugin::ProgramList &list = adapter->m_programs; | |
195 std::string program = ((FeatureExtractionPlugin *)handle)->getCurrentProgram(); | |
196 for (unsigned int i = 0; i < list.size(); ++i) { | |
197 if (list[i] == program) return i; | |
198 } | |
199 return 0; | |
200 } | |
201 | |
202 void | |
203 FeatureExtractionPluginAdapterBase::svpSelectProgram(SVPPluginHandle handle, | |
204 unsigned int program) | |
205 { | |
206 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
207 if (!adapter) return; | |
208 FeatureExtractionPlugin::ProgramList &list = adapter->m_programs; | |
209 ((FeatureExtractionPlugin *)handle)->selectProgram(list[program]); | |
210 } | |
211 | |
212 unsigned int | |
213 FeatureExtractionPluginAdapterBase::svpGetPreferredStepSize(SVPPluginHandle handle) | |
214 { | |
215 return ((FeatureExtractionPlugin *)handle)->getPreferredStepSize(); | |
216 } | |
217 | |
218 unsigned int | |
219 FeatureExtractionPluginAdapterBase::svpGetPreferredBlockSize(SVPPluginHandle handle) | |
220 { | |
221 return ((FeatureExtractionPlugin *)handle)->getPreferredBlockSize(); | |
222 } | |
223 | |
224 unsigned int | |
225 FeatureExtractionPluginAdapterBase::svpGetMinChannelCount(SVPPluginHandle handle) | |
226 { | |
227 return ((FeatureExtractionPlugin *)handle)->getMinChannelCount(); | |
228 } | |
229 | |
230 unsigned int | |
231 FeatureExtractionPluginAdapterBase::svpGetMaxChannelCount(SVPPluginHandle handle) | |
232 { | |
233 return ((FeatureExtractionPlugin *)handle)->getMaxChannelCount(); | |
234 } | |
235 | |
236 unsigned int | |
237 FeatureExtractionPluginAdapterBase::svpGetOutputCount(SVPPluginHandle handle) | |
238 { | |
239 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
240 if (!adapter) return 0; | |
241 return adapter->getOutputCount((FeatureExtractionPlugin *)handle); | |
242 } | |
243 | |
244 SVPOutputDescriptor * | |
245 FeatureExtractionPluginAdapterBase::svpGetOutputDescriptor(SVPPluginHandle handle, | |
246 unsigned int i) | |
247 { | |
248 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
249 if (!adapter) return 0; | |
250 return adapter->getOutputDescriptor((FeatureExtractionPlugin *)handle, i); | |
251 } | |
252 | |
253 void | |
254 FeatureExtractionPluginAdapterBase::svpReleaseOutputDescriptor(SVPOutputDescriptor *desc) | |
255 { | |
256 if (desc->name) free((void *)desc->name); | |
257 if (desc->description) free((void *)desc->description); | |
258 if (desc->unit) free((void *)desc->unit); | |
259 for (unsigned int i = 0; i < desc->valueCount; ++i) { | |
260 free((void *)desc->valueNames[i]); | |
261 } | |
262 if (desc->valueNames) free((void *)desc->valueNames); | |
263 free((void *)desc); | |
264 } | |
265 | |
266 SVPFeatureList ** | |
267 FeatureExtractionPluginAdapterBase::svpProcess(SVPPluginHandle handle, | |
268 float **inputBuffers, | |
269 int sec, | |
270 int nsec) | |
271 { | |
272 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
273 if (!adapter) return 0; | |
274 return adapter->process((FeatureExtractionPlugin *)handle, | |
275 inputBuffers, sec, nsec); | |
276 } | |
277 | |
278 SVPFeatureList ** | |
279 FeatureExtractionPluginAdapterBase::svpGetRemainingFeatures(SVPPluginHandle handle) | |
280 { | |
281 FeatureExtractionPluginAdapterBase *adapter = lookupAdapter(handle); | |
282 if (!adapter) return 0; | |
283 return adapter->getRemainingFeatures((FeatureExtractionPlugin *)handle); | |
284 } | |
285 | |
286 void | |
287 FeatureExtractionPluginAdapterBase::svpReleaseFeatureSet(SVPFeatureList **fs) | |
288 { | |
289 if (!fs) return; | |
290 for (unsigned int i = 0; fs[i]; ++i) { | |
291 for (unsigned int j = 0; j < fs[i]->featureCount; ++j) { | |
292 SVPFeature *feature = &fs[i]->features[j]; | |
293 if (feature->values) free((void *)feature->values); | |
294 if (feature->label) free((void *)feature->label); | |
295 free((void *)feature); | |
296 } | |
297 if (fs[i]->features) free((void *)fs[i]->features); | |
298 free((void *)fs[i]); | |
299 } | |
300 free((void *)fs); | |
301 } | |
302 | |
303 void | |
304 FeatureExtractionPluginAdapterBase::cleanup(FeatureExtractionPlugin *plugin) | |
305 { | |
306 if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) { | |
307 delete m_pluginOutputs[plugin]; | |
308 m_pluginOutputs.erase(plugin); | |
309 } | |
310 m_adapterMap.erase(plugin); | |
311 delete ((FeatureExtractionPlugin *)plugin); | |
312 } | |
313 | |
314 void | |
315 FeatureExtractionPluginAdapterBase::checkOutputMap(FeatureExtractionPlugin *plugin) | |
316 { | |
317 if (!m_pluginOutputs[plugin]) { | |
318 m_pluginOutputs[plugin] = new FeatureExtractionPlugin::OutputList | |
319 (plugin->getOutputDescriptors()); | |
320 } | |
321 } | |
322 | |
323 unsigned int | |
324 FeatureExtractionPluginAdapterBase::getOutputCount(FeatureExtractionPlugin *plugin) | |
325 { | |
326 checkOutputMap(plugin); | |
327 return m_pluginOutputs[plugin]->size(); | |
328 } | |
329 | |
330 SVPOutputDescriptor * | |
331 FeatureExtractionPluginAdapterBase::getOutputDescriptor(FeatureExtractionPlugin *plugin, | |
332 unsigned int i) | |
333 { | |
334 checkOutputMap(plugin); | |
335 FeatureExtractionPlugin::OutputDescriptor &od = | |
336 (*m_pluginOutputs[plugin])[i]; | |
337 | |
338 SVPOutputDescriptor *desc = (SVPOutputDescriptor *) | |
339 malloc(sizeof(SVPOutputDescriptor)); | |
340 | |
341 desc->name = strdup(od.name.c_str()); | |
342 desc->description = strdup(od.description.c_str()); | |
343 desc->unit = strdup(od.unit.c_str()); | |
344 desc->hasFixedValueCount = od.hasFixedValueCount; | |
345 desc->valueCount = od.valueCount; | |
346 | |
347 desc->valueNames = (const char **) | |
348 malloc(od.valueCount * sizeof(const char *)); | |
349 | |
350 for (unsigned int i = 0; i < od.valueCount; ++i) { | |
351 desc->valueNames[i] = strdup(od.valueNames[i].c_str()); | |
352 } | |
353 | |
354 desc->hasKnownExtents = od.hasKnownExtents; | |
355 desc->minValue = od.minValue; | |
356 desc->maxValue = od.maxValue; | |
357 desc->isQuantized = od.isQuantized; | |
358 desc->quantizeStep = od.quantizeStep; | |
359 | |
360 switch (od.sampleType) { | |
361 case FeatureExtractionPlugin::OutputDescriptor::OneSamplePerStep: | |
362 desc->sampleType = svpOneSamplePerStep; break; | |
363 case FeatureExtractionPlugin::OutputDescriptor::FixedSampleRate: | |
364 desc->sampleType = svpFixedSampleRate; break; | |
365 case FeatureExtractionPlugin::OutputDescriptor::VariableSampleRate: | |
366 desc->sampleType = svpVariableSampleRate; break; | |
367 } | |
368 | |
369 desc->sampleRate = od.sampleRate; | |
370 | |
371 return desc; | |
372 } | |
373 | |
374 SVPFeatureList ** | |
375 FeatureExtractionPluginAdapterBase::process(FeatureExtractionPlugin *plugin, | |
376 float **inputBuffers, | |
377 int sec, int nsec) | |
378 { | |
379 RealTime rt(sec, nsec); | |
380 return convertFeatures(plugin->process(inputBuffers, rt)); | |
381 } | |
382 | |
383 SVPFeatureList ** | |
384 FeatureExtractionPluginAdapterBase::getRemainingFeatures(FeatureExtractionPlugin *plugin) | |
385 { | |
386 return convertFeatures(plugin->getRemainingFeatures()); | |
387 } | |
388 | |
389 SVPFeatureList ** | |
390 FeatureExtractionPluginAdapterBase::convertFeatures(const FeatureExtractionPlugin::FeatureSet &features) | |
391 { | |
392 unsigned int n = 0; | |
393 if (features.begin() != features.end()) { | |
394 FeatureExtractionPlugin::FeatureSet::const_iterator i = features.end(); | |
395 --i; | |
396 n = i->first + 1; | |
397 } | |
398 | |
399 if (!n) return 0; | |
400 | |
401 SVPFeatureList **fs = (SVPFeatureList **) | |
402 malloc((n + 1) * sizeof(SVPFeatureList *)); | |
403 | |
404 for (unsigned int i = 0; i < n; ++i) { | |
405 fs[i] = (SVPFeatureList *)malloc(sizeof(SVPFeatureList)); | |
406 if (features.find(i) == features.end()) { | |
407 fs[i]->featureCount = 0; | |
408 fs[i]->features = 0; | |
409 } else { | |
410 FeatureExtractionPlugin::FeatureSet::const_iterator fi = | |
411 features.find(i); | |
412 const FeatureExtractionPlugin::FeatureList &fl = fi->second; | |
413 fs[i]->featureCount = fl.size(); | |
414 fs[i]->features = (SVPFeature *)malloc(fl.size() * | |
415 sizeof(SVPFeature)); | |
416 for (unsigned int j = 0; j < fl.size(); ++j) { | |
417 fs[i]->features[j].hasTimestamp = fl[j].hasTimestamp; | |
418 fs[i]->features[j].sec = fl[j].timestamp.sec; | |
419 fs[i]->features[j].nsec = fl[j].timestamp.nsec; | |
420 fs[i]->features[j].valueCount = fl[j].values.size(); | |
421 fs[i]->features[j].values = (float *)malloc | |
422 (fs[i]->features[j].valueCount * sizeof(float)); | |
423 for (unsigned int k = 0; k < fs[i]->features[j].valueCount; ++k) { | |
424 fs[i]->features[j].values[k] = fl[j].values[k]; | |
425 } | |
426 fs[i]->features[j].label = strdup(fl[j].label.c_str()); | |
427 } | |
428 } | |
429 } | |
430 | |
431 fs[n] = 0; | |
432 | |
433 return fs; | |
434 } | |
435 | |
436 FeatureExtractionPluginAdapterBase::AdapterMap | |
437 FeatureExtractionPluginAdapterBase::m_adapterMap; | |
438 | |
439 |