Mercurial > hg > svcore
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 |