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-hostsdk/PluginHostAdapter.h"
40 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 0 )
41 #error Incorrect Vamp SDK header included (not the expected 2.0 SDK)
44 _VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.cpp)
49 PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
50 float inputSampleRate) :
51 Plugin(inputSampleRate),
52 m_descriptor(descriptor)
54 // std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
55 m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
57 // std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
61 PluginHostAdapter::~PluginHostAdapter()
63 // std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
64 if (m_handle) m_descriptor->cleanup(m_handle);
67 std::vector<std::string>
68 PluginHostAdapter::getPluginPath()
70 std::vector<std::string> path;
73 char *cpath = getenv("VAMP_PATH");
74 if (cpath) envPath = cpath;
77 #define PATH_SEPARATOR ';'
78 #define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
80 #define PATH_SEPARATOR ':'
82 #define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
84 #define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
89 envPath = DEFAULT_VAMP_PATH;
90 char *chome = getenv("HOME");
92 std::string home(chome);
93 std::string::size_type f;
94 while ((f = envPath.find("$HOME")) != std::string::npos &&
95 f < envPath.length()) {
96 envPath.replace(f, 5, home);
100 char *cpfiles = getenv("ProgramFiles");
101 if (!cpfiles) cpfiles = (char *)"C:\\Program Files";
102 std::string pfiles(cpfiles);
103 std::string::size_type f;
104 while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
105 f < envPath.length()) {
106 envPath.replace(f, 14, pfiles);
111 std::string::size_type index = 0, newindex = 0;
113 while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
114 path.push_back(envPath.substr(index, newindex - index));
115 index = newindex + 1;
118 path.push_back(envPath.substr(index));
124 PluginHostAdapter::initialise(size_t channels,
128 if (!m_handle) return false;
129 return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
134 PluginHostAdapter::reset()
137 // std::cerr << "PluginHostAdapter::reset: no handle" << std::endl;
140 // std::cerr << "PluginHostAdapter::reset(" << m_handle << ")" << std::endl;
141 m_descriptor->reset(m_handle);
144 PluginHostAdapter::InputDomain
145 PluginHostAdapter::getInputDomain() const
147 if (m_descriptor->inputDomain == vampFrequencyDomain) {
148 return FrequencyDomain;
155 PluginHostAdapter::getVampApiVersion() const
157 return m_descriptor->vampApiVersion;
161 PluginHostAdapter::getIdentifier() const
163 return m_descriptor->identifier;
167 PluginHostAdapter::getName() const
169 return m_descriptor->name;
173 PluginHostAdapter::getDescription() const
175 return m_descriptor->description;
179 PluginHostAdapter::getMaker() const
181 return m_descriptor->maker;
185 PluginHostAdapter::getPluginVersion() const
187 return m_descriptor->pluginVersion;
191 PluginHostAdapter::getCopyright() const
193 return m_descriptor->copyright;
196 PluginHostAdapter::ParameterList
197 PluginHostAdapter::getParameterDescriptors() const
200 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
201 const VampParameterDescriptor *spd = m_descriptor->parameters[i];
202 ParameterDescriptor pd;
203 pd.identifier = spd->identifier;
205 pd.description = spd->description;
207 pd.minValue = spd->minValue;
208 pd.maxValue = spd->maxValue;
209 pd.defaultValue = spd->defaultValue;
210 pd.isQuantized = spd->isQuantized;
211 pd.quantizeStep = spd->quantizeStep;
212 if (pd.isQuantized && spd->valueNames) {
213 for (unsigned int j = 0; spd->valueNames[j]; ++j) {
214 pd.valueNames.push_back(spd->valueNames[j]);
223 PluginHostAdapter::getParameter(std::string param) const
225 if (!m_handle) return 0.0;
227 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
228 if (param == m_descriptor->parameters[i]->identifier) {
229 return m_descriptor->getParameter(m_handle, i);
237 PluginHostAdapter::setParameter(std::string param,
240 if (!m_handle) return;
242 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
243 if (param == m_descriptor->parameters[i]->identifier) {
244 m_descriptor->setParameter(m_handle, i, value);
250 PluginHostAdapter::ProgramList
251 PluginHostAdapter::getPrograms() const
255 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
256 list.push_back(m_descriptor->programs[i]);
263 PluginHostAdapter::getCurrentProgram() const
265 if (!m_handle) return "";
267 int pn = m_descriptor->getCurrentProgram(m_handle);
268 return m_descriptor->programs[pn];
272 PluginHostAdapter::selectProgram(std::string program)
274 if (!m_handle) return;
276 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
277 if (program == m_descriptor->programs[i]) {
278 m_descriptor->selectProgram(m_handle, i);
285 PluginHostAdapter::getPreferredStepSize() const
287 if (!m_handle) return 0;
288 return m_descriptor->getPreferredStepSize(m_handle);
292 PluginHostAdapter::getPreferredBlockSize() const
294 if (!m_handle) return 0;
295 return m_descriptor->getPreferredBlockSize(m_handle);
299 PluginHostAdapter::getMinChannelCount() const
301 if (!m_handle) return 0;
302 return m_descriptor->getMinChannelCount(m_handle);
306 PluginHostAdapter::getMaxChannelCount() const
308 if (!m_handle) return 0;
309 return m_descriptor->getMaxChannelCount(m_handle);
312 PluginHostAdapter::OutputList
313 PluginHostAdapter::getOutputDescriptors() const
317 // std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
321 unsigned int count = m_descriptor->getOutputCount(m_handle);
323 for (unsigned int i = 0; i < count; ++i) {
324 VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
326 d.identifier = sd->identifier;
328 d.description = sd->description;
330 d.hasFixedBinCount = sd->hasFixedBinCount;
331 d.binCount = sd->binCount;
332 if (d.hasFixedBinCount && sd->binNames) {
333 for (unsigned int j = 0; j < sd->binCount; ++j) {
334 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
337 d.hasKnownExtents = sd->hasKnownExtents;
338 d.minValue = sd->minValue;
339 d.maxValue = sd->maxValue;
340 d.isQuantized = sd->isQuantized;
341 d.quantizeStep = sd->quantizeStep;
343 switch (sd->sampleType) {
344 case vampOneSamplePerStep:
345 d.sampleType = OutputDescriptor::OneSamplePerStep; break;
346 case vampFixedSampleRate:
347 d.sampleType = OutputDescriptor::FixedSampleRate; break;
348 case vampVariableSampleRate:
349 d.sampleType = OutputDescriptor::VariableSampleRate; break;
352 d.sampleRate = sd->sampleRate;
354 if (m_descriptor->vampApiVersion >= 2) {
355 d.hasDuration = sd->hasDuration;
357 d.hasDuration = false;
362 m_descriptor->releaseOutputDescriptor(sd);
368 PluginHostAdapter::FeatureSet
369 PluginHostAdapter::process(const float *const *inputBuffers,
373 if (!m_handle) return fs;
375 int sec = timestamp.sec;
376 int nsec = timestamp.nsec;
378 VampFeatureList *features = m_descriptor->process(m_handle,
382 convertFeatures(features, fs);
383 m_descriptor->releaseFeatureSet(features);
387 PluginHostAdapter::FeatureSet
388 PluginHostAdapter::getRemainingFeatures()
391 if (!m_handle) return fs;
393 VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
395 convertFeatures(features, fs);
396 m_descriptor->releaseFeatureSet(features);
401 PluginHostAdapter::convertFeatures(VampFeatureList *features,
404 if (!features) return;
406 unsigned int outputs = m_descriptor->getOutputCount(m_handle);
408 for (unsigned int i = 0; i < outputs; ++i) {
410 VampFeatureList &list = features[i];
412 if (list.featureCount > 0) {
415 feature.values.reserve(list.features[0].v1.valueCount);
417 for (unsigned int j = 0; j < list.featureCount; ++j) {
419 feature.hasTimestamp = list.features[j].v1.hasTimestamp;
420 feature.timestamp = RealTime(list.features[j].v1.sec,
421 list.features[j].v1.nsec);
422 feature.hasDuration = false;
424 if (m_descriptor->vampApiVersion >= 2) {
425 unsigned int j2 = j + list.featureCount;
426 feature.hasDuration = list.features[j2].v2.hasDuration;
427 feature.duration = RealTime(list.features[j2].v2.durationSec,
428 list.features[j2].v2.durationNsec);
431 for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
432 feature.values.push_back(list.features[j].v1.values[k]);
435 if (list.features[j].v1.label) {
436 feature.label = list.features[j].v1.label;
439 fs[i].push_back(feature);
441 if (list.features[j].v1.valueCount > 0) {
442 feature.values.clear();
445 if (list.features[j].v1.label) {
455 _VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.cpp)