annotate vamp-sdk/PluginHostAdapter.cpp @ 64:9d3272c7db60

* Merge from host-factory-stuff branch: this adds several helper classes in the hostext directory that should make a host's life much easier. This will become version 1.1 of the SDK, eventually.
author cannam
date Fri, 01 Jun 2007 15:10:17 +0000
parents b907557b2fb9
children 1e7ab0399852
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@1 37 #include "PluginHostAdapter.h"
cannam@1 38
cannam@1 39 namespace Vamp
cannam@1 40 {
cannam@1 41
cannam@1 42 PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
cannam@1 43 float inputSampleRate) :
cannam@1 44 Plugin(inputSampleRate),
cannam@1 45 m_descriptor(descriptor)
cannam@1 46 {
cannam@15 47 // std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
cannam@1 48 m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
cannam@15 49 if (!m_handle) {
cannam@15 50 // std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
cannam@15 51 }
cannam@1 52 }
cannam@1 53
cannam@1 54 PluginHostAdapter::~PluginHostAdapter()
cannam@1 55 {
cannam@15 56 // std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
cannam@1 57 if (m_handle) m_descriptor->cleanup(m_handle);
cannam@1 58 }
cannam@1 59
cannam@32 60 std::vector<std::string>
cannam@32 61 PluginHostAdapter::getPluginPath()
cannam@32 62 {
cannam@32 63 std::vector<std::string> path;
cannam@32 64 std::string envPath;
cannam@32 65
cannam@32 66 char *cpath = getenv("VAMP_PATH");
cannam@32 67 if (cpath) envPath = cpath;
cannam@32 68
cannam@32 69 #ifdef _WIN32
cannam@32 70 #define PATH_SEPARATOR ';'
cannam@32 71 #define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
cannam@32 72 #else
cannam@32 73 #define PATH_SEPARATOR ':'
cannam@32 74 #ifdef __APPLE__
cannam@35 75 #define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
cannam@32 76 #else
cannam@35 77 #define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
cannam@32 78 #endif
cannam@32 79 #endif
cannam@32 80
cannam@32 81 if (envPath == "") {
cannam@32 82 envPath = DEFAULT_VAMP_PATH;
cannam@32 83 char *chome = getenv("HOME");
cannam@32 84 if (chome) {
cannam@32 85 std::string home(chome);
cannam@32 86 std::string::size_type f;
cannam@32 87 while ((f = envPath.find("$HOME")) != std::string::npos &&
cannam@32 88 f < envPath.length()) {
cannam@32 89 envPath.replace(f, 5, home);
cannam@32 90 }
cannam@32 91 }
cannam@32 92 #ifdef _WIN32
cannam@32 93 char *cpfiles = getenv("ProgramFiles");
cannam@32 94 if (!cpfiles) cpfiles = "C:\\Program Files";
cannam@32 95 std::string pfiles(cpfiles);
cannam@32 96 std::string::size_type f;
cannam@32 97 while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
cannam@32 98 f < envPath.length()) {
cannam@32 99 envPath.replace(f, 14, pfiles);
cannam@32 100 }
cannam@32 101 #endif
cannam@32 102 }
cannam@32 103
cannam@32 104 std::string::size_type index = 0, newindex = 0;
cannam@32 105
cannam@32 106 while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
cannam@32 107 path.push_back(envPath.substr(index, newindex - index));
cannam@32 108 index = newindex + 1;
cannam@32 109 }
cannam@32 110
cannam@32 111 path.push_back(envPath.substr(index));
cannam@32 112
cannam@32 113 return path;
cannam@32 114 }
cannam@32 115
cannam@1 116 bool
cannam@1 117 PluginHostAdapter::initialise(size_t channels,
cannam@1 118 size_t stepSize,
cannam@1 119 size_t blockSize)
cannam@1 120 {
cannam@1 121 if (!m_handle) return false;
cannam@1 122 return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
cannam@1 123 true : false;
cannam@1 124 }
cannam@1 125
cannam@1 126 void
cannam@1 127 PluginHostAdapter::reset()
cannam@1 128 {
cannam@1 129 if (!m_handle) return;
cannam@1 130 m_descriptor->reset(m_handle);
cannam@1 131 }
cannam@1 132
cannam@1 133 PluginHostAdapter::InputDomain
cannam@1 134 PluginHostAdapter::getInputDomain() const
cannam@1 135 {
cannam@1 136 if (m_descriptor->inputDomain == vampFrequencyDomain) {
cannam@1 137 return FrequencyDomain;
cannam@1 138 } else {
cannam@1 139 return TimeDomain;
cannam@1 140 }
cannam@1 141 }
cannam@1 142
cannam@50 143 unsigned int
cannam@50 144 PluginHostAdapter::getVampApiVersion() const
cannam@50 145 {
cannam@50 146 return m_descriptor->vampApiVersion;
cannam@50 147 }
cannam@50 148
cannam@1 149 std::string
cannam@49 150 PluginHostAdapter::getIdentifier() const
cannam@49 151 {
cannam@49 152 return m_descriptor->identifier;
cannam@49 153 }
cannam@49 154
cannam@49 155 std::string
cannam@1 156 PluginHostAdapter::getName() const
cannam@1 157 {
cannam@1 158 return m_descriptor->name;
cannam@1 159 }
cannam@1 160
cannam@1 161 std::string
cannam@1 162 PluginHostAdapter::getDescription() const
cannam@1 163 {
cannam@1 164 return m_descriptor->description;
cannam@1 165 }
cannam@1 166
cannam@1 167 std::string
cannam@1 168 PluginHostAdapter::getMaker() const
cannam@1 169 {
cannam@1 170 return m_descriptor->maker;
cannam@1 171 }
cannam@1 172
cannam@1 173 int
cannam@1 174 PluginHostAdapter::getPluginVersion() const
cannam@1 175 {
cannam@1 176 return m_descriptor->pluginVersion;
cannam@1 177 }
cannam@1 178
cannam@1 179 std::string
cannam@1 180 PluginHostAdapter::getCopyright() const
cannam@1 181 {
cannam@1 182 return m_descriptor->copyright;
cannam@1 183 }
cannam@1 184
cannam@1 185 PluginHostAdapter::ParameterList
cannam@1 186 PluginHostAdapter::getParameterDescriptors() const
cannam@1 187 {
cannam@1 188 ParameterList list;
cannam@1 189 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@1 190 const VampParameterDescriptor *spd = m_descriptor->parameters[i];
cannam@1 191 ParameterDescriptor pd;
cannam@49 192 pd.identifier = spd->identifier;
cannam@1 193 pd.name = spd->name;
cannam@1 194 pd.description = spd->description;
cannam@1 195 pd.unit = spd->unit;
cannam@1 196 pd.minValue = spd->minValue;
cannam@1 197 pd.maxValue = spd->maxValue;
cannam@1 198 pd.defaultValue = spd->defaultValue;
cannam@1 199 pd.isQuantized = spd->isQuantized;
cannam@1 200 pd.quantizeStep = spd->quantizeStep;
cannam@9 201 if (pd.isQuantized && spd->valueNames) {
cannam@9 202 for (unsigned int j = 0; spd->valueNames[j]; ++j) {
cannam@9 203 pd.valueNames.push_back(spd->valueNames[j]);
cannam@9 204 }
cannam@9 205 }
cannam@1 206 list.push_back(pd);
cannam@1 207 }
cannam@1 208 return list;
cannam@1 209 }
cannam@1 210
cannam@1 211 float
cannam@1 212 PluginHostAdapter::getParameter(std::string param) const
cannam@1 213 {
cannam@1 214 if (!m_handle) return 0.0;
cannam@1 215
cannam@1 216 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 217 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 218 return m_descriptor->getParameter(m_handle, i);
cannam@1 219 }
cannam@1 220 }
cannam@1 221
cannam@1 222 return 0.0;
cannam@1 223 }
cannam@1 224
cannam@1 225 void
cannam@1 226 PluginHostAdapter::setParameter(std::string param,
cannam@1 227 float value)
cannam@1 228 {
cannam@1 229 if (!m_handle) return;
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 m_descriptor->setParameter(m_handle, i, value);
cannam@1 234 return;
cannam@1 235 }
cannam@1 236 }
cannam@1 237 }
cannam@1 238
cannam@1 239 PluginHostAdapter::ProgramList
cannam@1 240 PluginHostAdapter::getPrograms() const
cannam@1 241 {
cannam@1 242 ProgramList list;
cannam@1 243
cannam@1 244 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 245 list.push_back(m_descriptor->programs[i]);
cannam@1 246 }
cannam@1 247
cannam@1 248 return list;
cannam@1 249 }
cannam@1 250
cannam@1 251 std::string
cannam@1 252 PluginHostAdapter::getCurrentProgram() const
cannam@1 253 {
cannam@1 254 if (!m_handle) return "";
cannam@1 255
cannam@1 256 int pn = m_descriptor->getCurrentProgram(m_handle);
cannam@1 257 return m_descriptor->programs[pn];
cannam@1 258 }
cannam@1 259
cannam@1 260 void
cannam@1 261 PluginHostAdapter::selectProgram(std::string program)
cannam@1 262 {
cannam@1 263 if (!m_handle) return;
cannam@1 264
cannam@1 265 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 266 if (program == m_descriptor->programs[i]) {
cannam@1 267 m_descriptor->selectProgram(m_handle, i);
cannam@1 268 return;
cannam@1 269 }
cannam@1 270 }
cannam@1 271 }
cannam@1 272
cannam@1 273 size_t
cannam@1 274 PluginHostAdapter::getPreferredStepSize() const
cannam@1 275 {
cannam@1 276 if (!m_handle) return 0;
cannam@1 277 return m_descriptor->getPreferredStepSize(m_handle);
cannam@1 278 }
cannam@1 279
cannam@1 280 size_t
cannam@1 281 PluginHostAdapter::getPreferredBlockSize() const
cannam@1 282 {
cannam@1 283 if (!m_handle) return 0;
cannam@1 284 return m_descriptor->getPreferredBlockSize(m_handle);
cannam@1 285 }
cannam@1 286
cannam@26 287 size_t
cannam@26 288 PluginHostAdapter::getMinChannelCount() const
cannam@26 289 {
cannam@26 290 if (!m_handle) return 0;
cannam@26 291 return m_descriptor->getMinChannelCount(m_handle);
cannam@26 292 }
cannam@26 293
cannam@26 294 size_t
cannam@26 295 PluginHostAdapter::getMaxChannelCount() const
cannam@26 296 {
cannam@26 297 if (!m_handle) return 0;
cannam@26 298 return m_descriptor->getMaxChannelCount(m_handle);
cannam@26 299 }
cannam@26 300
cannam@1 301 PluginHostAdapter::OutputList
cannam@1 302 PluginHostAdapter::getOutputDescriptors() const
cannam@1 303 {
cannam@1 304 OutputList list;
cannam@15 305 if (!m_handle) {
cannam@15 306 // std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
cannam@15 307 return list;
cannam@15 308 }
cannam@1 309
cannam@1 310 unsigned int count = m_descriptor->getOutputCount(m_handle);
cannam@1 311
cannam@1 312 for (unsigned int i = 0; i < count; ++i) {
cannam@1 313 VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
cannam@1 314 OutputDescriptor d;
cannam@49 315 d.identifier = sd->identifier;
cannam@1 316 d.name = sd->name;
cannam@1 317 d.description = sd->description;
cannam@1 318 d.unit = sd->unit;
cannam@9 319 d.hasFixedBinCount = sd->hasFixedBinCount;
cannam@9 320 d.binCount = sd->binCount;
cannam@9 321 if (d.hasFixedBinCount) {
cannam@9 322 for (unsigned int j = 0; j < sd->binCount; ++j) {
cannam@9 323 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
cannam@9 324 }
cannam@1 325 }
cannam@1 326 d.hasKnownExtents = sd->hasKnownExtents;
cannam@1 327 d.minValue = sd->minValue;
cannam@1 328 d.maxValue = sd->maxValue;
cannam@1 329 d.isQuantized = sd->isQuantized;
cannam@1 330 d.quantizeStep = sd->quantizeStep;
cannam@1 331
cannam@1 332 switch (sd->sampleType) {
cannam@1 333 case vampOneSamplePerStep:
cannam@1 334 d.sampleType = OutputDescriptor::OneSamplePerStep; break;
cannam@1 335 case vampFixedSampleRate:
cannam@1 336 d.sampleType = OutputDescriptor::FixedSampleRate; break;
cannam@1 337 case vampVariableSampleRate:
cannam@1 338 d.sampleType = OutputDescriptor::VariableSampleRate; break;
cannam@1 339 }
cannam@1 340
cannam@1 341 d.sampleRate = sd->sampleRate;
cannam@1 342
cannam@1 343 list.push_back(d);
cannam@1 344
cannam@1 345 m_descriptor->releaseOutputDescriptor(sd);
cannam@1 346 }
cannam@1 347
cannam@1 348 return list;
cannam@1 349 }
cannam@1 350
cannam@1 351 PluginHostAdapter::FeatureSet
cannam@47 352 PluginHostAdapter::process(const float *const *inputBuffers,
cannam@47 353 RealTime timestamp)
cannam@1 354 {
cannam@1 355 FeatureSet fs;
cannam@1 356 if (!m_handle) return fs;
cannam@1 357
cannam@1 358 int sec = timestamp.sec;
cannam@1 359 int nsec = timestamp.nsec;
cannam@1 360
cannam@12 361 VampFeatureList *features = m_descriptor->process(m_handle,
cannam@1 362 inputBuffers,
cannam@1 363 sec, nsec);
cannam@1 364
cannam@1 365 convertFeatures(features, fs);
cannam@1 366 m_descriptor->releaseFeatureSet(features);
cannam@1 367 return fs;
cannam@1 368 }
cannam@1 369
cannam@1 370 PluginHostAdapter::FeatureSet
cannam@1 371 PluginHostAdapter::getRemainingFeatures()
cannam@1 372 {
cannam@1 373 FeatureSet fs;
cannam@1 374 if (!m_handle) return fs;
cannam@1 375
cannam@12 376 VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
cannam@1 377
cannam@1 378 convertFeatures(features, fs);
cannam@1 379 m_descriptor->releaseFeatureSet(features);
cannam@1 380 return fs;
cannam@1 381 }
cannam@1 382
cannam@1 383 void
cannam@12 384 PluginHostAdapter::convertFeatures(VampFeatureList *features,
cannam@1 385 FeatureSet &fs)
cannam@1 386 {
cannam@7 387 if (!features) return;
cannam@7 388
cannam@12 389 unsigned int outputs = m_descriptor->getOutputCount(m_handle);
cannam@12 390
cannam@12 391 for (unsigned int i = 0; i < outputs; ++i) {
cannam@1 392
cannam@12 393 VampFeatureList &list = features[i];
cannam@1 394
cannam@1 395 if (list.featureCount > 0) {
cannam@1 396
cannam@1 397 for (unsigned int j = 0; j < list.featureCount; ++j) {
cannam@1 398
cannam@1 399 Feature feature;
cannam@1 400 feature.hasTimestamp = list.features[j].hasTimestamp;
cannam@1 401 feature.timestamp = RealTime(list.features[j].sec,
cannam@1 402 list.features[j].nsec);
cannam@1 403
cannam@1 404 for (unsigned int k = 0; k < list.features[j].valueCount; ++k) {
cannam@1 405 feature.values.push_back(list.features[j].values[k]);
cannam@1 406 }
cannam@7 407
cannam@7 408 if (list.features[j].label) {
cannam@7 409 feature.label = list.features[j].label;
cannam@7 410 }
cannam@1 411
cannam@1 412 fs[i].push_back(feature);
cannam@1 413 }
cannam@1 414 }
cannam@1 415 }
cannam@1 416 }
cannam@1 417
cannam@1 418 }