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 00343 int channels = sfinfo.channels; 00344 00345 float *filebuf = new float[blockSize * channels]; 00346 float **plugbuf = new float*[channels]; 00347 for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2]; 00348 00349 cerr << "Using block size = " << blockSize << ", step size = " 00350 << stepSize << endl; 00351 00352 // The channel queries here are for informational purposes only -- 00353 // a PluginChannelAdapter is being used automatically behind the 00354 // scenes, and it will take case of any channel mismatch 00355 00356 int minch = plugin->getMinChannelCount(); 00357 int maxch = plugin->getMaxChannelCount(); 00358 cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl; 00359 cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl; 00360 00361 Plugin::OutputList outputs = plugin->getOutputDescriptors(); 00362 Plugin::OutputDescriptor od; 00363 00364 int returnValue = 1; 00365 int progress = 0; 00366 00367 RealTime rt; 00368 PluginWrapper *wrapper = 0; 00369 RealTime adjustment = RealTime::zeroTime; 00370 00371 if (outputs.empty()) { 00372 cerr << "ERROR: Plugin has no outputs!" << endl; 00373 goto done; 00374 } 00375 00376 if (outputNo < 0) { 00377 00378 for (size_t oi = 0; oi < outputs.size(); ++oi) { 00379 if (outputs[oi].identifier == output) { 00380 outputNo = oi; 00381 break; 00382 } 00383 } 00384 00385 if (outputNo < 0) { 00386 cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl; 00387 goto done; 00388 } 00389 00390 } else { 00391 00392 if (int(outputs.size()) <= outputNo) { 00393 cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl; 00394 goto done; 00395 } 00396 } 00397 00398 od = outputs[outputNo]; 00399 cerr << "Output is: \"" << od.identifier << "\"" << endl; 00400 00401 if (!plugin->initialise(channels, stepSize, blockSize)) { 00402 cerr << "ERROR: Plugin initialise (channels = " << channels 00403 << ", stepSize = " << stepSize << ", blockSize = " 00404 << blockSize << ") failed." << endl; 00405 goto done; 00406 } 00407 00408 wrapper = dynamic_cast<PluginWrapper *>(plugin); 00409 if (wrapper) { 00410 // See documentation for 00411 // PluginInputDomainAdapter::getTimestampAdjustment 00412 PluginInputDomainAdapter *ida = 00413 wrapper->getWrapper<PluginInputDomainAdapter>(); 00414 if (ida) adjustment = ida->getTimestampAdjustment(); 00415 } 00416 00417 for (sf_count_t i = 0; i < sfinfo.frames; i += stepSize) { 00418 00419 int count; 00420 00421 if (sf_seek(sndfile, i, SEEK_SET) < 0) { 00422 cerr << "ERROR: sf_seek failed: " << sf_strerror(sndfile) << endl; 00423 break; 00424 } 00425 00426 if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) { 00427 cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl; 00428 break; 00429 } 00430 00431 for (int c = 0; c < channels; ++c) { 00432 int j = 0; 00433 while (j < count) { 00434 plugbuf[c][j] = filebuf[j * sfinfo.channels + c]; 00435 ++j; 00436 } 00437 while (j < blockSize) { 00438 plugbuf[c][j] = 0.0f; 00439 ++j; 00440 } 00441 } 00442 00443 rt = RealTime::frame2RealTime(i, sfinfo.samplerate); 00444 00445 printFeatures 00446 (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), 00447 sfinfo.samplerate, outputNo, plugin->process(plugbuf, rt), 00448 out, useFrames); 00449 00450 int pp = progress; 00451 progress = lrintf((float(i) / sfinfo.frames) * 100.f); 00452 if (progress != pp && out) { 00453 cerr << "\r" << progress << "%"; 00454 } 00455 } 00456 if (out) cerr << "\rDone" << endl; 00457 00458 rt = RealTime::frame2RealTime(sfinfo.frames, sfinfo.samplerate); 00459 00460 printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate), 00461 sfinfo.samplerate, outputNo, 00462 plugin->getRemainingFeatures(), out, useFrames); 00463 00464 returnValue = 0; 00465 00466 done: 00467 delete plugin; 00468 if (out) { 00469 out->close(); 00470 delete out; 00471 } 00472 sf_close(sndfile); 00473 return returnValue; 00474 } 00475 00476 void 00477 printFeatures(int frame, int sr, int output, 00478 Plugin::FeatureSet features, ofstream *out, bool useFrames) 00479 { 00480 for (unsigned int i = 0; i < features[output].size(); ++i) { 00481 00482 if (useFrames) { 00483 00484 int displayFrame = frame; 00485 00486 if (features[output][i].hasTimestamp) { 00487 displayFrame = RealTime::realTime2Frame 00488 (features[output][i].timestamp, sr); 00489 } 00490 00491 (out ? *out : cout) << displayFrame; 00492 00493 if (features[output][i].hasDuration) { 00494 displayFrame = RealTime::realTime2Frame 00495 (features[output][i].duration, sr); 00496 (out ? *out : cout) << "," << displayFrame; 00497 } 00498 00499 (out ? *out : cout) << ":"; 00500 00501 } else { 00502 00503 RealTime rt = RealTime::frame2RealTime(frame, sr); 00504 00505 if (features[output][i].hasTimestamp) { 00506 rt = features[output][i].timestamp; 00507 } 00508 00509 (out ? *out : cout) << rt.toString(); 00510 00511 if (features[output][i].hasDuration) { 00512 rt = features[output][i].duration; 00513 (out ? *out : cout) << "," << rt.toString(); 00514 } 00515 00516 (out ? *out : cout) << ":"; 00517 } 00518 00519 for (unsigned int j = 0; j < features[output][i].values.size(); ++j) { 00520 (out ? *out : cout) << " " << features[output][i].values[j]; 00521 } 00522 00523 (out ? *out : cout) << endl; 00524 } 00525 } 00526 00527 void 00528 printPluginPath(bool verbose) 00529 { 00530 if (verbose) { 00531 cout << "\nVamp plugin search path: "; 00532 } 00533 00534 vector<string> path = PluginHostAdapter::getPluginPath(); 00535 for (size_t i = 0; i < path.size(); ++i) { 00536 if (verbose) { 00537 cout << "[" << path[i] << "]"; 00538 } else { 00539 cout << path[i] << endl; 00540 } 00541 } 00542 00543 if (verbose) cout << endl; 00544 } 00545 00546 static 00547 string 00548 header(string text, int level) 00549 { 00550 string out = '\n' + text + '\n'; 00551 for (size_t i = 0; i < text.length(); ++i) { 00552 out += (level == 1 ? '=' : level == 2 ? '-' : '~'); 00553 } 00554 out += '\n'; 00555 return out; 00556 } 00557 00558 void 00559 enumeratePlugins(Verbosity verbosity) 00560 { 00561 PluginLoader *loader = PluginLoader::getInstance(); 00562 00563 if (verbosity == PluginInformation) { 00564 cout << "\nVamp plugin libraries found in search path:" << endl; 00565 } 00566 00567 vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); 00568 typedef multimap<string, PluginLoader::PluginKey> 00569 LibraryMap; 00570 LibraryMap libraryMap; 00571 00572 for (size_t i = 0; i < plugins.size(); ++i) { 00573 string path = loader->getLibraryPathForPlugin(plugins[i]); 00574 libraryMap.insert(LibraryMap::value_type(path, plugins[i])); 00575 } 00576 00577 string prevPath = ""; 00578 int index = 0; 00579 00580 for (LibraryMap::iterator i = libraryMap.begin(); 00581 i != libraryMap.end(); ++i) { 00582 00583 string path = i->first; 00584 PluginLoader::PluginKey key = i->second; 00585 00586 if (path != prevPath) { 00587 prevPath = path; 00588 index = 0; 00589 if (verbosity == PluginInformation) { 00590 cout << "\n " << path << ":" << endl; 00591 } else if (verbosity == PluginInformationDetailed) { 00592 string::size_type ki = i->second.find(':'); 00593 string text = "Library \"" + i->second.substr(0, ki) + "\""; 00594 cout << "\n" << header(text, 1); 00595 } 00596 } 00597 00598 Plugin *plugin = loader->loadPlugin(key, 48000); 00599 if (plugin) { 00600 00601 char c = char('A' + index); 00602 if (c > 'Z') c = char('a' + (index - 26)); 00603 00604 PluginLoader::PluginCategoryHierarchy category = 00605 loader->getPluginCategory(key); 00606 string catstr; 00607 if (!category.empty()) { 00608 for (size_t ci = 0; ci < category.size(); ++ci) { 00609 if (ci > 0) catstr += " > "; 00610 catstr += category[ci]; 00611 } 00612 } 00613 00614 if (verbosity == PluginInformation) { 00615 00616 cout << " [" << c << "] [v" 00617 << plugin->getVampApiVersion() << "] " 00618 << plugin->getName() << ", \"" 00619 << plugin->getIdentifier() << "\"" << " [" 00620 << plugin->getMaker() << "]" << endl; 00621 00622 if (catstr != "") { 00623 cout << " > " << catstr << endl; 00624 } 00625 00626 if (plugin->getDescription() != "") { 00627 cout << " - " << plugin->getDescription() << endl; 00628 } 00629 00630 } else if (verbosity == PluginInformationDetailed) { 00631 00632 cout << header(plugin->getName(), 2); 00633 cout << " - Identifier: " 00634 << key << endl; 00635 cout << " - Plugin Version: " 00636 << plugin->getPluginVersion() << endl; 00637 cout << " - Vamp API Version: " 00638 << plugin->getVampApiVersion() << endl; 00639 cout << " - Maker: \"" 00640 << plugin->getMaker() << "\"" << endl; 00641 cout << " - Copyright: \"" 00642 << plugin->getCopyright() << "\"" << endl; 00643 cout << " - Description: \"" 00644 << plugin->getDescription() << "\"" << endl; 00645 cout << " - Input Domain: " 00646 << (plugin->getInputDomain() == Vamp::Plugin::TimeDomain ? 00647 "Time Domain" : "Frequency Domain") << endl; 00648 cout << " - Default Step Size: " 00649 << plugin->getPreferredStepSize() << endl; 00650 cout << " - Default Block Size: " 00651 << plugin->getPreferredBlockSize() << endl; 00652 cout << " - Minimum Channels: " 00653 << plugin->getMinChannelCount() << endl; 00654 cout << " - Maximum Channels: " 00655 << plugin->getMaxChannelCount() << endl; 00656 00657 } else if (verbosity == PluginIds) { 00658 cout << "vamp:" << key << endl; 00659 } 00660 00661 Plugin::OutputList outputs = 00662 plugin->getOutputDescriptors(); 00663 00664 if (verbosity == PluginInformationDetailed) { 00665 00666 Plugin::ParameterList params = plugin->getParameterDescriptors(); 00667 for (size_t j = 0; j < params.size(); ++j) { 00668 Plugin::ParameterDescriptor &pd(params[j]); 00669 cout << "\nParameter " << j+1 << ": \"" << pd.name << "\"" << endl; 00670 cout << " - Identifier: " << pd.identifier << endl; 00671 cout << " - Description: \"" << pd.description << "\"" << endl; 00672 if (pd.unit != "") { 00673 cout << " - Unit: " << pd.unit << endl; 00674 } 00675 cout << " - Range: "; 00676 cout << pd.minValue << " -> " << pd.maxValue << endl; 00677 cout << " - Default: "; 00678 cout << pd.defaultValue << endl; 00679 if (pd.isQuantized) { 00680 cout << " - Quantize Step: " 00681 << pd.quantizeStep << endl; 00682 } 00683 if (!pd.valueNames.empty()) { 00684 cout << " - Value Names: "; 00685 for (size_t k = 0; k < pd.valueNames.size(); ++k) { 00686 if (k > 0) cout << ", "; 00687 cout << "\"" << pd.valueNames[k] << "\""; 00688 } 00689 cout << endl; 00690 } 00691 } 00692 00693 if (outputs.empty()) { 00694 cout << "\n** Note: This plugin reports no outputs!" << endl; 00695 } 00696 for (size_t j = 0; j < outputs.size(); ++j) { 00697 Plugin::OutputDescriptor &od(outputs[j]); 00698 cout << "\nOutput " << j+1 << ": \"" << od.name << "\"" << endl; 00699 cout << " - Identifier: " << od.identifier << endl; 00700 cout << " - Description: \"" << od.description << "\"" << endl; 00701 if (od.unit != "") { 00702 cout << " - Unit: " << od.unit << endl; 00703 } 00704 if (od.hasFixedBinCount) { 00705 cout << " - Default Bin Count: " << od.binCount << endl; 00706 } 00707 if (!od.binNames.empty()) { 00708 bool have = false; 00709 for (size_t k = 0; k < od.binNames.size(); ++k) { 00710 if (od.binNames[k] != "") { 00711 have = true; break; 00712 } 00713 } 00714 if (have) { 00715 cout << " - Bin Names: "; 00716 for (size_t k = 0; k < od.binNames.size(); ++k) { 00717 if (k > 0) cout << ", "; 00718 cout << "\"" << od.binNames[k] << "\""; 00719 } 00720 cout << endl; 00721 } 00722 } 00723 if (od.hasKnownExtents) { 00724 cout << " - Default Extents: "; 00725 cout << od.minValue << " -> " << od.maxValue << endl; 00726 } 00727 if (od.isQuantized) { 00728 cout << " - Quantize Step: " 00729 << od.quantizeStep << endl; 00730 } 00731 cout << " - Sample Type: " 00732 << (od.sampleType == 00733 Plugin::OutputDescriptor::OneSamplePerStep ? 00734 "One Sample Per Step" : 00735 od.sampleType == 00736 Plugin::OutputDescriptor::FixedSampleRate ? 00737 "Fixed Sample Rate" : 00738 "Variable Sample Rate") << endl; 00739 if (od.sampleType != 00740 Plugin::OutputDescriptor::OneSamplePerStep) { 00741 cout << " - Default Rate: " 00742 << od.sampleRate << endl; 00743 } 00744 cout << " - Has Duration: " 00745 << (od.hasDuration ? "Yes" : "No") << endl; 00746 } 00747 } 00748 00749 if (outputs.size() > 1 || verbosity == PluginOutputIds) { 00750 for (size_t j = 0; j < outputs.size(); ++j) { 00751 if (verbosity == PluginInformation) { 00752 cout << " (" << j << ") " 00753 << outputs[j].name << ", \"" 00754 << outputs[j].identifier << "\"" << endl; 00755 if (outputs[j].description != "") { 00756 cout << " - " 00757 << outputs[j].description << endl; 00758 } 00759 } else if (verbosity == PluginOutputIds) { 00760 cout << "vamp:" << key << ":" << outputs[j].identifier << endl; 00761 } 00762 } 00763 } 00764 00765 ++index; 00766 00767 delete plugin; 00768 } 00769 } 00770 00771 if (verbosity == PluginInformation || 00772 verbosity == PluginInformationDetailed) { 00773 cout << endl; 00774 } 00775 } 00776 00777 void 00778 printPluginCategoryList() 00779 { 00780 PluginLoader *loader = PluginLoader::getInstance(); 00781 00782 vector<PluginLoader::PluginKey> plugins = loader->listPlugins(); 00783 00784 set<string> printedcats; 00785 00786 for (size_t i = 0; i < plugins.size(); ++i) { 00787 00788 PluginLoader::PluginKey key = plugins[i]; 00789 00790 PluginLoader::PluginCategoryHierarchy category = 00791 loader->getPluginCategory(key); 00792 00793 Plugin *plugin = loader->loadPlugin(key, 48000); 00794 if (!plugin) continue; 00795 00796 string catstr = ""; 00797 00798 if (category.empty()) catstr = '|'; 00799 else { 00800 for (size_t j = 0; j < category.size(); ++j) { 00801 catstr += category[j]; 00802 catstr += '|'; 00803 if (printedcats.find(catstr) == printedcats.end()) { 00804 std::cout << catstr << std::endl; 00805 printedcats.insert(catstr); 00806 } 00807 } 00808 } 00809 00810 std::cout << catstr << key << ":::" << plugin->getName() << ":::" << plugin->getMaker() << ":::" << plugin->getDescription() << std::endl; 00811 } 00812 } 00813