annotate src/vamp-hostsdk/PluginHostAdapter.cpp @ 354:e85513153c71

Initialise rate to 0. Otherwise there's a danger plugins will change the SampleType (e.g. to VariableSampleRate) but not set the rate because they don't think they need it (when in fact it needs to be set to 0)
author Chris Cannam
date Thu, 28 Mar 2013 15:49:17 +0000
parents dc40fff9f20b
children 5628c5ec4000
rev   line source
cannam@1 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@1 2
cannam@1 3 /*
cannam@1 4 Vamp
cannam@1 5
cannam@1 6 An API for audio analysis and feature extraction plugins.
cannam@1 7
cannam@1 8 Centre for Digital Music, Queen Mary, University of London.
cannam@1 9 Copyright 2006 Chris Cannam.
cannam@1 10
cannam@1 11 Permission is hereby granted, free of charge, to any person
cannam@1 12 obtaining a copy of this software and associated documentation
cannam@1 13 files (the "Software"), to deal in the Software without
cannam@1 14 restriction, including without limitation the rights to use, copy,
cannam@1 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@1 16 of the Software, and to permit persons to whom the Software is
cannam@1 17 furnished to do so, subject to the following conditions:
cannam@1 18
cannam@1 19 The above copyright notice and this permission notice shall be
cannam@1 20 included in all copies or substantial portions of the Software.
cannam@1 21
cannam@1 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@1 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@1 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@6 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@1 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@1 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@1 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@1 29
cannam@1 30 Except as contained in this notice, the names of the Centre for
cannam@1 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@1 32 shall not be used in advertising or otherwise to promote the sale,
cannam@1 33 use or other dealings in this Software without prior written
cannam@1 34 authorization.
cannam@1 35 */
cannam@1 36
cannam@230 37 #include <vamp-hostsdk/PluginHostAdapter.h>
cannam@130 38 #include <cstdlib>
cannam@1 39
Chris@349 40 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 5 )
cannam@308 41 #error Unexpected version of Vamp SDK header included
cannam@234 42 #endif
cannam@234 43
cannam@263 44 _VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.cpp)
cannam@263 45
cannam@1 46 namespace Vamp
cannam@1 47 {
cannam@1 48
cannam@1 49 PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
cannam@1 50 float inputSampleRate) :
cannam@1 51 Plugin(inputSampleRate),
cannam@1 52 m_descriptor(descriptor)
cannam@1 53 {
cannam@15 54 // std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
cannam@1 55 m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
cannam@15 56 if (!m_handle) {
cannam@15 57 // std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
cannam@15 58 }
cannam@1 59 }
cannam@1 60
cannam@1 61 PluginHostAdapter::~PluginHostAdapter()
cannam@1 62 {
cannam@15 63 // std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
cannam@1 64 if (m_handle) m_descriptor->cleanup(m_handle);
cannam@1 65 }
cannam@1 66
cannam@32 67 std::vector<std::string>
cannam@32 68 PluginHostAdapter::getPluginPath()
cannam@32 69 {
cannam@32 70 std::vector<std::string> path;
cannam@32 71 std::string envPath;
cannam@32 72
cannam@32 73 char *cpath = getenv("VAMP_PATH");
cannam@32 74 if (cpath) envPath = cpath;
cannam@32 75
cannam@32 76 #ifdef _WIN32
cannam@32 77 #define PATH_SEPARATOR ';'
cannam@32 78 #define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
cannam@32 79 #else
cannam@32 80 #define PATH_SEPARATOR ':'
cannam@32 81 #ifdef __APPLE__
cannam@35 82 #define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
cannam@32 83 #else
cannam@35 84 #define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
cannam@32 85 #endif
cannam@32 86 #endif
cannam@32 87
cannam@32 88 if (envPath == "") {
cannam@32 89 envPath = DEFAULT_VAMP_PATH;
cannam@32 90 char *chome = getenv("HOME");
cannam@32 91 if (chome) {
cannam@32 92 std::string home(chome);
cannam@32 93 std::string::size_type f;
cannam@32 94 while ((f = envPath.find("$HOME")) != std::string::npos &&
cannam@32 95 f < envPath.length()) {
cannam@32 96 envPath.replace(f, 5, home);
cannam@32 97 }
cannam@32 98 }
cannam@32 99 #ifdef _WIN32
cannam@32 100 char *cpfiles = getenv("ProgramFiles");
cannam@259 101 if (!cpfiles) cpfiles = (char *)"C:\\Program Files";
cannam@32 102 std::string pfiles(cpfiles);
cannam@32 103 std::string::size_type f;
cannam@32 104 while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
cannam@32 105 f < envPath.length()) {
cannam@32 106 envPath.replace(f, 14, pfiles);
cannam@32 107 }
cannam@32 108 #endif
cannam@32 109 }
cannam@32 110
cannam@32 111 std::string::size_type index = 0, newindex = 0;
cannam@32 112
cannam@32 113 while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
cannam@32 114 path.push_back(envPath.substr(index, newindex - index));
cannam@32 115 index = newindex + 1;
cannam@32 116 }
cannam@32 117
cannam@32 118 path.push_back(envPath.substr(index));
cannam@32 119
cannam@32 120 return path;
cannam@32 121 }
cannam@32 122
cannam@1 123 bool
cannam@1 124 PluginHostAdapter::initialise(size_t channels,
cannam@1 125 size_t stepSize,
cannam@1 126 size_t blockSize)
cannam@1 127 {
cannam@1 128 if (!m_handle) return false;
cannam@1 129 return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
cannam@1 130 true : false;
cannam@1 131 }
cannam@1 132
cannam@1 133 void
cannam@1 134 PluginHostAdapter::reset()
cannam@1 135 {
cannam@197 136 if (!m_handle) {
cannam@197 137 // std::cerr << "PluginHostAdapter::reset: no handle" << std::endl;
cannam@197 138 return;
cannam@197 139 }
cannam@197 140 // std::cerr << "PluginHostAdapter::reset(" << m_handle << ")" << std::endl;
cannam@1 141 m_descriptor->reset(m_handle);
cannam@1 142 }
cannam@1 143
cannam@1 144 PluginHostAdapter::InputDomain
cannam@1 145 PluginHostAdapter::getInputDomain() const
cannam@1 146 {
cannam@1 147 if (m_descriptor->inputDomain == vampFrequencyDomain) {
cannam@1 148 return FrequencyDomain;
cannam@1 149 } else {
cannam@1 150 return TimeDomain;
cannam@1 151 }
cannam@1 152 }
cannam@1 153
cannam@50 154 unsigned int
cannam@50 155 PluginHostAdapter::getVampApiVersion() const
cannam@50 156 {
cannam@50 157 return m_descriptor->vampApiVersion;
cannam@50 158 }
cannam@50 159
cannam@1 160 std::string
cannam@49 161 PluginHostAdapter::getIdentifier() const
cannam@49 162 {
cannam@49 163 return m_descriptor->identifier;
cannam@49 164 }
cannam@49 165
cannam@49 166 std::string
cannam@1 167 PluginHostAdapter::getName() const
cannam@1 168 {
cannam@1 169 return m_descriptor->name;
cannam@1 170 }
cannam@1 171
cannam@1 172 std::string
cannam@1 173 PluginHostAdapter::getDescription() const
cannam@1 174 {
cannam@1 175 return m_descriptor->description;
cannam@1 176 }
cannam@1 177
cannam@1 178 std::string
cannam@1 179 PluginHostAdapter::getMaker() const
cannam@1 180 {
cannam@1 181 return m_descriptor->maker;
cannam@1 182 }
cannam@1 183
cannam@1 184 int
cannam@1 185 PluginHostAdapter::getPluginVersion() const
cannam@1 186 {
cannam@1 187 return m_descriptor->pluginVersion;
cannam@1 188 }
cannam@1 189
cannam@1 190 std::string
cannam@1 191 PluginHostAdapter::getCopyright() const
cannam@1 192 {
cannam@1 193 return m_descriptor->copyright;
cannam@1 194 }
cannam@1 195
cannam@1 196 PluginHostAdapter::ParameterList
cannam@1 197 PluginHostAdapter::getParameterDescriptors() const
cannam@1 198 {
cannam@1 199 ParameterList list;
cannam@1 200 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@1 201 const VampParameterDescriptor *spd = m_descriptor->parameters[i];
cannam@1 202 ParameterDescriptor pd;
cannam@49 203 pd.identifier = spd->identifier;
cannam@1 204 pd.name = spd->name;
cannam@1 205 pd.description = spd->description;
cannam@1 206 pd.unit = spd->unit;
cannam@1 207 pd.minValue = spd->minValue;
cannam@1 208 pd.maxValue = spd->maxValue;
cannam@1 209 pd.defaultValue = spd->defaultValue;
cannam@1 210 pd.isQuantized = spd->isQuantized;
cannam@1 211 pd.quantizeStep = spd->quantizeStep;
cannam@9 212 if (pd.isQuantized && spd->valueNames) {
cannam@9 213 for (unsigned int j = 0; spd->valueNames[j]; ++j) {
cannam@9 214 pd.valueNames.push_back(spd->valueNames[j]);
cannam@9 215 }
cannam@9 216 }
cannam@1 217 list.push_back(pd);
cannam@1 218 }
cannam@1 219 return list;
cannam@1 220 }
cannam@1 221
cannam@1 222 float
cannam@1 223 PluginHostAdapter::getParameter(std::string param) const
cannam@1 224 {
cannam@1 225 if (!m_handle) return 0.0;
cannam@1 226
cannam@1 227 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 228 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 229 return m_descriptor->getParameter(m_handle, i);
cannam@1 230 }
cannam@1 231 }
cannam@1 232
cannam@1 233 return 0.0;
cannam@1 234 }
cannam@1 235
cannam@1 236 void
cannam@1 237 PluginHostAdapter::setParameter(std::string param,
cannam@1 238 float value)
cannam@1 239 {
cannam@1 240 if (!m_handle) return;
cannam@1 241
cannam@1 242 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 243 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 244 m_descriptor->setParameter(m_handle, i, value);
cannam@1 245 return;
cannam@1 246 }
cannam@1 247 }
cannam@1 248 }
cannam@1 249
cannam@1 250 PluginHostAdapter::ProgramList
cannam@1 251 PluginHostAdapter::getPrograms() const
cannam@1 252 {
cannam@1 253 ProgramList list;
cannam@1 254
cannam@1 255 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 256 list.push_back(m_descriptor->programs[i]);
cannam@1 257 }
cannam@1 258
cannam@1 259 return list;
cannam@1 260 }
cannam@1 261
cannam@1 262 std::string
cannam@1 263 PluginHostAdapter::getCurrentProgram() const
cannam@1 264 {
cannam@1 265 if (!m_handle) return "";
cannam@1 266
cannam@1 267 int pn = m_descriptor->getCurrentProgram(m_handle);
Chris@345 268 if (pn < (int)m_descriptor->programCount) {
Chris@345 269 return m_descriptor->programs[pn];
Chris@345 270 } else {
Chris@345 271 return "";
Chris@345 272 }
cannam@1 273 }
cannam@1 274
cannam@1 275 void
cannam@1 276 PluginHostAdapter::selectProgram(std::string program)
cannam@1 277 {
cannam@1 278 if (!m_handle) return;
cannam@1 279
cannam@1 280 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 281 if (program == m_descriptor->programs[i]) {
cannam@1 282 m_descriptor->selectProgram(m_handle, i);
cannam@1 283 return;
cannam@1 284 }
cannam@1 285 }
cannam@1 286 }
cannam@1 287
cannam@1 288 size_t
cannam@1 289 PluginHostAdapter::getPreferredStepSize() const
cannam@1 290 {
cannam@1 291 if (!m_handle) return 0;
cannam@1 292 return m_descriptor->getPreferredStepSize(m_handle);
cannam@1 293 }
cannam@1 294
cannam@1 295 size_t
cannam@1 296 PluginHostAdapter::getPreferredBlockSize() const
cannam@1 297 {
cannam@1 298 if (!m_handle) return 0;
cannam@1 299 return m_descriptor->getPreferredBlockSize(m_handle);
cannam@1 300 }
cannam@1 301
cannam@26 302 size_t
cannam@26 303 PluginHostAdapter::getMinChannelCount() const
cannam@26 304 {
cannam@26 305 if (!m_handle) return 0;
cannam@26 306 return m_descriptor->getMinChannelCount(m_handle);
cannam@26 307 }
cannam@26 308
cannam@26 309 size_t
cannam@26 310 PluginHostAdapter::getMaxChannelCount() const
cannam@26 311 {
cannam@26 312 if (!m_handle) return 0;
cannam@26 313 return m_descriptor->getMaxChannelCount(m_handle);
cannam@26 314 }
cannam@26 315
cannam@1 316 PluginHostAdapter::OutputList
cannam@1 317 PluginHostAdapter::getOutputDescriptors() const
cannam@1 318 {
cannam@1 319 OutputList list;
cannam@15 320 if (!m_handle) {
cannam@15 321 // std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
cannam@15 322 return list;
cannam@15 323 }
cannam@1 324
cannam@1 325 unsigned int count = m_descriptor->getOutputCount(m_handle);
cannam@1 326
cannam@1 327 for (unsigned int i = 0; i < count; ++i) {
cannam@1 328 VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
cannam@1 329 OutputDescriptor d;
cannam@49 330 d.identifier = sd->identifier;
cannam@1 331 d.name = sd->name;
cannam@1 332 d.description = sd->description;
cannam@1 333 d.unit = sd->unit;
cannam@9 334 d.hasFixedBinCount = sd->hasFixedBinCount;
cannam@9 335 d.binCount = sd->binCount;
cannam@240 336 if (d.hasFixedBinCount && sd->binNames) {
cannam@9 337 for (unsigned int j = 0; j < sd->binCount; ++j) {
cannam@9 338 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
cannam@9 339 }
cannam@1 340 }
cannam@1 341 d.hasKnownExtents = sd->hasKnownExtents;
cannam@1 342 d.minValue = sd->minValue;
cannam@1 343 d.maxValue = sd->maxValue;
cannam@1 344 d.isQuantized = sd->isQuantized;
cannam@1 345 d.quantizeStep = sd->quantizeStep;
cannam@1 346
cannam@1 347 switch (sd->sampleType) {
cannam@1 348 case vampOneSamplePerStep:
cannam@1 349 d.sampleType = OutputDescriptor::OneSamplePerStep; break;
cannam@1 350 case vampFixedSampleRate:
cannam@1 351 d.sampleType = OutputDescriptor::FixedSampleRate; break;
cannam@1 352 case vampVariableSampleRate:
cannam@1 353 d.sampleType = OutputDescriptor::VariableSampleRate; break;
cannam@1 354 }
cannam@1 355
cannam@1 356 d.sampleRate = sd->sampleRate;
cannam@1 357
cannam@192 358 if (m_descriptor->vampApiVersion >= 2) {
cannam@192 359 d.hasDuration = sd->hasDuration;
cannam@192 360 } else {
cannam@192 361 d.hasDuration = false;
cannam@192 362 }
cannam@192 363
cannam@1 364 list.push_back(d);
cannam@1 365
cannam@1 366 m_descriptor->releaseOutputDescriptor(sd);
cannam@1 367 }
cannam@1 368
cannam@1 369 return list;
cannam@1 370 }
cannam@1 371
cannam@1 372 PluginHostAdapter::FeatureSet
cannam@47 373 PluginHostAdapter::process(const float *const *inputBuffers,
cannam@47 374 RealTime timestamp)
cannam@1 375 {
cannam@1 376 FeatureSet fs;
cannam@1 377 if (!m_handle) return fs;
cannam@1 378
cannam@1 379 int sec = timestamp.sec;
cannam@1 380 int nsec = timestamp.nsec;
cannam@1 381
cannam@12 382 VampFeatureList *features = m_descriptor->process(m_handle,
cannam@1 383 inputBuffers,
cannam@1 384 sec, nsec);
cannam@1 385
cannam@1 386 convertFeatures(features, fs);
cannam@1 387 m_descriptor->releaseFeatureSet(features);
cannam@1 388 return fs;
cannam@1 389 }
cannam@1 390
cannam@1 391 PluginHostAdapter::FeatureSet
cannam@1 392 PluginHostAdapter::getRemainingFeatures()
cannam@1 393 {
cannam@1 394 FeatureSet fs;
cannam@1 395 if (!m_handle) return fs;
cannam@1 396
cannam@12 397 VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
cannam@1 398
cannam@1 399 convertFeatures(features, fs);
cannam@1 400 m_descriptor->releaseFeatureSet(features);
cannam@1 401 return fs;
cannam@1 402 }
cannam@1 403
cannam@1 404 void
cannam@12 405 PluginHostAdapter::convertFeatures(VampFeatureList *features,
cannam@1 406 FeatureSet &fs)
cannam@1 407 {
cannam@7 408 if (!features) return;
cannam@7 409
cannam@12 410 unsigned int outputs = m_descriptor->getOutputCount(m_handle);
cannam@12 411
cannam@12 412 for (unsigned int i = 0; i < outputs; ++i) {
cannam@1 413
cannam@12 414 VampFeatureList &list = features[i];
cannam@1 415
cannam@1 416 if (list.featureCount > 0) {
cannam@1 417
cannam@108 418 Feature feature;
cannam@168 419 feature.values.reserve(list.features[0].v1.valueCount);
cannam@108 420
cannam@1 421 for (unsigned int j = 0; j < list.featureCount; ++j) {
cannam@108 422
cannam@168 423 feature.hasTimestamp = list.features[j].v1.hasTimestamp;
cannam@168 424 feature.timestamp = RealTime(list.features[j].v1.sec,
cannam@168 425 list.features[j].v1.nsec);
cannam@168 426 feature.hasDuration = false;
cannam@1 427
cannam@167 428 if (m_descriptor->vampApiVersion >= 2) {
cannam@168 429 unsigned int j2 = j + list.featureCount;
cannam@168 430 feature.hasDuration = list.features[j2].v2.hasDuration;
cannam@168 431 feature.duration = RealTime(list.features[j2].v2.durationSec,
cannam@168 432 list.features[j2].v2.durationNsec);
cannam@167 433 }
cannam@167 434
cannam@168 435 for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
cannam@168 436 feature.values.push_back(list.features[j].v1.values[k]);
cannam@1 437 }
cannam@7 438
cannam@168 439 if (list.features[j].v1.label) {
cannam@168 440 feature.label = list.features[j].v1.label;
cannam@7 441 }
cannam@1 442
cannam@1 443 fs[i].push_back(feature);
cannam@108 444
cannam@168 445 if (list.features[j].v1.valueCount > 0) {
cannam@108 446 feature.values.clear();
cannam@108 447 }
cannam@108 448
cannam@168 449 if (list.features[j].v1.label) {
cannam@108 450 feature.label = "";
cannam@108 451 }
cannam@1 452 }
cannam@1 453 }
cannam@1 454 }
cannam@1 455 }
cannam@1 456
cannam@1 457 }
cannam@263 458
cannam@263 459 _VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.cpp)
cannam@263 460