comparison plugin/FeatureExtractionPluginAdapter.h @ 58:0a34d529f8e0

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