1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
6 An API for audio analysis and feature extraction plugins.
8 Centre for Digital Music, Queen Mary, University of London.
9 Copyright 2006 Chris Cannam.
11 Permission is hereby granted, free of charge, to any person
12 obtaining a copy of this software and associated documentation
13 files (the "Software"), to deal in the Software without
14 restriction, including without limitation the rights to use, copy,
15 modify, merge, publish, distribute, sublicense, and/or sell copies
16 of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
19 The above copyright notice and this permission notice shall be
20 included in all copies or substantial portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 Except as contained in this notice, the names of the Centre for
31 Digital Music; Queen Mary, University of London; and Chris Cannam
32 shall not be used in advertising or otherwise to promote the sale,
33 use or other dealings in this Software without prior written
37 #include <vamp-sdk/PluginAdapter.h>
42 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 0 )
43 #error Incorrect Vamp SDK header included (not the expected 2.0 SDK)
47 //#define DEBUG_PLUGIN_ADAPTER 1
49 _VAMP_SDK_PLUGSPACE_BEGIN(PluginAdapter.cpp)
53 class PluginAdapterBase::Impl
56 Impl(PluginAdapterBase *);
59 const VampPluginDescriptor *getDescriptor();
62 PluginAdapterBase *m_base;
64 static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc,
65 float inputSampleRate);
67 static void vampCleanup(VampPluginHandle handle);
69 static int vampInitialise(VampPluginHandle handle, unsigned int channels,
70 unsigned int stepSize, unsigned int blockSize);
72 static void vampReset(VampPluginHandle handle);
74 static float vampGetParameter(VampPluginHandle handle, int param);
75 static void vampSetParameter(VampPluginHandle handle, int param, float value);
77 static unsigned int vampGetCurrentProgram(VampPluginHandle handle);
78 static void vampSelectProgram(VampPluginHandle handle, unsigned int program);
80 static unsigned int vampGetPreferredStepSize(VampPluginHandle handle);
81 static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle);
82 static unsigned int vampGetMinChannelCount(VampPluginHandle handle);
83 static unsigned int vampGetMaxChannelCount(VampPluginHandle handle);
85 static unsigned int vampGetOutputCount(VampPluginHandle handle);
87 static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle,
90 static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc);
92 static VampFeatureList *vampProcess(VampPluginHandle handle,
93 const float *const *inputBuffers,
97 static VampFeatureList *vampGetRemainingFeatures(VampPluginHandle handle);
99 static void vampReleaseFeatureSet(VampFeatureList *fs);
101 void checkOutputMap(Plugin *plugin);
102 void markOutputsChanged(Plugin *plugin);
104 void cleanup(Plugin *plugin);
105 unsigned int getOutputCount(Plugin *plugin);
106 VampOutputDescriptor *getOutputDescriptor(Plugin *plugin,
108 VampFeatureList *process(Plugin *plugin,
109 const float *const *inputBuffers,
111 VampFeatureList *getRemainingFeatures(Plugin *plugin);
112 VampFeatureList *convertFeatures(Plugin *plugin,
113 const Plugin::FeatureSet &features);
115 // maps both plugins and descriptors to adapters
116 typedef std::map<const void *, Impl *> AdapterMap;
117 static AdapterMap *m_adapterMap;
118 static Impl *lookupAdapter(VampPluginHandle);
121 VampPluginDescriptor m_descriptor;
122 Plugin::ParameterList m_parameters;
123 Plugin::ProgramList m_programs;
125 typedef std::map<Plugin *, Plugin::OutputList *> OutputMap;
126 OutputMap m_pluginOutputs;
128 std::map<Plugin *, VampFeatureList *> m_fs;
129 std::map<Plugin *, std::vector<size_t> > m_fsizes;
130 std::map<Plugin *, std::vector<std::vector<size_t> > > m_fvsizes;
131 void resizeFS(Plugin *plugin, int n);
132 void resizeFL(Plugin *plugin, int n, size_t sz);
133 void resizeFV(Plugin *plugin, int n, int j, size_t sz);
136 PluginAdapterBase::PluginAdapterBase()
138 m_impl = new Impl(this);
141 PluginAdapterBase::~PluginAdapterBase()
146 const VampPluginDescriptor *
147 PluginAdapterBase::getDescriptor()
149 return m_impl->getDescriptor();
152 PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
156 #ifdef DEBUG_PLUGIN_ADAPTER
157 std::cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << std::endl;
161 const VampPluginDescriptor *
162 PluginAdapterBase::Impl::getDescriptor()
164 #ifdef DEBUG_PLUGIN_ADAPTER
165 std::cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << std::endl;
168 if (m_populated) return &m_descriptor;
170 Plugin *plugin = m_base->createPlugin(48000);
172 if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
173 std::cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
174 << "API version " << plugin->getVampApiVersion()
175 << " for\nplugin \"" << plugin->getIdentifier() << "\" "
176 << "differs from version "
177 << VAMP_API_VERSION << " for adapter.\n"
178 << "This plugin is probably linked against a different version of the Vamp SDK\n"
179 << "from the version it was compiled with. It will need to be re-linked correctly\n"
180 << "before it can be used." << std::endl;
185 m_parameters = plugin->getParameterDescriptors();
186 m_programs = plugin->getPrograms();
188 m_descriptor.vampApiVersion = plugin->getVampApiVersion();
189 m_descriptor.identifier = strdup(plugin->getIdentifier().c_str());
190 m_descriptor.name = strdup(plugin->getName().c_str());
191 m_descriptor.description = strdup(plugin->getDescription().c_str());
192 m_descriptor.maker = strdup(plugin->getMaker().c_str());
193 m_descriptor.pluginVersion = plugin->getPluginVersion();
194 m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
196 m_descriptor.parameterCount = m_parameters.size();
197 m_descriptor.parameters = (const VampParameterDescriptor **)
198 malloc(m_parameters.size() * sizeof(VampParameterDescriptor));
202 for (i = 0; i < m_parameters.size(); ++i) {
203 VampParameterDescriptor *desc = (VampParameterDescriptor *)
204 malloc(sizeof(VampParameterDescriptor));
205 desc->identifier = strdup(m_parameters[i].identifier.c_str());
206 desc->name = strdup(m_parameters[i].name.c_str());
207 desc->description = strdup(m_parameters[i].description.c_str());
208 desc->unit = strdup(m_parameters[i].unit.c_str());
209 desc->minValue = m_parameters[i].minValue;
210 desc->maxValue = m_parameters[i].maxValue;
211 desc->defaultValue = m_parameters[i].defaultValue;
212 desc->isQuantized = m_parameters[i].isQuantized;
213 desc->quantizeStep = m_parameters[i].quantizeStep;
214 desc->valueNames = 0;
215 if (desc->isQuantized && !m_parameters[i].valueNames.empty()) {
216 desc->valueNames = (const char **)
217 malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *));
218 for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) {
219 desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str());
221 desc->valueNames[m_parameters[i].valueNames.size()] = 0;
223 m_descriptor.parameters[i] = desc;
226 m_descriptor.programCount = m_programs.size();
227 m_descriptor.programs = (const char **)
228 malloc(m_programs.size() * sizeof(const char *));
230 for (i = 0; i < m_programs.size(); ++i) {
231 m_descriptor.programs[i] = strdup(m_programs[i].c_str());
234 if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
235 m_descriptor.inputDomain = vampFrequencyDomain;
237 m_descriptor.inputDomain = vampTimeDomain;
240 m_descriptor.instantiate = vampInstantiate;
241 m_descriptor.cleanup = vampCleanup;
242 m_descriptor.initialise = vampInitialise;
243 m_descriptor.reset = vampReset;
244 m_descriptor.getParameter = vampGetParameter;
245 m_descriptor.setParameter = vampSetParameter;
246 m_descriptor.getCurrentProgram = vampGetCurrentProgram;
247 m_descriptor.selectProgram = vampSelectProgram;
248 m_descriptor.getPreferredStepSize = vampGetPreferredStepSize;
249 m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize;
250 m_descriptor.getMinChannelCount = vampGetMinChannelCount;
251 m_descriptor.getMaxChannelCount = vampGetMaxChannelCount;
252 m_descriptor.getOutputCount = vampGetOutputCount;
253 m_descriptor.getOutputDescriptor = vampGetOutputDescriptor;
254 m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor;
255 m_descriptor.process = vampProcess;
256 m_descriptor.getRemainingFeatures = vampGetRemainingFeatures;
257 m_descriptor.releaseFeatureSet = vampReleaseFeatureSet;
260 m_adapterMap = new AdapterMap;
262 (*m_adapterMap)[&m_descriptor] = this;
267 return &m_descriptor;
270 PluginAdapterBase::Impl::~Impl()
272 #ifdef DEBUG_PLUGIN_ADAPTER
273 std::cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << std::endl;
276 if (!m_populated) return;
278 free((void *)m_descriptor.identifier);
279 free((void *)m_descriptor.name);
280 free((void *)m_descriptor.description);
281 free((void *)m_descriptor.maker);
282 free((void *)m_descriptor.copyright);
284 for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) {
285 const VampParameterDescriptor *desc = m_descriptor.parameters[i];
286 free((void *)desc->identifier);
287 free((void *)desc->name);
288 free((void *)desc->description);
289 free((void *)desc->unit);
290 if (desc->valueNames) {
291 for (unsigned int j = 0; desc->valueNames[j]; ++j) {
292 free((void *)desc->valueNames[j]);
294 free((void *)desc->valueNames);
297 free((void *)m_descriptor.parameters);
299 for (unsigned int i = 0; i < m_descriptor.programCount; ++i) {
300 free((void *)m_descriptor.programs[i]);
302 free((void *)m_descriptor.programs);
306 m_adapterMap->erase(&m_descriptor);
308 if (m_adapterMap->empty()) {
315 PluginAdapterBase::Impl *
316 PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle)
318 #ifdef DEBUG_PLUGIN_ADAPTER
319 std::cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << std::endl;
322 if (!m_adapterMap) return 0;
323 AdapterMap::const_iterator i = m_adapterMap->find(handle);
324 if (i == m_adapterMap->end()) return 0;
329 PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc,
330 float inputSampleRate)
332 #ifdef DEBUG_PLUGIN_ADAPTER
333 std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << std::endl;
337 m_adapterMap = new AdapterMap();
340 if (m_adapterMap->find(desc) == m_adapterMap->end()) {
341 std::cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << std::endl;
345 Impl *adapter = (*m_adapterMap)[desc];
346 if (desc != &adapter->m_descriptor) return 0;
348 Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate);
350 (*m_adapterMap)[plugin] = adapter;
353 #ifdef DEBUG_PLUGIN_ADAPTER
354 std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << std::endl;
361 PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle)
363 #ifdef DEBUG_PLUGIN_ADAPTER
364 std::cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << std::endl;
367 Impl *adapter = lookupAdapter(handle);
369 delete ((Plugin *)handle);
372 adapter->cleanup(((Plugin *)handle));
376 PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle,
377 unsigned int channels,
378 unsigned int stepSize,
379 unsigned int blockSize)
381 #ifdef DEBUG_PLUGIN_ADAPTER
382 std::cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << std::endl;
385 Impl *adapter = lookupAdapter(handle);
386 if (!adapter) return 0;
387 bool result = ((Plugin *)handle)->initialise(channels, stepSize, blockSize);
388 adapter->markOutputsChanged((Plugin *)handle);
389 return result ? 1 : 0;
393 PluginAdapterBase::Impl::vampReset(VampPluginHandle handle)
395 #ifdef DEBUG_PLUGIN_ADAPTER
396 std::cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << std::endl;
399 ((Plugin *)handle)->reset();
403 PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle,
406 #ifdef DEBUG_PLUGIN_ADAPTER
407 std::cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << std::endl;
410 Impl *adapter = lookupAdapter(handle);
411 if (!adapter) return 0.0;
412 Plugin::ParameterList &list = adapter->m_parameters;
413 return ((Plugin *)handle)->getParameter(list[param].identifier);
417 PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle,
418 int param, float value)
420 #ifdef DEBUG_PLUGIN_ADAPTER
421 std::cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << std::endl;
424 Impl *adapter = lookupAdapter(handle);
425 if (!adapter) return;
426 Plugin::ParameterList &list = adapter->m_parameters;
427 ((Plugin *)handle)->setParameter(list[param].identifier, value);
428 adapter->markOutputsChanged((Plugin *)handle);
432 PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle)
434 #ifdef DEBUG_PLUGIN_ADAPTER
435 std::cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << std::endl;
438 Impl *adapter = lookupAdapter(handle);
439 if (!adapter) return 0;
440 Plugin::ProgramList &list = adapter->m_programs;
441 std::string program = ((Plugin *)handle)->getCurrentProgram();
442 for (unsigned int i = 0; i < list.size(); ++i) {
443 if (list[i] == program) return i;
449 PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle,
450 unsigned int program)
452 #ifdef DEBUG_PLUGIN_ADAPTER
453 std::cerr << "PluginAdapterBase::Impl::vampSelectProgram(" << handle << ", " << program << ")" << std::endl;
456 Impl *adapter = lookupAdapter(handle);
457 if (!adapter) return;
459 Plugin::ProgramList &list = adapter->m_programs;
460 ((Plugin *)handle)->selectProgram(list[program]);
462 adapter->markOutputsChanged((Plugin *)handle);
466 PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle)
468 #ifdef DEBUG_PLUGIN_ADAPTER
469 std::cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << std::endl;
472 return ((Plugin *)handle)->getPreferredStepSize();
476 PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle)
478 #ifdef DEBUG_PLUGIN_ADAPTER
479 std::cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << std::endl;
482 return ((Plugin *)handle)->getPreferredBlockSize();
486 PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle)
488 #ifdef DEBUG_PLUGIN_ADAPTER
489 std::cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << std::endl;
492 return ((Plugin *)handle)->getMinChannelCount();
496 PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
498 #ifdef DEBUG_PLUGIN_ADAPTER
499 std::cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << std::endl;
502 return ((Plugin *)handle)->getMaxChannelCount();
506 PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle)
508 #ifdef DEBUG_PLUGIN_ADAPTER
509 std::cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << std::endl;
512 Impl *adapter = lookupAdapter(handle);
514 // std::cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << std::endl;
516 if (!adapter) return 0;
517 return adapter->getOutputCount((Plugin *)handle);
520 VampOutputDescriptor *
521 PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle,
524 #ifdef DEBUG_PLUGIN_ADAPTER
525 std::cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << std::endl;
528 Impl *adapter = lookupAdapter(handle);
530 // std::cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << std::endl;
532 if (!adapter) return 0;
533 return adapter->getOutputDescriptor((Plugin *)handle, i);
537 PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
539 #ifdef DEBUG_PLUGIN_ADAPTER
540 std::cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << std::endl;
543 if (desc->identifier) free((void *)desc->identifier);
544 if (desc->name) free((void *)desc->name);
545 if (desc->description) free((void *)desc->description);
546 if (desc->unit) free((void *)desc->unit);
547 if (desc->hasFixedBinCount && desc->binNames) {
548 for (unsigned int i = 0; i < desc->binCount; ++i) {
549 if (desc->binNames[i]) {
550 free((void *)desc->binNames[i]);
554 if (desc->binNames) free((void *)desc->binNames);
559 PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
560 const float *const *inputBuffers,
564 #ifdef DEBUG_PLUGIN_ADAPTER
565 std::cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << std::endl;
568 Impl *adapter = lookupAdapter(handle);
569 if (!adapter) return 0;
570 return adapter->process((Plugin *)handle, inputBuffers, sec, nsec);
574 PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
576 #ifdef DEBUG_PLUGIN_ADAPTER
577 std::cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << std::endl;
580 Impl *adapter = lookupAdapter(handle);
581 if (!adapter) return 0;
582 return adapter->getRemainingFeatures((Plugin *)handle);
586 PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *fs)
588 #ifdef DEBUG_PLUGIN_ADAPTER
589 std::cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << std::endl;
594 PluginAdapterBase::Impl::cleanup(Plugin *plugin)
596 if (m_fs.find(plugin) != m_fs.end()) {
597 size_t outputCount = 0;
598 if (m_pluginOutputs[plugin]) {
599 outputCount = m_pluginOutputs[plugin]->size();
601 VampFeatureList *list = m_fs[plugin];
602 for (unsigned int i = 0; i < outputCount; ++i) {
603 for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) {
604 if (list[i].features[j].v1.label) {
605 free(list[i].features[j].v1.label);
607 if (list[i].features[j].v1.values) {
608 free(list[i].features[j].v1.values);
611 if (list[i].features) free(list[i].features);
614 m_fsizes.erase(plugin);
615 m_fvsizes.erase(plugin);
618 if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
619 delete m_pluginOutputs[plugin];
620 m_pluginOutputs.erase(plugin);
624 m_adapterMap->erase(plugin);
626 if (m_adapterMap->empty()) {
632 delete ((Plugin *)plugin);
636 PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin)
638 OutputMap::iterator i = m_pluginOutputs.find(plugin);
640 if (i == m_pluginOutputs.end() || !i->second) {
642 m_pluginOutputs[plugin] = new Plugin::OutputList
643 (plugin->getOutputDescriptors());
645 // std::cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << std::endl;
650 PluginAdapterBase::Impl::markOutputsChanged(Plugin *plugin)
652 OutputMap::iterator i = m_pluginOutputs.find(plugin);
654 // std::cerr << "PluginAdapterBase::Impl::markOutputsChanged" << std::endl;
656 if (i != m_pluginOutputs.end()) {
658 Plugin::OutputList *list = i->second;
659 m_pluginOutputs.erase(i);
665 PluginAdapterBase::Impl::getOutputCount(Plugin *plugin)
667 checkOutputMap(plugin);
669 return m_pluginOutputs[plugin]->size();
672 VampOutputDescriptor *
673 PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
676 checkOutputMap(plugin);
678 Plugin::OutputDescriptor &od =
679 (*m_pluginOutputs[plugin])[i];
681 VampOutputDescriptor *desc = (VampOutputDescriptor *)
682 malloc(sizeof(VampOutputDescriptor));
684 desc->identifier = strdup(od.identifier.c_str());
685 desc->name = strdup(od.name.c_str());
686 desc->description = strdup(od.description.c_str());
687 desc->unit = strdup(od.unit.c_str());
688 desc->hasFixedBinCount = od.hasFixedBinCount;
689 desc->binCount = od.binCount;
691 if (od.hasFixedBinCount && od.binCount > 0
692 // We would like to do "&& !od.binNames.empty()" here -- but we
693 // can't, because it will crash older versions of the host adapter
694 // which try to copy the names across whenever the bin count is
695 // non-zero, regardless of whether they exist or not
697 desc->binNames = (const char **)
698 malloc(od.binCount * sizeof(const char *));
700 for (unsigned int i = 0; i < od.binCount; ++i) {
701 if (i < od.binNames.size()) {
702 desc->binNames[i] = strdup(od.binNames[i].c_str());
704 desc->binNames[i] = 0;
711 desc->hasKnownExtents = od.hasKnownExtents;
712 desc->minValue = od.minValue;
713 desc->maxValue = od.maxValue;
714 desc->isQuantized = od.isQuantized;
715 desc->quantizeStep = od.quantizeStep;
717 switch (od.sampleType) {
718 case Plugin::OutputDescriptor::OneSamplePerStep:
719 desc->sampleType = vampOneSamplePerStep; break;
720 case Plugin::OutputDescriptor::FixedSampleRate:
721 desc->sampleType = vampFixedSampleRate; break;
722 case Plugin::OutputDescriptor::VariableSampleRate:
723 desc->sampleType = vampVariableSampleRate; break;
726 desc->sampleRate = od.sampleRate;
727 desc->hasDuration = od.hasDuration;
733 PluginAdapterBase::Impl::process(Plugin *plugin,
734 const float *const *inputBuffers,
737 // std::cerr << "PluginAdapterBase::Impl::process" << std::endl;
738 RealTime rt(sec, nsec);
739 checkOutputMap(plugin);
740 return convertFeatures(plugin, plugin->process(inputBuffers, rt));
744 PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin)
746 // std::cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << std::endl;
747 checkOutputMap(plugin);
748 return convertFeatures(plugin, plugin->getRemainingFeatures());
752 PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
753 const Plugin::FeatureSet &features)
758 if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size();
760 resizeFS(plugin, outputCount);
761 VampFeatureList *fs = m_fs[plugin];
763 // std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: sizeof(Feature) == " << sizeof(Plugin::Feature) << ", sizeof(VampFeature) == " << sizeof(VampFeature) << ", sizeof(VampFeatureList) == " << sizeof(VampFeatureList) << std::endl;
765 for (Plugin::FeatureSet::const_iterator fi = features.begin();
766 fi != features.end(); ++fi) {
770 // std::cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << std::endl;
772 if (n >= int(outputCount)) {
773 std::cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << std::endl;
778 for (int i = lastN + 1; i < n; ++i) {
779 fs[i].featureCount = 0;
783 const Plugin::FeatureList &fl = fi->second;
785 size_t sz = fl.size();
786 if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz);
787 fs[n].featureCount = sz;
789 for (size_t j = 0; j < sz; ++j) {
791 // std::cerr << "PluginAdapterBase::Impl::convertFeatures: j = " << j << std::endl;
793 VampFeature *feature = &fs[n].features[j].v1;
795 feature->hasTimestamp = fl[j].hasTimestamp;
796 feature->sec = fl[j].timestamp.sec;
797 feature->nsec = fl[j].timestamp.nsec;
798 feature->valueCount = fl[j].values.size();
800 VampFeatureV2 *v2 = &fs[n].features[j + sz].v2;
802 v2->hasDuration = fl[j].hasDuration;
803 v2->durationSec = fl[j].duration.sec;
804 v2->durationNsec = fl[j].duration.nsec;
806 if (feature->label) free(feature->label);
808 if (fl[j].label.empty()) {
811 feature->label = strdup(fl[j].label.c_str());
814 if (feature->valueCount > m_fvsizes[plugin][n][j]) {
815 resizeFV(plugin, n, j, feature->valueCount);
818 for (unsigned int k = 0; k < feature->valueCount; ++k) {
819 // std::cerr << "PluginAdapterBase::Impl::convertFeatures: k = " << k << std::endl;
820 feature->values[k] = fl[j].values[k];
827 if (lastN == -1) return 0;
829 if (int(outputCount) > lastN + 1) {
830 for (int i = lastN + 1; i < int(outputCount); ++i) {
831 fs[i].featureCount = 0;
835 // std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: have " << outputCount << " outputs" << std::endl;
836 // for (int i = 0; i < outputCount; ++i) {
837 // std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: output " << i << " has " << fs[i].featureCount << " features" << std::endl;
845 PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n)
847 // std::cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << std::endl;
849 int i = m_fsizes[plugin].size();
852 // std::cerr << "resizing from " << i << std::endl;
854 m_fs[plugin] = (VampFeatureList *)realloc
855 (m_fs[plugin], n * sizeof(VampFeatureList));
858 m_fs[plugin][i].featureCount = 0;
859 m_fs[plugin][i].features = 0;
860 m_fsizes[plugin].push_back(0);
861 m_fvsizes[plugin].push_back(std::vector<size_t>());
867 PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz)
869 // std::cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", "
870 // << sz << ")" << std::endl;
872 size_t i = m_fsizes[plugin][n];
875 // std::cerr << "resizing from " << i << std::endl;
877 m_fs[plugin][n].features = (VampFeatureUnion *)realloc
878 (m_fs[plugin][n].features, 2 * sz * sizeof(VampFeatureUnion));
880 while (m_fsizes[plugin][n] < sz) {
881 m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.hasTimestamp = 0;
882 m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.valueCount = 0;
883 m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.values = 0;
884 m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.label = 0;
885 m_fs[plugin][n].features[m_fsizes[plugin][n] + sz].v2.hasDuration = 0;
886 m_fvsizes[plugin][n].push_back(0);
887 m_fsizes[plugin][n]++;
892 PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz)
894 // std::cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", "
895 // << j << ", " << sz << ")" << std::endl;
897 size_t i = m_fvsizes[plugin][n][j];
900 // std::cerr << "resizing from " << i << std::endl;
902 m_fs[plugin][n].features[j].v1.values = (float *)realloc
903 (m_fs[plugin][n].features[j].v1.values, sz * sizeof(float));
905 m_fvsizes[plugin][n][j] = sz;
908 PluginAdapterBase::Impl::AdapterMap *
909 PluginAdapterBase::Impl::m_adapterMap = 0;
913 _VAMP_SDK_PLUGSPACE_END(PluginAdapter.cpp)