annotate src/vamp-hostsdk/PluginHostAdapter.cpp @ 263:4454843ff384

* OK, we're going to have to place the host stuff in its own namespace too. Otherwise our new SV build on OSX fails to load old plugins because they pull in the host namespace PluginBase and thus report the wrong Vamp version... *sigh*
author cannam
date Thu, 20 Nov 2008 15:01:30 +0000
parents 7d678f889789
children 34754c776530
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
cannam@234 40 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 0 )
cannam@234 41 #error Incorrect Vamp SDK header included (not the expected 2.0 SDK)
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);
cannam@1 268 return m_descriptor->programs[pn];
cannam@1 269 }
cannam@1 270
cannam@1 271 void
cannam@1 272 PluginHostAdapter::selectProgram(std::string program)
cannam@1 273 {
cannam@1 274 if (!m_handle) return;
cannam@1 275
cannam@1 276 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 277 if (program == m_descriptor->programs[i]) {
cannam@1 278 m_descriptor->selectProgram(m_handle, i);
cannam@1 279 return;
cannam@1 280 }
cannam@1 281 }
cannam@1 282 }
cannam@1 283
cannam@1 284 size_t
cannam@1 285 PluginHostAdapter::getPreferredStepSize() const
cannam@1 286 {
cannam@1 287 if (!m_handle) return 0;
cannam@1 288 return m_descriptor->getPreferredStepSize(m_handle);
cannam@1 289 }
cannam@1 290
cannam@1 291 size_t
cannam@1 292 PluginHostAdapter::getPreferredBlockSize() const
cannam@1 293 {
cannam@1 294 if (!m_handle) return 0;
cannam@1 295 return m_descriptor->getPreferredBlockSize(m_handle);
cannam@1 296 }
cannam@1 297
cannam@26 298 size_t
cannam@26 299 PluginHostAdapter::getMinChannelCount() const
cannam@26 300 {
cannam@26 301 if (!m_handle) return 0;
cannam@26 302 return m_descriptor->getMinChannelCount(m_handle);
cannam@26 303 }
cannam@26 304
cannam@26 305 size_t
cannam@26 306 PluginHostAdapter::getMaxChannelCount() const
cannam@26 307 {
cannam@26 308 if (!m_handle) return 0;
cannam@26 309 return m_descriptor->getMaxChannelCount(m_handle);
cannam@26 310 }
cannam@26 311
cannam@1 312 PluginHostAdapter::OutputList
cannam@1 313 PluginHostAdapter::getOutputDescriptors() const
cannam@1 314 {
cannam@1 315 OutputList list;
cannam@15 316 if (!m_handle) {
cannam@15 317 // std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
cannam@15 318 return list;
cannam@15 319 }
cannam@1 320
cannam@1 321 unsigned int count = m_descriptor->getOutputCount(m_handle);
cannam@1 322
cannam@1 323 for (unsigned int i = 0; i < count; ++i) {
cannam@1 324 VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
cannam@1 325 OutputDescriptor d;
cannam@49 326 d.identifier = sd->identifier;
cannam@1 327 d.name = sd->name;
cannam@1 328 d.description = sd->description;
cannam@1 329 d.unit = sd->unit;
cannam@9 330 d.hasFixedBinCount = sd->hasFixedBinCount;
cannam@9 331 d.binCount = sd->binCount;
cannam@240 332 if (d.hasFixedBinCount && sd->binNames) {
cannam@9 333 for (unsigned int j = 0; j < sd->binCount; ++j) {
cannam@9 334 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
cannam@9 335 }
cannam@1 336 }
cannam@1 337 d.hasKnownExtents = sd->hasKnownExtents;
cannam@1 338 d.minValue = sd->minValue;
cannam@1 339 d.maxValue = sd->maxValue;
cannam@1 340 d.isQuantized = sd->isQuantized;
cannam@1 341 d.quantizeStep = sd->quantizeStep;
cannam@1 342
cannam@1 343 switch (sd->sampleType) {
cannam@1 344 case vampOneSamplePerStep:
cannam@1 345 d.sampleType = OutputDescriptor::OneSamplePerStep; break;
cannam@1 346 case vampFixedSampleRate:
cannam@1 347 d.sampleType = OutputDescriptor::FixedSampleRate; break;
cannam@1 348 case vampVariableSampleRate:
cannam@1 349 d.sampleType = OutputDescriptor::VariableSampleRate; break;
cannam@1 350 }
cannam@1 351
cannam@1 352 d.sampleRate = sd->sampleRate;
cannam@1 353
cannam@192 354 if (m_descriptor->vampApiVersion >= 2) {
cannam@192 355 d.hasDuration = sd->hasDuration;
cannam@192 356 } else {
cannam@192 357 d.hasDuration = false;
cannam@192 358 }
cannam@192 359
cannam@1 360 list.push_back(d);
cannam@1 361
cannam@1 362 m_descriptor->releaseOutputDescriptor(sd);
cannam@1 363 }
cannam@1 364
cannam@1 365 return list;
cannam@1 366 }
cannam@1 367
cannam@1 368 PluginHostAdapter::FeatureSet
cannam@47 369 PluginHostAdapter::process(const float *const *inputBuffers,
cannam@47 370 RealTime timestamp)
cannam@1 371 {
cannam@1 372 FeatureSet fs;
cannam@1 373 if (!m_handle) return fs;
cannam@1 374
cannam@1 375 int sec = timestamp.sec;
cannam@1 376 int nsec = timestamp.nsec;
cannam@1 377
cannam@12 378 VampFeatureList *features = m_descriptor->process(m_handle,
cannam@1 379 inputBuffers,
cannam@1 380 sec, nsec);
cannam@1 381
cannam@1 382 convertFeatures(features, fs);
cannam@1 383 m_descriptor->releaseFeatureSet(features);
cannam@1 384 return fs;
cannam@1 385 }
cannam@1 386
cannam@1 387 PluginHostAdapter::FeatureSet
cannam@1 388 PluginHostAdapter::getRemainingFeatures()
cannam@1 389 {
cannam@1 390 FeatureSet fs;
cannam@1 391 if (!m_handle) return fs;
cannam@1 392
cannam@12 393 VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
cannam@1 394
cannam@1 395 convertFeatures(features, fs);
cannam@1 396 m_descriptor->releaseFeatureSet(features);
cannam@1 397 return fs;
cannam@1 398 }
cannam@1 399
cannam@1 400 void
cannam@12 401 PluginHostAdapter::convertFeatures(VampFeatureList *features,
cannam@1 402 FeatureSet &fs)
cannam@1 403 {
cannam@7 404 if (!features) return;
cannam@7 405
cannam@12 406 unsigned int outputs = m_descriptor->getOutputCount(m_handle);
cannam@12 407
cannam@12 408 for (unsigned int i = 0; i < outputs; ++i) {
cannam@1 409
cannam@12 410 VampFeatureList &list = features[i];
cannam@1 411
cannam@1 412 if (list.featureCount > 0) {
cannam@1 413
cannam@108 414 Feature feature;
cannam@168 415 feature.values.reserve(list.features[0].v1.valueCount);
cannam@108 416
cannam@1 417 for (unsigned int j = 0; j < list.featureCount; ++j) {
cannam@108 418
cannam@168 419 feature.hasTimestamp = list.features[j].v1.hasTimestamp;
cannam@168 420 feature.timestamp = RealTime(list.features[j].v1.sec,
cannam@168 421 list.features[j].v1.nsec);
cannam@168 422 feature.hasDuration = false;
cannam@1 423
cannam@167 424 if (m_descriptor->vampApiVersion >= 2) {
cannam@168 425 unsigned int j2 = j + list.featureCount;
cannam@168 426 feature.hasDuration = list.features[j2].v2.hasDuration;
cannam@168 427 feature.duration = RealTime(list.features[j2].v2.durationSec,
cannam@168 428 list.features[j2].v2.durationNsec);
cannam@167 429 }
cannam@167 430
cannam@168 431 for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
cannam@168 432 feature.values.push_back(list.features[j].v1.values[k]);
cannam@1 433 }
cannam@7 434
cannam@168 435 if (list.features[j].v1.label) {
cannam@168 436 feature.label = list.features[j].v1.label;
cannam@7 437 }
cannam@1 438
cannam@1 439 fs[i].push_back(feature);
cannam@108 440
cannam@168 441 if (list.features[j].v1.valueCount > 0) {
cannam@108 442 feature.values.clear();
cannam@108 443 }
cannam@108 444
cannam@168 445 if (list.features[j].v1.label) {
cannam@108 446 feature.label = "";
cannam@108 447 }
cannam@1 448 }
cannam@1 449 }
cannam@1 450 }
cannam@1 451 }
cannam@1 452
cannam@1 453 }
cannam@263 454
cannam@263 455 _VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.cpp)
cannam@263 456