VampPluginSDK
2.1
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Vamp 00005 00006 An API for audio analysis and feature extraction plugins. 00007 00008 Centre for Digital Music, Queen Mary, University of London. 00009 Copyright 2006 Chris Cannam, copyright 2007-2008 QMUL. 00010 00011 Permission is hereby granted, free of charge, to any person 00012 obtaining a copy of this software and associated documentation 00013 files (the "Software"), to deal in the Software without 00014 restriction, including without limitation the rights to use, copy, 00015 modify, merge, publish, distribute, sublicense, and/or sell copies 00016 of the Software, and to permit persons to whom the Software is 00017 furnished to do so, subject to the following conditions: 00018 00019 The above copyright notice and this permission notice shall be 00020 included in all copies or substantial portions of the Software. 00021 00022 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00023 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00024 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00025 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 00026 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 00027 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 00028 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00029 00030 Except as contained in this notice, the names of the Centre for 00031 Digital Music; Queen Mary, University of London; and Chris Cannam 00032 shall not be used in advertising or otherwise to promote the sale, 00033 use or other dealings in this Software without prior written 00034 authorization. 00035 */ 00036 00037 00038 /* 00039 * This "simple" Vamp plugin host is no longer as simple as it was; it 00040 * now has a lot of options and includes a lot of code to handle the 00041 * various useful listing modes it supports. 00042 * 00043 * However, the runPlugin function still contains a reasonable 00044 * implementation of a fairly generic Vamp plugin host capable of 00045 * evaluating a given output on a given plugin for a sound file read 00046 * via libsndfile. 00047 */ 00048 00049 #include <vamp-hostsdk/PluginHostAdapter.h> 00050 #include <vamp-hostsdk/PluginInputDomainAdapter.h> 00051 #include <vamp-hostsdk/PluginLoader.h> 00052 00053 #include <iostream> 00054 #include <fstream> 00055 #include <set> 00056 #include <sndfile.h> 00057 00058 #include <cstring> 00059 #include <cstdlib> 00060 00061 #include "system.h" 00062 00063 #include <cmath> 00064 00065 using namespace std; 00066 00067 using Vamp::Plugin; 00068 using Vamp::PluginHostAdapter; 00069 using Vamp::RealTime; 00070 using Vamp::HostExt::PluginLoader; 00071 using Vamp::HostExt::PluginWrapper; 00072 using Vamp::HostExt::PluginInputDomainAdapter; 00073 00074 #define HOST_VERSION "1.4" 00075 00076 enum Verbosity { 00077 PluginIds, 00078 PluginOutputIds, 00079 PluginInformation, 00080 PluginInformationDetailed 00081 }; 00082 00083 void printFeatures(int, int, int, Plugin::FeatureSet, ofstream *, bool frames); 00084 void transformInput(float *, size_t); 00085 void fft(unsigned int, bool, double *, double *, double *, double *); 00086 void printPluginPath(bool verbose); 00087 void printPluginCategoryList(); 00088 void enumeratePlugins(Verbosity); 00089 void listPluginsInLibrary(string soname); 00090 int runPlugin(string myname, string soname, string id, string output, 00091 int outputNo, string inputFile, string outfilename, bool frames); 00092 00093 void usage(const char *name) 00094 { 00095 cerr << "\n" 00096 << name << ": A command-line host for Vamp audio analysis plugins.\n\n" 00097 "Centre for Digital Music, Queen Mary, University of London.\n" 00098 "Copyright 2006-2009 Chris Cannam and QMUL.\n" 00099 "Freely redistributable; published under a BSD-style license.\n\n" 00100 "Usage:\n\n" 00101 " " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin[:output] file.wav [-o out.txt]\n" 00102 " " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin file.wav [outputno] [-o out.txt]\n\n" 00103 " -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n" 00104 " audio data in \"file.wav\", retrieving the named \"output\", or output\n" 00105 " number \"outputno\" (the first output by default) and dumping it to\n" 00106 " standard output, or to \"out.txt\" if the -o option is given.\n\n" 00107 " \"pluginlibrary\" should be a library name, not a file path; the\n" 00108 " standard Vamp library search path will be used to locate it. If\n" 00109 " a file path is supplied, the directory part(s) will be ignored.\n\n" 00110 " If the -s option is given, results will be labelled with the audio\n" 00111 " sample frame at which they occur. Otherwise, they will be labelled\n" 00112 " with time in seconds.\n\n" 00113 " " << name << " -l\n" 00114 " " << name << " --list\n\n" 00115 " -- List the plugin libraries and Vamp plugins in the library search path\n" 00116 " in a verbose human-readable format.\n\n" 00117 " " << name << " --list-full\n\n" 00118 " -- List all data reported by all the Vamp plugins in the library search\n" 00119 " path in a very verbose human-readable format.\n\n" 00120 " " << name << " --list-ids\n\n" 00121 " -- List the plugins in the search path in a terse machine-readable format,\n" 00122 " in the form vamp:soname:identifier.\n\n" 00123 " " << name << " --list-outputs\n\n" 00124 " -- List the outputs for plugins in the search path in a machine-readable\n" 00125 " format, in the form vamp:soname:identifier:output.\n\n" 00126 " " << name << " --list-by-category\n\n" 00127 " -- List the plugins as a plugin index by category, in a machine-readable\n" 00128 " format. The format may change in future releases.\n\n" 00129 " " << name << " -p\n\n" 00130 " -- Print out the Vamp library search path.\n\n" 00131 " " << name << " -v\n\n" 00132 " -- Display version information only.\n" 00133 << endl; 00134 exit(2); 00135 } 00136 00137 int main(int argc, char **argv) 00138 { 00139 char *scooter = argv[0]; 00140 char *name = 0; 00141 while (scooter && *scooter) { 00142 if (*scooter == '/' || *scooter == '\\') name = ++scooter; 00143 else ++scooter; 00144 } 00145 if (!name || !*name) name = argv[0]; 00146 00147 if (argc < 2) usage(name); 00148 00149 if (argc == 2) { 00150 00151 if (!strcmp(argv[1], "-v")) { 00152 00153 cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl 00154 << "Vamp API version: " << VAMP_API_VERSION << endl 00155 << "Vamp SDK version: " << VAMP_SDK_VERSION << endl; 00156 return 0; 00157 00158 } else if (!strcmp(argv[1], "-l") || !strcmp(argv[1], "--list")) { 00159 00160 printPluginPath(true); 00161 enumeratePlugins(PluginInformation); 00162 return 0; 00163 00164 } else if (!strcmp(argv[1], "--list-full")) { 00165 00166 enumeratePlugins(PluginInformationDetailed); 00167 return 0; 00168 00169 } else if (!strcmp(argv[1], "-p")) { 00170 00171 printPluginPath(false); 00172 return 0; 00173 00174 } else if (!strcmp(argv[1], "--list-ids")) { 00175 00176 enumeratePlugins(PluginIds); 00177 return 0; 00178 00179 } else if (!strcmp(argv[1], "--list-outputs")) { 00180 00181 enumeratePlugins(PluginOutputIds); 00182 return 0; 00183 00184 } else if (!strcmp(argv[1], "--list-by-category")) { 00185 00186 printPluginCategoryList(); 00187 return 0; 00188 00189 } else usage(name); 00190 } 00191 00192 if (argc < 3) usage(name); 00193 00194 bool useFrames = false; 00195 00196 int base = 1; 00197 if (!strcmp(argv[1], "-s")) { 00198 useFrames = true; 00199 base = 2; 00200 } 00201 00202 string soname = argv[base]; 00203 string wavname = argv[base+1]; 00204 string plugid = ""; 00205 string output = ""; 00206 int outputNo = -1; 00207 string outfilename; 00208 00209 if (argc >= base+3) { 00210 00211 int idx = base+2; 00212 00213 if (isdigit(*argv[idx])) { 00214 outputNo = atoi(argv[idx++]); 00215 } 00216 00217 if (argc == idx + 2) { 00218 if (!strcmp(argv[idx], "-o")) { 00219 outfilename = argv[idx+1]; 00220 } else usage(name); 00221 } else if (argc != idx) { 00222 (usage(name)); 00223 } 00224 } 00225 00226 cerr << endl << name << ": Running..." << endl; 00227 00228 cerr << "Reading file: \"" << wavname << "\", writing to "; 00229 if (outfilename == "") { 00230 cerr << "standard output" << endl; 00231 } else { 00232 cerr << "\"" << outfilename << "\"" << endl; 00233 } 00234 00235 string::size_type sep = soname.find(':'); 00236 00237 if (sep != string::npos) { 00238 plugid = soname.substr(sep + 1); 00239 soname = soname.substr(0, sep); 00240 00241 sep = plugid.find(':'); 00242 if (sep != string::npos) { 00243 output = plugid.substr(sep + 1); 00244 plugid = plugid.substr(0, sep); 00245 } 00246 } 00247 00248 if (plugid == "") { 00249 usage(name); 00250 } 00251 00252 if (output != "" && outputNo != -1) { 00253 usage(name); 00254 } 00255 00256 if (output == "" && outputNo == -1) { 00257 outputNo = 0; 00258 } 00259 00260 return runPlugin(name, soname, plugid, output, outputNo, 00261 wavname, outfilename, useFrames); 00262 } 00263 00264 00265 int runPlugin(string myname, string soname, string id, 00266 string output, int outputNo, string wavname, 00267 string outfilename, bool useFrames) 00268 { 00269 PluginLoader *loader = PluginLoader::getInstance(); 00270 00271 PluginLoader::PluginKey key = loader->composePluginKey(soname, id); 00272 00273 SNDFILE *sndfile; 00274 SF_INFO sfinfo; 00275 memset(&sfinfo, 0, sizeof(SF_INFO)); 00276 00277 sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo); 00278 if (!sndfile) { 00279 cerr << myname << ": ERROR: Failed to open input file \"" 00280 << wavname << "\": " << sf_strerror(sndfile) << endl; 00281 return 1; 00282 } 00283 00284 ofstream *out = 0; 00285 if (outfilename != "") { 00286 out = new ofstream(outfilename.c_str(), ios::out); 00287 if (!*out) { 00288 cerr << myname << ": ERROR: Failed to open output file \"" 00289 << outfilename << "\" for writing" << endl; 00290 delete out; 00291 return 1; 00292 } 00293 } 00294 00295 Plugin *plugin = loader->loadPlugin 00296 (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE); 00297 if (!plugin) { 00298 cerr << myname << ": ERROR: Failed to load plugin \"" << id 00299 << "\" from library \"" << soname << "\"" << endl; 00300 sf_close(sndfile); 00301 if (out) { 00302 out->close(); 00303 delete out; 00304 } 00305 return 1; 00306 } 00307 00308 cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl; 00309 00310 // Note that the following would be much simpler if we used a 00311 // PluginBufferingAdapter as well -- i.e. if we had passed 00312 // PluginLoader::ADAPT_ALL to loader->loadPlugin() above, instead 00313 // of ADAPT_ALL_SAFE. Then we could simply specify our own block 00314 // size, keep the step size equal to the block size, and ignore 00315 // the plugin's bleatings. However, there are some issues with 00316 // using a PluginBufferingAdapter that make the results sometimes 00317 // technically different from (if effectively the same as) the 00318 // un-adapted plugin, so we aren't doing that here. See the 00319 // PluginBufferingAdapter documentation for details. 00320 00321 int blockSize = plugin->getPreferredBlockSize(); 00322 int stepSize = plugin->getPreferredStepSize(); 00323 00324 if (blockSize == 0) { 00325 blockSize = 1024; 00326 } 00327 if (stepSize == 0) { 00328 if (plugin->getInputDomain() == Plugin::FrequencyDomain) { 00329 stepSize = blockSize/2; 00330 } else { 00331 stepSize = blockSize; 00332 } 00333 } else if (stepSize > blockSize) { 00334 cerr << "WARNING: stepSize " << stepSize << " > blockSize " << blockSize << ", resetting blockSize to "; 00335 if (plugin->getInputDomain() == Plugin::FrequencyDomain) { 00336 blockSize = stepSize * 2; 00337 } else { 00338 blockSize = stepSize; 00339 } 00340 cerr << blockSize << endl; 00341 } 00342 int overlapSize = blockSize - stepSize; 00343 sf_count_t currentStep = 0; 00344 int finalStepsRemaining = max(1, (blockSize / stepSize) - 1); // at end of file, this many part-silent frames needed after we hit EOF 00345 00346 int channels = sfinfo.channels; 00347 00348 float *filebuf = new float[blockSize * channels]; 00349 float **plugbuf = new float*[channels]; 00350 for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2]; 00351 00352 cerr << "Using block size = " << blockSize << ", step size = " 00353 << stepSize << endl; 00354 00355 // The channel queries here are for informational purposes only -- 00356 // a PluginChannelAdapter is being used automatically behind the 00357 // scenes, and it will take case of any channel mismatch 00358 00359 int minch = plugin->getMinChannelCount(); 00360 int maxch = plugin->getMaxChannelCount(); 00361 cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl; 00362 cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl; 00363 00364 Plugin::OutputList outputs = plugin->getOutputDescriptors(); 00365 Plugin::OutputDescriptor od; 00366 00367 int returnValue = 1; 00368 int progress = 0; 00369 00370 RealTime rt; 00371 PluginWrapper *wrapper = 0; 00372 RealTime adjustment = RealTime::zeroTime; 00373 00374 if (outputs.empty()) { 00375 cerr << "ERROR: Plugin has no outputs!" << endl; 00376 goto done; 00377 } 00378 00379 if (outputNo < 0) { 00380 00381 for (size_t oi = 0; oi < outputs.size(); ++oi) { 00382 if (outputs[oi].identifier == output) { 00383 outputNo = oi; 00384 break; 00385 } 00386 } 00387 00388 if (outputNo < 0) { 00389 cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl; 00390 goto done; 00391 } 00392 00393 } else { 00394 00395 if (int(outputs.size()) <= outputNo) { 00396 cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl; 00397 goto done; 00398 } 00399 } 00400 00401 od = outputs[outputNo]; 00402 cerr << "Output is: \"" << od.identifier << "\"" << endl; 00403 00404 if (!plugin->initialise(channels, stepSize, blockSize)) { 00405 cerr << "ERROR: Plugin initialise (channels = " << channels 00406 << ", stepSize = " << stepSize << ", blockSize = " 00407 << blockSize << ") failed." << endl; 00408 goto done; 00409 } 00410 00411 wrapper = dynamic_cast<PluginWrapper *>(plugin); 00412 if (wrapper) { 00413 // See documentation for 00414 // PluginInputDomainAdapter::getTimestampAdjustment 00415 PluginInputDomainAdapter *ida = 00416 wrapper->getWrapper<PluginInputDomainAdapter>(); 00417 if (ida) adjustment = ida->getTimestampAdjustment(); 00418 } 00419 00420 // Here we iterate over the frames, avoiding asking the numframes in case it's streaming input. 00421 do { 00422 00423 int count; 00424 00425 if ((blockSize==stepSize) || (currentStep==0)) { 00426 // read a full fresh block 00427 if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) { 00428 cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl; 00429 break; 00430 } 00431 if (count != blockSize) --finalStepsRemaining; 00432 } else { 00433 // otherwise shunt the existing data down and read the remainder. 00434 memmove(filebuf, filebuf + (stepSize * channels), overlapSize * channels * sizeof(float)); 00435 if ((count = sf_readf_float(sndfile, filebuf + (overlapSize * channels), stepSize)) < 0) { 00436 cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl; 00437 break; 00438 } 00439 if (count != stepSize) --finalStepsRemaining; 00440 count += overlapSize; 00441 } 00442 00443 for (int c = 0; c < channels; ++c) { 00444 int j = 0; 00445 while (j < count) { 00446 plugbuf[c][j] = filebuf[j * sfinfo.channels + c]; 00447 ++j; 00448 } 00449 while (j < blockSize) { 00450 plugbuf[c][j] = 0.0f; 00451 ++j; 00452 } 00453 } 00454 00455 rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate); 00456 00457 printFeatures 00458 (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), 00459 sfinfo.samplerate, outputNo, plugin->process(plugbuf, rt), 00460 out, useFrames); 00461 00462 if (sfinfo.frames > 0){ 00463 int pp = progress; 00464 progress = lrintf((float(currentStep * stepSize) / sfinfo.frames) * 100.f); 00465 if (progress != pp && out) { 00466 cerr << "\r" << progress << "%"; 00467 } 00468 } 00469 00470 ++currentStep; 00471 00472 } while (finalStepsRemaining > 0); 00473 00474 if (out) cerr << "\rDone" << endl; 00475 00476 rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate); 00477 00478 printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), 00479 sfinfo.samplerate, outputNo, 00480 plugin->getRemainingFeatures(), out, useFrames); 00481 00482 returnValue = 0; 00483 00484 done: 00485 delete plugin; 00486 if (out) { 00487 out->close(); 00488 delete out; 00489 } 00490 sf_close(sndfile); 00491 return returnValue; 00492 } 00493 00494 void 00495 printFeatures(int frame, int sr, int output, 00496 Plugin::FeatureSet features, ofstream *out, bool useFrames) 00497 { 00498 for (unsigned int i = 0; i < features[output].size(); ++i) { 00499 00500 if (useFrames) { 00501 00502 int displayFrame = frame; 00503 00504 if (features[output][i].hasTimestamp) { 00505 displayFrame = RealTime::realTime2Frame 00506 (features[output][i].timestamp, sr); 00507 } 00508 00509 (out ? *out : cout) << displayFrame; 00510 00511 if (features[output][i].hasDuration) { 00512 displayFrame = RealTime::realTime2Frame 00513 (features[output][i].duration, sr); 00514 (out ? *out : cout) << "," << displayFrame; 00515 } 00516 00517 (out ? *out : cout) << ":"; 00518 00519 } else { 00520 00521 RealTime rt = RealTime::frame2RealTime(frame, sr); 00522 00523 if (features[output][i].hasTimestamp) { 00524 rt = features[output][i].timestamp; 00525 } 00526 00527 (out ? *out : cout) << rt.toString(); 00528 00529 if (features[output][i].hasDuration) { 00530 rt = features[output][i].duration; 00531 (out ? *out : cout) << "," << rt.toString(); 00532 } 00533 00534 (out ? *out : cout) << ":"; 00535 } 00536 00537 for (unsigned int j = 0; j < features[output][i].values.size(); ++j) { 00538 (out ? *out : cout) << " " << features[output][i].values[j]; 00539 } 00540 (out ? *out : cout) << " " << features[output][i].label; 00541 00542 (out ? *out : cout) << endl; 00543 } 00544 } 00545 00546 void 00547 printPluginPath(bool verbose) 00548 { 00549 if (verbose) { 00550 cout << "\nVamp plugin search path: "; 00551 } 00552 00553 vector<string> path = PluginHostAdapter::getPluginPath(); 00554 for (size_t i = 0; i < path.size(); ++i) { 00555 if (verbose) { 00556 cout << "[" << path[i] << "]"; 00557 } else { 00558 cout << path[i] << endl; 00559 } 00560 } 00561 00562 if (verbose) cout << endl; 00563 } 00564 00565 static 00566 string 00567 header(string text, int level) 00568 { 00569 string out = '\n' + text + '\n'; 00570 for (size_t i = 0; i < text.length(); ++i) { 00571 out += (level == 1 ? '=' : level == 2 ? '-' : '~'); 00572 } 00573 out += '\n'; 00574 return out; 00575 } 00576 00577 void 00578 enumeratePlugins(Verbosity verbosity) 00579 { 00580 PluginLoader *loader = PluginLoader::getInstance(); 00581 00582 if (verbosity == PluginInformation) { 00583 cout << "\nVamp plugin libraries found in search path:" << endl; 00584 } 00585 00586 vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); 00587 typedef multimap<string, PluginLoader::PluginKey> 00588 LibraryMap; 00589 LibraryMap libraryMap; 00590 00591 for (size_t i = 0; i < plugins.size(); ++i) { 00592 string path = loader->getLibraryPathForPlugin(plugins[i]); 00593 libraryMap.insert(LibraryMap::value_type(path, plugins[i])); 00594 } 00595 00596 string prevPath = ""; 00597 int index = 0; 00598 00599 for (LibraryMap::iterator i = libraryMap.begin(); 00600 i != libraryMap.end(); ++i) { 00601 00602 string path = i->first; 00603 PluginLoader::PluginKey key = i->second; 00604 00605 if (path != prevPath) { 00606 prevPath = path; 00607 index = 0; 00608 if (verbosity == PluginInformation) { 00609 cout << "\n " << path << ":" << endl; 00610 } else if (verbosity == PluginInformationDetailed) { 00611 string::size_type ki = i->second.find(':'); 00612 string text = "Library \"" + i->second.substr(0, ki) + "\""; 00613 cout << "\n" << header(text, 1); 00614 } 00615 } 00616 00617 Plugin *plugin = loader->loadPlugin(key, 48000); 00618 if (plugin) { 00619 00620 char c = char('A' + index); 00621 if (c > 'Z') c = char('a' + (index - 26)); 00622 00623 PluginLoader::PluginCategoryHierarchy category = 00624 loader->getPluginCategory(key); 00625 string catstr; 00626 if (!category.empty()) { 00627 for (size_t ci = 0; ci < category.size(); ++ci) { 00628 if (ci > 0) catstr += " > "; 00629 catstr += category[ci]; 00630 } 00631 } 00632 00633 if (verbosity == PluginInformation) { 00634 00635 cout << " [" << c << "] [v" 00636 << plugin->getVampApiVersion() << "] " 00637 << plugin->getName() << ", \"" 00638 << plugin->getIdentifier() << "\"" << " [" 00639 << plugin->getMaker() << "]" << endl; 00640 00641 if (catstr != "") { 00642 cout << " > " << catstr << endl; 00643 } 00644 00645 if (plugin->getDescription() != "") { 00646 cout << " - " << plugin->getDescription() << endl; 00647 } 00648 00649 } else if (verbosity == PluginInformationDetailed) { 00650 00651 cout << header(plugin->getName(), 2); 00652 cout << " - Identifier: " 00653 << key << endl; 00654 cout << " - Plugin Version: " 00655 << plugin->getPluginVersion() << endl; 00656 cout << " - Vamp API Version: " 00657 << plugin->getVampApiVersion() << endl; 00658 cout << " - Maker: \"" 00659 << plugin->getMaker() << "\"" << endl; 00660 cout << " - Copyright: \"" 00661 << plugin->getCopyright() << "\"" << endl; 00662 cout << " - Description: \"" 00663 << plugin->getDescription() << "\"" << endl; 00664 cout << " - Input Domain: " 00665 << (plugin->getInputDomain() == Vamp::Plugin::TimeDomain ? 00666 "Time Domain" : "Frequency Domain") << endl; 00667 cout << " - Default Step Size: " 00668 << plugin->getPreferredStepSize() << endl; 00669 cout << " - Default Block Size: " 00670 << plugin->getPreferredBlockSize() << endl; 00671 cout << " - Minimum Channels: " 00672 << plugin->getMinChannelCount() << endl; 00673 cout << " - Maximum Channels: " 00674 << plugin->getMaxChannelCount() << endl; 00675 00676 } else if (verbosity == PluginIds) { 00677 cout << "vamp:" << key << endl; 00678 } 00679 00680 Plugin::OutputList outputs = 00681 plugin->getOutputDescriptors(); 00682 00683 if (verbosity == PluginInformationDetailed) { 00684 00685 Plugin::ParameterList params = plugin->getParameterDescriptors(); 00686 for (size_t j = 0; j < params.size(); ++j) { 00687 Plugin::ParameterDescriptor &pd(params[j]); 00688 cout << "\nParameter " << j+1 << ": \"" << pd.name << "\"" << endl; 00689 cout << " - Identifier: " << pd.identifier << endl; 00690 cout << " - Description: \"" << pd.description << "\"" << endl; 00691 if (pd.unit != "") { 00692 cout << " - Unit: " << pd.unit << endl; 00693 } 00694 cout << " - Range: "; 00695 cout << pd.minValue << " -> " << pd.maxValue << endl; 00696 cout << " - Default: "; 00697 cout << pd.defaultValue << endl; 00698 if (pd.isQuantized) { 00699 cout << " - Quantize Step: " 00700 << pd.quantizeStep << endl; 00701 } 00702 if (!pd.valueNames.empty()) { 00703 cout << " - Value Names: "; 00704 for (size_t k = 0; k < pd.valueNames.size(); ++k) { 00705 if (k > 0) cout << ", "; 00706 cout << "\"" << pd.valueNames[k] << "\""; 00707 } 00708 cout << endl; 00709 } 00710 } 00711 00712 if (outputs.empty()) { 00713 cout << "\n** Note: This plugin reports no outputs!" << endl; 00714 } 00715 for (size_t j = 0; j < outputs.size(); ++j) { 00716 Plugin::OutputDescriptor &od(outputs[j]); 00717 cout << "\nOutput " << j+1 << ": \"" << od.name << "\"" << endl; 00718 cout << " - Identifier: " << od.identifier << endl; 00719 cout << " - Description: \"" << od.description << "\"" << endl; 00720 if (od.unit != "") { 00721 cout << " - Unit: " << od.unit << endl; 00722 } 00723 if (od.hasFixedBinCount) { 00724 cout << " - Default Bin Count: " << od.binCount << endl; 00725 } 00726 if (!od.binNames.empty()) { 00727 bool have = false; 00728 for (size_t k = 0; k < od.binNames.size(); ++k) { 00729 if (od.binNames[k] != "") { 00730 have = true; break; 00731 } 00732 } 00733 if (have) { 00734 cout << " - Bin Names: "; 00735 for (size_t k = 0; k < od.binNames.size(); ++k) { 00736 if (k > 0) cout << ", "; 00737 cout << "\"" << od.binNames[k] << "\""; 00738 } 00739 cout << endl; 00740 } 00741 } 00742 if (od.hasKnownExtents) { 00743 cout << " - Default Extents: "; 00744 cout << od.minValue << " -> " << od.maxValue << endl; 00745 } 00746 if (od.isQuantized) { 00747 cout << " - Quantize Step: " 00748 << od.quantizeStep << endl; 00749 } 00750 cout << " - Sample Type: " 00751 << (od.sampleType == 00752 Plugin::OutputDescriptor::OneSamplePerStep ? 00753 "One Sample Per Step" : 00754 od.sampleType == 00755 Plugin::OutputDescriptor::FixedSampleRate ? 00756 "Fixed Sample Rate" : 00757 "Variable Sample Rate") << endl; 00758 if (od.sampleType != 00759 Plugin::OutputDescriptor::OneSamplePerStep) { 00760 cout << " - Default Rate: " 00761 << od.sampleRate << endl; 00762 } 00763 cout << " - Has Duration: " 00764 << (od.hasDuration ? "Yes" : "No") << endl; 00765 } 00766 } 00767 00768 if (outputs.size() > 1 || verbosity == PluginOutputIds) { 00769 for (size_t j = 0; j < outputs.size(); ++j) { 00770 if (verbosity == PluginInformation) { 00771 cout << " (" << j << ") " 00772 << outputs[j].name << ", \"" 00773 << outputs[j].identifier << "\"" << endl; 00774 if (outputs[j].description != "") { 00775 cout << " - " 00776 << outputs[j].description << endl; 00777 } 00778 } else if (verbosity == PluginOutputIds) { 00779 cout << "vamp:" << key << ":" << outputs[j].identifier << endl; 00780 } 00781 } 00782 } 00783 00784 ++index; 00785 00786 delete plugin; 00787 } 00788 } 00789 00790 if (verbosity == PluginInformation || 00791 verbosity == PluginInformationDetailed) { 00792 cout << endl; 00793 } 00794 } 00795 00796 void 00797 printPluginCategoryList() 00798 { 00799 PluginLoader *loader = PluginLoader::getInstance(); 00800 00801 vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); 00802 00803 set<string> printedcats; 00804 00805 for (size_t i = 0; i < plugins.size(); ++i) { 00806 00807 PluginLoader::PluginKey key = plugins[i]; 00808 00809 PluginLoader::PluginCategoryHierarchy category = 00810 loader->getPluginCategory(key); 00811 00812 Plugin *plugin = loader->loadPlugin(key, 48000); 00813 if (!plugin) continue; 00814 00815 string catstr = ""; 00816 00817 if (category.empty()) catstr = '|'; 00818 else { 00819 for (size_t j = 0; j < category.size(); ++j) { 00820 catstr += category[j]; 00821 catstr += '|'; 00822 if (printedcats.find(catstr) == printedcats.end()) { 00823 std::cout << catstr << std::endl; 00824 printedcats.insert(catstr); 00825 } 00826 } 00827 } 00828 00829 std::cout << catstr << key << ":::" << plugin->getName() << ":::" << plugin->getMaker() << ":::" << plugin->getDescription() << std::endl; 00830 } 00831 } 00832