74 #define HOST_VERSION "1.5" 84 const Plugin::OutputDescriptor &,
int,
85 const Plugin::FeatureSet &, ofstream *,
bool frames);
87 void fft(
unsigned int,
bool,
double *,
double *,
double *,
double *);
92 int runPlugin(
string myname,
string soname,
string id,
string output,
93 int outputNo,
string inputFile,
string outfilename,
bool frames);
98 << name <<
": A command-line host for Vamp audio analysis plugins.\n\n" 99 "Centre for Digital Music, Queen Mary, University of London.\n" 100 "Copyright 2006-2009 Chris Cannam and QMUL.\n" 101 "Freely redistributable; published under a BSD-style license.\n\n" 103 " " << name <<
" [-s] pluginlibrary[." <<
PLUGIN_SUFFIX <<
"]:plugin[:output] file.wav [-o out.txt]\n" 104 " " << name <<
" [-s] pluginlibrary[." <<
PLUGIN_SUFFIX <<
"]:plugin file.wav [outputno] [-o out.txt]\n\n" 105 " -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n" 106 " audio data in \"file.wav\", retrieving the named \"output\", or output\n" 107 " number \"outputno\" (the first output by default) and dumping it to\n" 108 " standard output, or to \"out.txt\" if the -o option is given.\n\n" 109 " \"pluginlibrary\" should be a library name, not a file path; the\n" 110 " standard Vamp library search path will be used to locate it. If\n" 111 " a file path is supplied, the directory part(s) will be ignored.\n\n" 112 " If the -s option is given, results will be labelled with the audio\n" 113 " sample frame at which they occur. Otherwise, they will be labelled\n" 114 " with time in seconds.\n\n" 115 " " << name <<
" -l\n" 116 " " << name <<
" --list\n\n" 117 " -- List the plugin libraries and Vamp plugins in the library search path\n" 118 " in a verbose human-readable format.\n\n" 119 " " << name <<
" -L\n" 120 " " << name <<
" --list-full\n\n" 121 " -- List all data reported by all the Vamp plugins in the library search\n" 122 " path in a very verbose human-readable format.\n\n" 123 " " << name <<
" --list-ids\n\n" 124 " -- List the plugins in the search path in a terse machine-readable format,\n" 125 " in the form vamp:soname:identifier.\n\n" 126 " " << name <<
" --list-outputs\n\n" 127 " -- List the outputs for plugins in the search path in a machine-readable\n" 128 " format, in the form vamp:soname:identifier:output.\n\n" 129 " " << name <<
" --list-by-category\n\n" 130 " -- List the plugins as a plugin index by category, in a machine-readable\n" 131 " format. The format may change in future releases.\n\n" 132 " " << name <<
" -p\n\n" 133 " -- Print out the Vamp library search path.\n\n" 134 " " << name <<
" -v\n\n" 135 " -- Display version information only.\n" 140 int main(
int argc,
char **argv)
142 char *scooter = argv[0];
144 while (scooter && *scooter) {
145 if (*scooter ==
'/' || *scooter ==
'\\') name = ++scooter;
148 if (!name || !*name) name = argv[0];
150 if (argc < 2)
usage(name);
154 if (!strcmp(argv[1],
"-v")) {
156 cout <<
"Simple Vamp plugin host version: " <<
HOST_VERSION << endl
161 }
else if (!strcmp(argv[1],
"-l") || !strcmp(argv[1],
"--list")) {
167 }
else if (!strcmp(argv[1],
"-L") || !strcmp(argv[1],
"--list-full")) {
172 }
else if (!strcmp(argv[1],
"-p")) {
177 }
else if (!strcmp(argv[1],
"--list-ids")) {
182 }
else if (!strcmp(argv[1],
"--list-outputs")) {
187 }
else if (!strcmp(argv[1],
"--list-by-category")) {
195 if (argc < 3)
usage(name);
197 bool useFrames =
false;
200 if (!strcmp(argv[1],
"-s")) {
205 string soname = argv[base];
206 string wavname = argv[base+1];
212 if (argc >= base+3) {
216 if (isdigit(*argv[idx])) {
217 outputNo = atoi(argv[idx++]);
220 if (argc == idx + 2) {
221 if (!strcmp(argv[idx],
"-o")) {
222 outfilename = argv[idx+1];
224 }
else if (argc != idx) {
229 cerr << endl << name <<
": Running..." << endl;
231 cerr <<
"Reading file: \"" << wavname <<
"\", writing to ";
232 if (outfilename ==
"") {
233 cerr <<
"standard output" << endl;
235 cerr <<
"\"" << outfilename <<
"\"" << endl;
238 string::size_type sep = soname.find(
':');
240 if (sep != string::npos) {
241 plugid = soname.substr(sep + 1);
242 soname = soname.substr(0, sep);
244 sep = plugid.find(
':');
245 if (sep != string::npos) {
246 output = plugid.substr(sep + 1);
247 plugid = plugid.substr(0, sep);
255 if (output !=
"" && outputNo != -1) {
259 if (output ==
"" && outputNo == -1) {
263 return runPlugin(name, soname, plugid, output, outputNo,
264 wavname, outfilename, useFrames);
269 string output,
int outputNo,
string wavname,
270 string outfilename,
bool useFrames)
278 memset(&sfinfo, 0,
sizeof(SF_INFO));
280 sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo);
282 cerr << myname <<
": ERROR: Failed to open input file \"" 283 << wavname <<
"\": " << sf_strerror(sndfile) << endl;
288 if (outfilename !=
"") {
289 out =
new ofstream(outfilename.c_str(), ios::out);
291 cerr << myname <<
": ERROR: Failed to open output file \"" 292 << outfilename <<
"\" for writing" << endl;
299 (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE);
301 cerr << myname <<
": ERROR: Failed to load plugin \"" <<
id 302 <<
"\" from library \"" << soname <<
"\"" << endl;
311 cerr <<
"Running plugin: \"" << plugin->
getIdentifier() <<
"\"..." << endl;
327 if (blockSize == 0) {
332 stepSize = blockSize/2;
334 stepSize = blockSize;
336 }
else if (stepSize > blockSize) {
337 cerr <<
"WARNING: stepSize " << stepSize <<
" > blockSize " << blockSize <<
", resetting blockSize to ";
339 blockSize = stepSize * 2;
341 blockSize = stepSize;
343 cerr << blockSize << endl;
345 int overlapSize = blockSize - stepSize;
346 sf_count_t currentStep = 0;
347 int finalStepsRemaining = max(1, (blockSize / stepSize) - 1);
349 int channels = sfinfo.channels;
351 float *filebuf =
new float[blockSize * channels];
352 float **plugbuf =
new float*[channels];
353 for (
int c = 0; c < channels; ++c) plugbuf[c] =
new float[blockSize + 2];
355 cerr <<
"Using block size = " << blockSize <<
", step size = " 364 cerr <<
"Plugin accepts " << minch <<
" -> " << maxch <<
" channel(s)" << endl;
365 cerr <<
"Sound file has " << channels <<
" (will mix/augment if necessary)" << endl;
368 Plugin::OutputDescriptor od;
369 Plugin::FeatureSet features;
376 RealTime adjustment = RealTime::zeroTime;
378 if (outputs.empty()) {
379 cerr <<
"ERROR: Plugin has no outputs!" << endl;
385 for (
size_t oi = 0; oi < outputs.size(); ++oi) {
386 if (outputs[oi].identifier == output) {
393 cerr <<
"ERROR: Non-existent output \"" << output <<
"\" requested" << endl;
399 if (
int(outputs.size()) <= outputNo) {
400 cerr <<
"ERROR: Output " << outputNo <<
" requested, but plugin has only " << outputs.size() <<
" output(s)" << endl;
405 od = outputs[outputNo];
406 cerr <<
"Output is: \"" << od.identifier <<
"\"" << endl;
408 if (!plugin->
initialise(channels, stepSize, blockSize)) {
409 cerr <<
"ERROR: Plugin initialise (channels = " << channels
410 <<
", stepSize = " << stepSize <<
", blockSize = " 411 << blockSize <<
") failed." << endl;
429 if ((blockSize==stepSize) || (currentStep==0)) {
431 if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) {
432 cerr <<
"ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
435 if (count != blockSize) --finalStepsRemaining;
438 memmove(filebuf, filebuf + (stepSize * channels), overlapSize * channels *
sizeof(
float));
439 if ((count = sf_readf_float(sndfile, filebuf + (overlapSize * channels), stepSize)) < 0) {
440 cerr <<
"ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
443 if (count != stepSize) --finalStepsRemaining;
444 count += overlapSize;
447 for (
int c = 0; c < channels; ++c) {
450 plugbuf[c][j] = filebuf[j * sfinfo.channels + c];
453 while (j < blockSize) {
454 plugbuf[c][j] = 0.0f;
459 rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
461 features = plugin->
process(plugbuf, rt);
464 (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
465 sfinfo.samplerate, od, outputNo, features, out, useFrames);
467 if (sfinfo.frames > 0){
469 progress = (int)((
float(currentStep * stepSize) / sfinfo.frames) * 100.f + 0.5f);
470 if (progress != pp && out) {
471 cerr <<
"\r" << progress <<
"%";
477 }
while (finalStepsRemaining > 0);
479 if (out) cerr <<
"\rDone" << endl;
481 rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
485 printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
486 sfinfo.samplerate, od, outputNo, features, out, useFrames);
503 return time.
sec + double(time.
nsec + 1) / 1000000000.0;
508 const Plugin::OutputDescriptor &output,
int outputNo,
509 const Plugin::FeatureSet &features, ofstream *out,
bool useFrames)
511 static int featureCount = -1;
513 if (features.find(outputNo) == features.end())
return;
515 for (
size_t i = 0; i < features.at(outputNo).size(); ++i) {
517 const Plugin::Feature &f = features.at(outputNo).at(i);
522 if (output.sampleType == Plugin::OutputDescriptor::VariableSampleRate) {
525 }
else if (output.sampleType == Plugin::OutputDescriptor::FixedSampleRate) {
526 int n = featureCount + 1;
527 if (f.hasTimestamp) {
528 n = int(round(
toSeconds(f.timestamp) * output.sampleRate));
530 rt = RealTime::fromSeconds(
double(n) / output.sampleRate);
537 int displayFrame = frame;
540 displayFrame = RealTime::realTime2Frame(rt, sr);
543 (out ? *out : cout) << displayFrame;
546 displayFrame = RealTime::realTime2Frame(f.duration, sr);
547 (out ? *out : cout) <<
"," << displayFrame;
550 (out ? *out : cout) <<
":";
555 rt = RealTime::frame2RealTime(frame, sr);
558 (out ? *out : cout) << rt.
toString();
562 (out ? *out : cout) <<
"," << rt.
toString();
565 (out ? *out : cout) <<
":";
568 for (
unsigned int j = 0; j < f.values.size(); ++j) {
569 (out ? *out : cout) <<
" " << f.values[j];
571 (out ? *out : cout) <<
" " << f.label;
573 (out ? *out : cout) << endl;
581 cout <<
"\nVamp plugin search path: ";
584 vector<string> path = PluginHostAdapter::getPluginPath();
585 for (
size_t i = 0; i < path.size(); ++i) {
587 cout <<
"[" << path[i] <<
"]";
589 cout << path[i] << endl;
593 if (verbose) cout << endl;
600 string out =
'\n' + text +
'\n';
601 for (
size_t i = 0; i < text.length(); ++i) {
602 out += (level == 1 ?
'=' : level == 2 ?
'-' :
'~');
614 cout <<
"\nVamp plugin libraries found in search path:" << endl;
617 vector<PluginLoader::PluginKey> plugins = loader->
listPlugins();
618 typedef multimap<string, PluginLoader::PluginKey>
620 LibraryMap libraryMap;
622 for (
size_t i = 0; i < plugins.size(); ++i) {
624 libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
627 string prevPath =
"";
630 for (LibraryMap::iterator i = libraryMap.begin();
631 i != libraryMap.end(); ++i) {
633 string path = i->first;
634 PluginLoader::PluginKey key = i->second;
636 if (path != prevPath) {
640 cout <<
"\n " << path <<
":" << endl;
642 string::size_type ki = i->second.find(
':');
643 string text =
"Library \"" + i->second.substr(0, ki) +
"\"";
644 cout <<
"\n" <<
header(text, 1);
651 char c = char(
'A' + index);
652 if (c >
'Z') c = char(
'a' + (index - 26));
654 PluginLoader::PluginCategoryHierarchy category =
657 if (!category.empty()) {
658 for (
size_t ci = 0; ci < category.size(); ++ci) {
659 if (ci > 0) catstr +=
" > ";
660 catstr += category[ci];
666 cout <<
" [" << c <<
"] [v" 670 << plugin->
getMaker() <<
"]" << endl;
673 cout <<
" > " << catstr << endl;
683 cout <<
" - Identifier: " 685 cout <<
" - Plugin Version: " 687 cout <<
" - Vamp API Version: " 689 cout <<
" - Maker: \"" 690 << plugin->
getMaker() <<
"\"" << endl;
691 cout <<
" - Copyright: \"" 693 cout <<
" - Description: \"" 695 cout <<
" - Input Domain: " 697 "Time Domain" :
"Frequency Domain") << endl;
698 cout <<
" - Default Step Size: " 700 cout <<
" - Default Block Size: " 702 cout <<
" - Minimum Channels: " 704 cout <<
" - Maximum Channels: " 708 cout <<
"vamp:" << key << endl;
711 Plugin::OutputList outputs =
717 for (
size_t j = 0; j < params.size(); ++j) {
718 Plugin::ParameterDescriptor &pd(params[j]);
719 cout <<
"\nParameter " << j+1 <<
": \"" << pd.name <<
"\"" << endl;
720 cout <<
" - Identifier: " << pd.identifier << endl;
721 cout <<
" - Description: \"" << pd.description <<
"\"" << endl;
723 cout <<
" - Unit: " << pd.unit << endl;
725 cout <<
" - Range: ";
726 cout << pd.minValue <<
" -> " << pd.maxValue << endl;
727 cout <<
" - Default: ";
728 cout << pd.defaultValue << endl;
729 if (pd.isQuantized) {
730 cout <<
" - Quantize Step: " 731 << pd.quantizeStep << endl;
733 if (!pd.valueNames.empty()) {
734 cout <<
" - Value Names: ";
735 for (
size_t k = 0; k < pd.valueNames.size(); ++k) {
736 if (k > 0) cout <<
", ";
737 cout <<
"\"" << pd.valueNames[k] <<
"\"";
743 if (outputs.empty()) {
744 cout <<
"\n** Note: This plugin reports no outputs!" << endl;
746 for (
size_t j = 0; j < outputs.size(); ++j) {
747 Plugin::OutputDescriptor &od(outputs[j]);
748 cout <<
"\nOutput " << j+1 <<
": \"" << od.name <<
"\"" << endl;
749 cout <<
" - Identifier: " << od.identifier << endl;
750 cout <<
" - Description: \"" << od.description <<
"\"" << endl;
752 cout <<
" - Unit: " << od.unit << endl;
754 if (od.hasFixedBinCount) {
755 cout <<
" - Default Bin Count: " << od.binCount << endl;
757 if (!od.binNames.empty()) {
759 for (
size_t k = 0; k < od.binNames.size(); ++k) {
760 if (od.binNames[k] !=
"") {
765 cout <<
" - Bin Names: ";
766 for (
size_t k = 0; k < od.binNames.size(); ++k) {
767 if (k > 0) cout <<
", ";
768 cout <<
"\"" << od.binNames[k] <<
"\"";
773 if (od.hasKnownExtents) {
774 cout <<
" - Default Extents: ";
775 cout << od.minValue <<
" -> " << od.maxValue << endl;
777 if (od.isQuantized) {
778 cout <<
" - Quantize Step: " 779 << od.quantizeStep << endl;
781 cout <<
" - Sample Type: " 783 Plugin::OutputDescriptor::OneSamplePerStep ?
784 "One Sample Per Step" :
786 Plugin::OutputDescriptor::FixedSampleRate ?
787 "Fixed Sample Rate" :
788 "Variable Sample Rate") << endl;
790 Plugin::OutputDescriptor::OneSamplePerStep) {
791 cout <<
" - Default Rate: " 792 << od.sampleRate << endl;
794 cout <<
" - Has Duration: " 795 << (od.hasDuration ?
"Yes" :
"No") << endl;
800 for (
size_t j = 0; j < outputs.size(); ++j) {
802 cout <<
" (" << j <<
") " 803 << outputs[j].name <<
", \"" 804 << outputs[j].identifier <<
"\"" << endl;
805 if (outputs[j].description !=
"") {
807 << outputs[j].description << endl;
810 cout <<
"vamp:" << key <<
":" << outputs[j].identifier << endl;
832 vector<PluginLoader::PluginKey> plugins = loader->
listPlugins();
834 set<string> printedcats;
836 for (
size_t i = 0; i < plugins.size(); ++i) {
838 PluginLoader::PluginKey key = plugins[i];
840 PluginLoader::PluginCategoryHierarchy category =
844 if (!plugin)
continue;
848 if (category.empty()) catstr =
'|';
850 for (
size_t j = 0; j < category.size(); ++j) {
851 catstr += category[j];
853 if (printedcats.find(catstr) == printedcats.end()) {
854 std::cout << catstr << std::endl;
855 printedcats.insert(catstr);
PluginKey composePluginKey(std::string libraryName, std::string identifier)
Given a Vamp plugin library name and plugin identifier, return the corresponding plugin key in a form...
Vamp::Plugin is a base class for plugin instance classes that provide feature extraction from audio o...
void listPluginsInLibrary(string soname)
virtual size_t getPreferredStepSize() const
Get the preferred step size (window increment – the distance in sample frames between the start fram...
virtual int getPluginVersion() const =0
Get the version number of the plugin.
virtual std::string getName() const =0
Get a human-readable name or title of the plugin.
int runPlugin(string myname, string soname, string id, string output, int outputNo, string inputFile, string outfilename, bool frames)
void transformInput(float *, size_t)
void printFeatures(int, int, const Plugin::OutputDescriptor &, int, const Plugin::FeatureSet &, ofstream *, bool frames)
RealTime getTimestampAdjustment() const
Return the amount by which the timestamps supplied to process() are being incremented when they are p...
virtual std::string getIdentifier() const =0
Get the computer-usable name of the plugin.
virtual unsigned int getVampApiVersion() const
Get the Vamp API compatibility level of the plugin.
virtual OutputList getOutputDescriptors() const =0
Get the outputs of this plugin.
static string header(string text, int level)
WrapperType * getWrapper()
Return a pointer to the plugin wrapper of type WrapperType surrounding this wrapper's plugin...
virtual FeatureSet process(const float *const *inputBuffers, RealTime timestamp)=0
Process a single block of input data.
int main(int argc, char **argv)
std::string getLibraryPathForPlugin(PluginKey plugin)
Return the file path of the dynamic library from which the given plugin will be loaded (if available)...
PluginInputDomainAdapter is a Vamp plugin adapter that converts time-domain input into frequency-doma...
virtual std::string getMaker() const =0
Get the name of the author or vendor of the plugin in human-readable form.
PluginKeyList listPlugins()
Search for all available Vamp plugins, and return a list of them in the order in which they were foun...
virtual bool initialise(size_t inputChannels, size_t stepSize, size_t blockSize)=0
Initialise a plugin to prepare it for use with the given number of input channels, step size (window increment, in sample frames) and block size (window size, in sample frames).
#define VAMP_API_VERSION
Plugin API version.
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
PluginHostAdapter is a wrapper class that a Vamp host can use to make the C-language VampPluginDescri...
PluginWrapper is a simple base class for adapter plugins.
Plugin * loadPlugin(PluginKey key, float inputSampleRate, int adapterFlags=0)
Load a Vamp plugin, given its identifying key.
virtual InputDomain getInputDomain() const =0
Get the plugin's required input domain.
void printPluginCategoryList()
void usage(const char *name)
static double toSeconds(const RealTime &time)
Vamp::HostExt::PluginLoader is a convenience class for discovering and loading Vamp plugins using the...
virtual std::string getCopyright() const =0
Get the copyright statement or licensing summary for the plugin.
virtual FeatureSet getRemainingFeatures()=0
After all blocks have been processed, calculate and return any remaining features derived from the co...
virtual ParameterList getParameterDescriptors() const
Get the controllable parameters of this plugin.
virtual size_t getMaxChannelCount() const
Get the maximum supported number of input channels.
void fft(unsigned int, bool, double *, double *, double *, double *)
std::string toString() const
Return a human-readable debug-type string to full precision (probably not a format to show to a user ...
virtual std::string getDescription() const =0
Get a human-readable description for the plugin, typically a line of text that may optionally be disp...
void printPluginPath(bool verbose)
virtual size_t getPreferredBlockSize() const
Get the preferred block size (window size – the number of sample frames passed in each block to the ...
virtual size_t getMinChannelCount() const
Get the minimum supported number of input channels.
PluginCategoryHierarchy getPluginCategory(PluginKey plugin)
Return the category hierarchy for a Vamp plugin, given its identifying key.
void enumeratePlugins(Verbosity)