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