VampPluginSDK 2.1

- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

vamp-simple-host.cpp
Go to the documentation of this file.

    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