annotate src/vamp-hostsdk/PluginHostAdapter.cpp @ 434:e979a9c4ffb6 vampipe

Switch from Cross FFT with option of FFTW build, to KissFFT only (code bundled). This is much faster than the default build and simpler than managing two options.
author Chris Cannam
date Tue, 16 Aug 2016 16:04:09 +0100
parents abdf03252c8a
children 54277cb679ff
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@424 40 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 7 )
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;
Chris@421 129 return m_descriptor->initialise
Chris@421 130 (m_handle,
Chris@421 131 (unsigned int)channels,
Chris@421 132 (unsigned int)stepSize,
Chris@421 133 (unsigned int)blockSize) ?
cannam@1 134 true : false;
cannam@1 135 }
cannam@1 136
cannam@1 137 void
cannam@1 138 PluginHostAdapter::reset()
cannam@1 139 {
cannam@197 140 if (!m_handle) {
cannam@197 141 // std::cerr << "PluginHostAdapter::reset: no handle" << std::endl;
cannam@197 142 return;
cannam@197 143 }
cannam@197 144 // std::cerr << "PluginHostAdapter::reset(" << m_handle << ")" << std::endl;
cannam@1 145 m_descriptor->reset(m_handle);
cannam@1 146 }
cannam@1 147
cannam@1 148 PluginHostAdapter::InputDomain
cannam@1 149 PluginHostAdapter::getInputDomain() const
cannam@1 150 {
cannam@1 151 if (m_descriptor->inputDomain == vampFrequencyDomain) {
cannam@1 152 return FrequencyDomain;
cannam@1 153 } else {
cannam@1 154 return TimeDomain;
cannam@1 155 }
cannam@1 156 }
cannam@1 157
cannam@50 158 unsigned int
cannam@50 159 PluginHostAdapter::getVampApiVersion() const
cannam@50 160 {
cannam@50 161 return m_descriptor->vampApiVersion;
cannam@50 162 }
cannam@50 163
cannam@1 164 std::string
cannam@49 165 PluginHostAdapter::getIdentifier() const
cannam@49 166 {
cannam@49 167 return m_descriptor->identifier;
cannam@49 168 }
cannam@49 169
cannam@49 170 std::string
cannam@1 171 PluginHostAdapter::getName() const
cannam@1 172 {
cannam@1 173 return m_descriptor->name;
cannam@1 174 }
cannam@1 175
cannam@1 176 std::string
cannam@1 177 PluginHostAdapter::getDescription() const
cannam@1 178 {
cannam@1 179 return m_descriptor->description;
cannam@1 180 }
cannam@1 181
cannam@1 182 std::string
cannam@1 183 PluginHostAdapter::getMaker() const
cannam@1 184 {
cannam@1 185 return m_descriptor->maker;
cannam@1 186 }
cannam@1 187
cannam@1 188 int
cannam@1 189 PluginHostAdapter::getPluginVersion() const
cannam@1 190 {
cannam@1 191 return m_descriptor->pluginVersion;
cannam@1 192 }
cannam@1 193
cannam@1 194 std::string
cannam@1 195 PluginHostAdapter::getCopyright() const
cannam@1 196 {
cannam@1 197 return m_descriptor->copyright;
cannam@1 198 }
cannam@1 199
cannam@1 200 PluginHostAdapter::ParameterList
cannam@1 201 PluginHostAdapter::getParameterDescriptors() const
cannam@1 202 {
cannam@1 203 ParameterList list;
cannam@1 204 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@1 205 const VampParameterDescriptor *spd = m_descriptor->parameters[i];
cannam@1 206 ParameterDescriptor pd;
cannam@49 207 pd.identifier = spd->identifier;
cannam@1 208 pd.name = spd->name;
cannam@1 209 pd.description = spd->description;
cannam@1 210 pd.unit = spd->unit;
cannam@1 211 pd.minValue = spd->minValue;
cannam@1 212 pd.maxValue = spd->maxValue;
cannam@1 213 pd.defaultValue = spd->defaultValue;
cannam@1 214 pd.isQuantized = spd->isQuantized;
cannam@1 215 pd.quantizeStep = spd->quantizeStep;
cannam@9 216 if (pd.isQuantized && spd->valueNames) {
cannam@9 217 for (unsigned int j = 0; spd->valueNames[j]; ++j) {
cannam@9 218 pd.valueNames.push_back(spd->valueNames[j]);
cannam@9 219 }
cannam@9 220 }
cannam@1 221 list.push_back(pd);
cannam@1 222 }
cannam@1 223 return list;
cannam@1 224 }
cannam@1 225
cannam@1 226 float
cannam@1 227 PluginHostAdapter::getParameter(std::string param) const
cannam@1 228 {
cannam@1 229 if (!m_handle) return 0.0;
cannam@1 230
cannam@1 231 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 232 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 233 return m_descriptor->getParameter(m_handle, i);
cannam@1 234 }
cannam@1 235 }
cannam@1 236
cannam@1 237 return 0.0;
cannam@1 238 }
cannam@1 239
cannam@1 240 void
cannam@1 241 PluginHostAdapter::setParameter(std::string param,
cannam@1 242 float value)
cannam@1 243 {
cannam@1 244 if (!m_handle) return;
cannam@1 245
cannam@1 246 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 247 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 248 m_descriptor->setParameter(m_handle, i, value);
cannam@1 249 return;
cannam@1 250 }
cannam@1 251 }
cannam@1 252 }
cannam@1 253
cannam@1 254 PluginHostAdapter::ProgramList
cannam@1 255 PluginHostAdapter::getPrograms() const
cannam@1 256 {
cannam@1 257 ProgramList list;
cannam@1 258
cannam@1 259 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 260 list.push_back(m_descriptor->programs[i]);
cannam@1 261 }
cannam@1 262
cannam@1 263 return list;
cannam@1 264 }
cannam@1 265
cannam@1 266 std::string
cannam@1 267 PluginHostAdapter::getCurrentProgram() const
cannam@1 268 {
cannam@1 269 if (!m_handle) return "";
cannam@1 270
cannam@1 271 int pn = m_descriptor->getCurrentProgram(m_handle);
Chris@345 272 if (pn < (int)m_descriptor->programCount) {
Chris@345 273 return m_descriptor->programs[pn];
Chris@345 274 } else {
Chris@345 275 return "";
Chris@345 276 }
cannam@1 277 }
cannam@1 278
cannam@1 279 void
cannam@1 280 PluginHostAdapter::selectProgram(std::string program)
cannam@1 281 {
cannam@1 282 if (!m_handle) return;
cannam@1 283
cannam@1 284 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 285 if (program == m_descriptor->programs[i]) {
cannam@1 286 m_descriptor->selectProgram(m_handle, i);
cannam@1 287 return;
cannam@1 288 }
cannam@1 289 }
cannam@1 290 }
cannam@1 291
cannam@1 292 size_t
cannam@1 293 PluginHostAdapter::getPreferredStepSize() const
cannam@1 294 {
cannam@1 295 if (!m_handle) return 0;
cannam@1 296 return m_descriptor->getPreferredStepSize(m_handle);
cannam@1 297 }
cannam@1 298
cannam@1 299 size_t
cannam@1 300 PluginHostAdapter::getPreferredBlockSize() const
cannam@1 301 {
cannam@1 302 if (!m_handle) return 0;
cannam@1 303 return m_descriptor->getPreferredBlockSize(m_handle);
cannam@1 304 }
cannam@1 305
cannam@26 306 size_t
cannam@26 307 PluginHostAdapter::getMinChannelCount() const
cannam@26 308 {
cannam@26 309 if (!m_handle) return 0;
cannam@26 310 return m_descriptor->getMinChannelCount(m_handle);
cannam@26 311 }
cannam@26 312
cannam@26 313 size_t
cannam@26 314 PluginHostAdapter::getMaxChannelCount() const
cannam@26 315 {
cannam@26 316 if (!m_handle) return 0;
cannam@26 317 return m_descriptor->getMaxChannelCount(m_handle);
cannam@26 318 }
cannam@26 319
cannam@1 320 PluginHostAdapter::OutputList
cannam@1 321 PluginHostAdapter::getOutputDescriptors() const
cannam@1 322 {
cannam@1 323 OutputList list;
cannam@15 324 if (!m_handle) {
cannam@15 325 // std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
cannam@15 326 return list;
cannam@15 327 }
cannam@1 328
cannam@1 329 unsigned int count = m_descriptor->getOutputCount(m_handle);
cannam@1 330
cannam@1 331 for (unsigned int i = 0; i < count; ++i) {
cannam@1 332 VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
cannam@1 333 OutputDescriptor d;
cannam@49 334 d.identifier = sd->identifier;
cannam@1 335 d.name = sd->name;
cannam@1 336 d.description = sd->description;
cannam@1 337 d.unit = sd->unit;
cannam@9 338 d.hasFixedBinCount = sd->hasFixedBinCount;
cannam@9 339 d.binCount = sd->binCount;
cannam@240 340 if (d.hasFixedBinCount && sd->binNames) {
cannam@9 341 for (unsigned int j = 0; j < sd->binCount; ++j) {
cannam@9 342 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
cannam@9 343 }
cannam@1 344 }
cannam@1 345 d.hasKnownExtents = sd->hasKnownExtents;
cannam@1 346 d.minValue = sd->minValue;
cannam@1 347 d.maxValue = sd->maxValue;
cannam@1 348 d.isQuantized = sd->isQuantized;
cannam@1 349 d.quantizeStep = sd->quantizeStep;
cannam@1 350
cannam@1 351 switch (sd->sampleType) {
cannam@1 352 case vampOneSamplePerStep:
cannam@1 353 d.sampleType = OutputDescriptor::OneSamplePerStep; break;
cannam@1 354 case vampFixedSampleRate:
cannam@1 355 d.sampleType = OutputDescriptor::FixedSampleRate; break;
cannam@1 356 case vampVariableSampleRate:
cannam@1 357 d.sampleType = OutputDescriptor::VariableSampleRate; break;
cannam@1 358 }
cannam@1 359
cannam@1 360 d.sampleRate = sd->sampleRate;
cannam@1 361
cannam@192 362 if (m_descriptor->vampApiVersion >= 2) {
cannam@192 363 d.hasDuration = sd->hasDuration;
cannam@192 364 } else {
cannam@192 365 d.hasDuration = false;
cannam@192 366 }
cannam@192 367
cannam@1 368 list.push_back(d);
cannam@1 369
cannam@1 370 m_descriptor->releaseOutputDescriptor(sd);
cannam@1 371 }
cannam@1 372
cannam@1 373 return list;
cannam@1 374 }
cannam@1 375
cannam@1 376 PluginHostAdapter::FeatureSet
cannam@47 377 PluginHostAdapter::process(const float *const *inputBuffers,
cannam@47 378 RealTime timestamp)
cannam@1 379 {
cannam@1 380 FeatureSet fs;
cannam@1 381 if (!m_handle) return fs;
cannam@1 382
cannam@1 383 int sec = timestamp.sec;
cannam@1 384 int nsec = timestamp.nsec;
cannam@1 385
cannam@12 386 VampFeatureList *features = m_descriptor->process(m_handle,
cannam@1 387 inputBuffers,
cannam@1 388 sec, nsec);
cannam@1 389
cannam@1 390 convertFeatures(features, fs);
cannam@1 391 m_descriptor->releaseFeatureSet(features);
cannam@1 392 return fs;
cannam@1 393 }
cannam@1 394
cannam@1 395 PluginHostAdapter::FeatureSet
cannam@1 396 PluginHostAdapter::getRemainingFeatures()
cannam@1 397 {
cannam@1 398 FeatureSet fs;
cannam@1 399 if (!m_handle) return fs;
cannam@1 400
cannam@12 401 VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
cannam@1 402
cannam@1 403 convertFeatures(features, fs);
cannam@1 404 m_descriptor->releaseFeatureSet(features);
cannam@1 405 return fs;
cannam@1 406 }
cannam@1 407
cannam@1 408 void
cannam@12 409 PluginHostAdapter::convertFeatures(VampFeatureList *features,
cannam@1 410 FeatureSet &fs)
cannam@1 411 {
cannam@7 412 if (!features) return;
cannam@7 413
cannam@12 414 unsigned int outputs = m_descriptor->getOutputCount(m_handle);
cannam@12 415
cannam@12 416 for (unsigned int i = 0; i < outputs; ++i) {
cannam@1 417
cannam@12 418 VampFeatureList &list = features[i];
cannam@1 419
cannam@1 420 if (list.featureCount > 0) {
cannam@1 421
cannam@108 422 Feature feature;
cannam@168 423 feature.values.reserve(list.features[0].v1.valueCount);
cannam@108 424
cannam@1 425 for (unsigned int j = 0; j < list.featureCount; ++j) {
cannam@108 426
cannam@168 427 feature.hasTimestamp = list.features[j].v1.hasTimestamp;
cannam@168 428 feature.timestamp = RealTime(list.features[j].v1.sec,
cannam@168 429 list.features[j].v1.nsec);
cannam@168 430 feature.hasDuration = false;
cannam@1 431
cannam@167 432 if (m_descriptor->vampApiVersion >= 2) {
cannam@168 433 unsigned int j2 = j + list.featureCount;
cannam@168 434 feature.hasDuration = list.features[j2].v2.hasDuration;
cannam@168 435 feature.duration = RealTime(list.features[j2].v2.durationSec,
cannam@168 436 list.features[j2].v2.durationNsec);
cannam@167 437 }
cannam@167 438
cannam@168 439 for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
cannam@168 440 feature.values.push_back(list.features[j].v1.values[k]);
cannam@1 441 }
cannam@7 442
cannam@168 443 if (list.features[j].v1.label) {
cannam@168 444 feature.label = list.features[j].v1.label;
cannam@7 445 }
cannam@1 446
cannam@1 447 fs[i].push_back(feature);
cannam@108 448
cannam@168 449 if (list.features[j].v1.valueCount > 0) {
cannam@108 450 feature.values.clear();
cannam@108 451 }
cannam@108 452
cannam@168 453 if (list.features[j].v1.label) {
cannam@108 454 feature.label = "";
cannam@108 455 }
cannam@1 456 }
cannam@1 457 }
cannam@1 458 }
cannam@1 459 }
cannam@1 460
cannam@1 461 }
cannam@263 462
cannam@263 463 _VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.cpp)
cannam@263 464