VampPluginSDK  2.5
vamp-simple-host.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Vamp
5 
6  An API for audio analysis and feature extraction plugins.
7 
8  Centre for Digital Music, Queen Mary, University of London.
9  Copyright 2006 Chris Cannam, copyright 2007-2008 QMUL.
10 
11  Permission is hereby granted, free of charge, to any person
12  obtaining a copy of this software and associated documentation
13  files (the "Software"), to deal in the Software without
14  restriction, including without limitation the rights to use, copy,
15  modify, merge, publish, distribute, sublicense, and/or sell copies
16  of the Software, and to permit persons to whom the Software is
17  furnished to do so, subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be
20  included in all copies or substantial portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
26  ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27  CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 
30  Except as contained in this notice, the names of the Centre for
31  Digital Music; Queen Mary, University of London; and Chris Cannam
32  shall not be used in advertising or otherwise to promote the sale,
33  use or other dealings in this Software without prior written
34  authorization.
35 */
36 
37 
38 /*
39  * This "simple" Vamp plugin host is no longer as simple as it was; it
40  * now has a lot of options and includes a lot of code to handle the
41  * various useful listing modes it supports.
42  *
43  * However, the runPlugin function still contains a reasonable
44  * implementation of a fairly generic Vamp plugin host capable of
45  * evaluating a given output on a given plugin for a sound file read
46  * via libsndfile.
47  */
48 
52 
53 #include <iostream>
54 #include <fstream>
55 #include <set>
56 #include <sndfile.h>
57 
58 #include <cstring>
59 #include <cstdlib>
60 
61 #include "system.h"
62 
63 #include <cmath>
64 
65 using namespace std;
66 
67 using Vamp::Plugin;
69 using Vamp::RealTime;
73 
74 #define HOST_VERSION "1.5"
75 
76 enum Verbosity {
81 };
82 
83 void printFeatures(int, int, int, Plugin::FeatureSet, ofstream *, bool frames);
84 void transformInput(float *, size_t);
85 void fft(unsigned int, bool, double *, double *, double *, double *);
86 void printPluginPath(bool verbose);
89 void listPluginsInLibrary(string soname);
90 int runPlugin(string myname, string soname, string id, string output,
91  int outputNo, string inputFile, string outfilename, bool frames);
92 
93 void usage(const char *name)
94 {
95  cerr << "\n"
96  << name << ": A command-line host for Vamp audio analysis plugins.\n\n"
97  "Centre for Digital Music, Queen Mary, University of London.\n"
98  "Copyright 2006-2009 Chris Cannam and QMUL.\n"
99  "Freely redistributable; published under a BSD-style license.\n\n"
100  "Usage:\n\n"
101  " " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin[:output] file.wav [-o out.txt]\n"
102  " " << name << " [-s] pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin file.wav [outputno] [-o out.txt]\n\n"
103  " -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n"
104  " audio data in \"file.wav\", retrieving the named \"output\", or output\n"
105  " number \"outputno\" (the first output by default) and dumping it to\n"
106  " standard output, or to \"out.txt\" if the -o option is given.\n\n"
107  " \"pluginlibrary\" should be a library name, not a file path; the\n"
108  " standard Vamp library search path will be used to locate it. If\n"
109  " a file path is supplied, the directory part(s) will be ignored.\n\n"
110  " If the -s option is given, results will be labelled with the audio\n"
111  " sample frame at which they occur. Otherwise, they will be labelled\n"
112  " with time in seconds.\n\n"
113  " " << name << " -l\n"
114  " " << name << " --list\n\n"
115  " -- List the plugin libraries and Vamp plugins in the library search path\n"
116  " in a verbose human-readable format.\n\n"
117  " " << name << " -L\n"
118  " " << name << " --list-full\n\n"
119  " -- List all data reported by all the Vamp plugins in the library search\n"
120  " path in a very verbose human-readable format.\n\n"
121  " " << name << " --list-ids\n\n"
122  " -- List the plugins in the search path in a terse machine-readable format,\n"
123  " in the form vamp:soname:identifier.\n\n"
124  " " << name << " --list-outputs\n\n"
125  " -- List the outputs for plugins in the search path in a machine-readable\n"
126  " format, in the form vamp:soname:identifier:output.\n\n"
127  " " << name << " --list-by-category\n\n"
128  " -- List the plugins as a plugin index by category, in a machine-readable\n"
129  " format. The format may change in future releases.\n\n"
130  " " << name << " -p\n\n"
131  " -- Print out the Vamp library search path.\n\n"
132  " " << name << " -v\n\n"
133  " -- Display version information only.\n"
134  << endl;
135  exit(2);
136 }
137 
138 int main(int argc, char **argv)
139 {
140  char *scooter = argv[0];
141  char *name = 0;
142  while (scooter && *scooter) {
143  if (*scooter == '/' || *scooter == '\\') name = ++scooter;
144  else ++scooter;
145  }
146  if (!name || !*name) name = argv[0];
147 
148  if (argc < 2) usage(name);
149 
150  if (argc == 2) {
151 
152  if (!strcmp(argv[1], "-v")) {
153 
154  cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl
155  << "Vamp API version: " << VAMP_API_VERSION << endl
156  << "Vamp SDK version: " << VAMP_SDK_VERSION << endl;
157  return 0;
158 
159  } else if (!strcmp(argv[1], "-l") || !strcmp(argv[1], "--list")) {
160 
161  printPluginPath(true);
163  return 0;
164 
165  } else if (!strcmp(argv[1], "-L") || !strcmp(argv[1], "--list-full")) {
166 
168  return 0;
169 
170  } else if (!strcmp(argv[1], "-p")) {
171 
172  printPluginPath(false);
173  return 0;
174 
175  } else if (!strcmp(argv[1], "--list-ids")) {
176 
178  return 0;
179 
180  } else if (!strcmp(argv[1], "--list-outputs")) {
181 
183  return 0;
184 
185  } else if (!strcmp(argv[1], "--list-by-category")) {
186 
188  return 0;
189 
190  } else usage(name);
191  }
192 
193  if (argc < 3) usage(name);
194 
195  bool useFrames = false;
196 
197  int base = 1;
198  if (!strcmp(argv[1], "-s")) {
199  useFrames = true;
200  base = 2;
201  }
202 
203  string soname = argv[base];
204  string wavname = argv[base+1];
205  string plugid = "";
206  string output = "";
207  int outputNo = -1;
208  string outfilename;
209 
210  if (argc >= base+3) {
211 
212  int idx = base+2;
213 
214  if (isdigit(*argv[idx])) {
215  outputNo = atoi(argv[idx++]);
216  }
217 
218  if (argc == idx + 2) {
219  if (!strcmp(argv[idx], "-o")) {
220  outfilename = argv[idx+1];
221  } else usage(name);
222  } else if (argc != idx) {
223  (usage(name));
224  }
225  }
226 
227  cerr << endl << name << ": Running..." << endl;
228 
229  cerr << "Reading file: \"" << wavname << "\", writing to ";
230  if (outfilename == "") {
231  cerr << "standard output" << endl;
232  } else {
233  cerr << "\"" << outfilename << "\"" << endl;
234  }
235 
236  string::size_type sep = soname.find(':');
237 
238  if (sep != string::npos) {
239  plugid = soname.substr(sep + 1);
240  soname = soname.substr(0, sep);
241 
242  sep = plugid.find(':');
243  if (sep != string::npos) {
244  output = plugid.substr(sep + 1);
245  plugid = plugid.substr(0, sep);
246  }
247  }
248 
249  if (plugid == "") {
250  usage(name);
251  }
252 
253  if (output != "" && outputNo != -1) {
254  usage(name);
255  }
256 
257  if (output == "" && outputNo == -1) {
258  outputNo = 0;
259  }
260 
261  return runPlugin(name, soname, plugid, output, outputNo,
262  wavname, outfilename, useFrames);
263 }
264 
265 
266 int runPlugin(string myname, string soname, string id,
267  string output, int outputNo, string wavname,
268  string outfilename, bool useFrames)
269 {
270  PluginLoader *loader = PluginLoader::getInstance();
271 
272  PluginLoader::PluginKey key = loader->composePluginKey(soname, id);
273 
274  SNDFILE *sndfile;
275  SF_INFO sfinfo;
276  memset(&sfinfo, 0, sizeof(SF_INFO));
277 
278  sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo);
279  if (!sndfile) {
280  cerr << myname << ": ERROR: Failed to open input file \""
281  << wavname << "\": " << sf_strerror(sndfile) << endl;
282  return 1;
283  }
284 
285  ofstream *out = 0;
286  if (outfilename != "") {
287  out = new ofstream(outfilename.c_str(), ios::out);
288  if (!*out) {
289  cerr << myname << ": ERROR: Failed to open output file \""
290  << outfilename << "\" for writing" << endl;
291  delete out;
292  return 1;
293  }
294  }
295 
296  Plugin *plugin = loader->loadPlugin
297  (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE);
298  if (!plugin) {
299  cerr << myname << ": ERROR: Failed to load plugin \"" << id
300  << "\" from library \"" << soname << "\"" << endl;
301  sf_close(sndfile);
302  if (out) {
303  out->close();
304  delete out;
305  }
306  return 1;
307  }
308 
309  cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl;
310 
311  // Note that the following would be much simpler if we used a
312  // PluginBufferingAdapter as well -- i.e. if we had passed
313  // PluginLoader::ADAPT_ALL to loader->loadPlugin() above, instead
314  // of ADAPT_ALL_SAFE. Then we could simply specify our own block
315  // size, keep the step size equal to the block size, and ignore
316  // the plugin's bleatings. However, there are some issues with
317  // using a PluginBufferingAdapter that make the results sometimes
318  // technically different from (if effectively the same as) the
319  // un-adapted plugin, so we aren't doing that here. See the
320  // PluginBufferingAdapter documentation for details.
321 
322  int blockSize = plugin->getPreferredBlockSize();
323  int stepSize = plugin->getPreferredStepSize();
324 
325  if (blockSize == 0) {
326  blockSize = 1024;
327  }
328  if (stepSize == 0) {
329  if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
330  stepSize = blockSize/2;
331  } else {
332  stepSize = blockSize;
333  }
334  } else if (stepSize > blockSize) {
335  cerr << "WARNING: stepSize " << stepSize << " > blockSize " << blockSize << ", resetting blockSize to ";
336  if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
337  blockSize = stepSize * 2;
338  } else {
339  blockSize = stepSize;
340  }
341  cerr << blockSize << endl;
342  }
343  int overlapSize = blockSize - stepSize;
344  sf_count_t currentStep = 0;
345  int finalStepsRemaining = max(1, (blockSize / stepSize) - 1); // at end of file, this many part-silent frames needed after we hit EOF
346 
347  int channels = sfinfo.channels;
348 
349  float *filebuf = new float[blockSize * channels];
350  float **plugbuf = new float*[channels];
351  for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2];
352 
353  cerr << "Using block size = " << blockSize << ", step size = "
354  << stepSize << endl;
355 
356  // The channel queries here are for informational purposes only --
357  // a PluginChannelAdapter is being used automatically behind the
358  // scenes, and it will take case of any channel mismatch
359 
360  int minch = plugin->getMinChannelCount();
361  int maxch = plugin->getMaxChannelCount();
362  cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl;
363  cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl;
364 
365  Plugin::OutputList outputs = plugin->getOutputDescriptors();
366  Plugin::OutputDescriptor od;
367 
368  int returnValue = 1;
369  int progress = 0;
370 
371  RealTime rt;
372  PluginWrapper *wrapper = 0;
373  RealTime adjustment = RealTime::zeroTime;
374 
375  if (outputs.empty()) {
376  cerr << "ERROR: Plugin has no outputs!" << endl;
377  goto done;
378  }
379 
380  if (outputNo < 0) {
381 
382  for (size_t oi = 0; oi < outputs.size(); ++oi) {
383  if (outputs[oi].identifier == output) {
384  outputNo = oi;
385  break;
386  }
387  }
388 
389  if (outputNo < 0) {
390  cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl;
391  goto done;
392  }
393 
394  } else {
395 
396  if (int(outputs.size()) <= outputNo) {
397  cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl;
398  goto done;
399  }
400  }
401 
402  od = outputs[outputNo];
403  cerr << "Output is: \"" << od.identifier << "\"" << endl;
404 
405  if (!plugin->initialise(channels, stepSize, blockSize)) {
406  cerr << "ERROR: Plugin initialise (channels = " << channels
407  << ", stepSize = " << stepSize << ", blockSize = "
408  << blockSize << ") failed." << endl;
409  goto done;
410  }
411 
412  wrapper = dynamic_cast<PluginWrapper *>(plugin);
413  if (wrapper) {
414  // See documentation for
415  // PluginInputDomainAdapter::getTimestampAdjustment
418  if (ida) adjustment = ida->getTimestampAdjustment();
419  }
420 
421  // Here we iterate over the frames, avoiding asking the numframes in case it's streaming input.
422  do {
423 
424  int count;
425 
426  if ((blockSize==stepSize) || (currentStep==0)) {
427  // read a full fresh block
428  if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) {
429  cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
430  break;
431  }
432  if (count != blockSize) --finalStepsRemaining;
433  } else {
434  // otherwise shunt the existing data down and read the remainder.
435  memmove(filebuf, filebuf + (stepSize * channels), overlapSize * channels * sizeof(float));
436  if ((count = sf_readf_float(sndfile, filebuf + (overlapSize * channels), stepSize)) < 0) {
437  cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
438  break;
439  }
440  if (count != stepSize) --finalStepsRemaining;
441  count += overlapSize;
442  }
443 
444  for (int c = 0; c < channels; ++c) {
445  int j = 0;
446  while (j < count) {
447  plugbuf[c][j] = filebuf[j * sfinfo.channels + c];
448  ++j;
449  }
450  while (j < blockSize) {
451  plugbuf[c][j] = 0.0f;
452  ++j;
453  }
454  }
455 
456  rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
457 
459  (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
460  sfinfo.samplerate, outputNo, plugin->process(plugbuf, rt),
461  out, useFrames);
462 
463  if (sfinfo.frames > 0){
464  int pp = progress;
465  progress = (int)((float(currentStep * stepSize) / sfinfo.frames) * 100.f + 0.5f);
466  if (progress != pp && out) {
467  cerr << "\r" << progress << "%";
468  }
469  }
470 
471  ++currentStep;
472 
473  } while (finalStepsRemaining > 0);
474 
475  if (out) cerr << "\rDone" << endl;
476 
477  rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
478 
479  printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
480  sfinfo.samplerate, outputNo,
481  plugin->getRemainingFeatures(), out, useFrames);
482 
483  returnValue = 0;
484 
485 done:
486  delete plugin;
487  if (out) {
488  out->close();
489  delete out;
490  }
491  sf_close(sndfile);
492  return returnValue;
493 }
494 
495 void
496 printFeatures(int frame, int sr, int output,
497  Plugin::FeatureSet features, ofstream *out, bool useFrames)
498 {
499  for (unsigned int i = 0; i < features[output].size(); ++i) {
500 
501  if (useFrames) {
502 
503  int displayFrame = frame;
504 
505  if (features[output][i].hasTimestamp) {
506  displayFrame = RealTime::realTime2Frame
507  (features[output][i].timestamp, sr);
508  }
509 
510  (out ? *out : cout) << displayFrame;
511 
512  if (features[output][i].hasDuration) {
513  displayFrame = RealTime::realTime2Frame
514  (features[output][i].duration, sr);
515  (out ? *out : cout) << "," << displayFrame;
516  }
517 
518  (out ? *out : cout) << ":";
519 
520  } else {
521 
522  RealTime rt = RealTime::frame2RealTime(frame, sr);
523 
524  if (features[output][i].hasTimestamp) {
525  rt = features[output][i].timestamp;
526  }
527 
528  (out ? *out : cout) << rt.toString();
529 
530  if (features[output][i].hasDuration) {
531  rt = features[output][i].duration;
532  (out ? *out : cout) << "," << rt.toString();
533  }
534 
535  (out ? *out : cout) << ":";
536  }
537 
538  for (unsigned int j = 0; j < features[output][i].values.size(); ++j) {
539  (out ? *out : cout) << " " << features[output][i].values[j];
540  }
541  (out ? *out : cout) << " " << features[output][i].label;
542 
543  (out ? *out : cout) << endl;
544  }
545 }
546 
547 void
548 printPluginPath(bool verbose)
549 {
550  if (verbose) {
551  cout << "\nVamp plugin search path: ";
552  }
553 
554  vector<string> path = PluginHostAdapter::getPluginPath();
555  for (size_t i = 0; i < path.size(); ++i) {
556  if (verbose) {
557  cout << "[" << path[i] << "]";
558  } else {
559  cout << path[i] << endl;
560  }
561  }
562 
563  if (verbose) cout << endl;
564 }
565 
566 static
567 string
568 header(string text, int level)
569 {
570  string out = '\n' + text + '\n';
571  for (size_t i = 0; i < text.length(); ++i) {
572  out += (level == 1 ? '=' : level == 2 ? '-' : '~');
573  }
574  out += '\n';
575  return out;
576 }
577 
578 void
580 {
581  PluginLoader *loader = PluginLoader::getInstance();
582 
583  if (verbosity == PluginInformation) {
584  cout << "\nVamp plugin libraries found in search path:" << endl;
585  }
586 
587  vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
588  typedef multimap<string, PluginLoader::PluginKey>
589  LibraryMap;
590  LibraryMap libraryMap;
591 
592  for (size_t i = 0; i < plugins.size(); ++i) {
593  string path = loader->getLibraryPathForPlugin(plugins[i]);
594  libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
595  }
596 
597  string prevPath = "";
598  int index = 0;
599 
600  for (LibraryMap::iterator i = libraryMap.begin();
601  i != libraryMap.end(); ++i) {
602 
603  string path = i->first;
604  PluginLoader::PluginKey key = i->second;
605 
606  if (path != prevPath) {
607  prevPath = path;
608  index = 0;
609  if (verbosity == PluginInformation) {
610  cout << "\n " << path << ":" << endl;
611  } else if (verbosity == PluginInformationDetailed) {
612  string::size_type ki = i->second.find(':');
613  string text = "Library \"" + i->second.substr(0, ki) + "\"";
614  cout << "\n" << header(text, 1);
615  }
616  }
617 
618  Plugin *plugin = loader->loadPlugin(key, 48000);
619  if (plugin) {
620 
621  char c = char('A' + index);
622  if (c > 'Z') c = char('a' + (index - 26));
623 
624  PluginLoader::PluginCategoryHierarchy category =
625  loader->getPluginCategory(key);
626  string catstr;
627  if (!category.empty()) {
628  for (size_t ci = 0; ci < category.size(); ++ci) {
629  if (ci > 0) catstr += " > ";
630  catstr += category[ci];
631  }
632  }
633 
634  if (verbosity == PluginInformation) {
635 
636  cout << " [" << c << "] [v"
637  << plugin->getVampApiVersion() << "] "
638  << plugin->getName() << ", \""
639  << plugin->getIdentifier() << "\"" << " ["
640  << plugin->getMaker() << "]" << endl;
641 
642  if (catstr != "") {
643  cout << " > " << catstr << endl;
644  }
645 
646  if (plugin->getDescription() != "") {
647  cout << " - " << plugin->getDescription() << endl;
648  }
649 
650  } else if (verbosity == PluginInformationDetailed) {
651 
652  cout << header(plugin->getName(), 2);
653  cout << " - Identifier: "
654  << key << endl;
655  cout << " - Plugin Version: "
656  << plugin->getPluginVersion() << endl;
657  cout << " - Vamp API Version: "
658  << plugin->getVampApiVersion() << endl;
659  cout << " - Maker: \""
660  << plugin->getMaker() << "\"" << endl;
661  cout << " - Copyright: \""
662  << plugin->getCopyright() << "\"" << endl;
663  cout << " - Description: \""
664  << plugin->getDescription() << "\"" << endl;
665  cout << " - Input Domain: "
666  << (plugin->getInputDomain() == Vamp::Plugin::TimeDomain ?
667  "Time Domain" : "Frequency Domain") << endl;
668  cout << " - Default Step Size: "
669  << plugin->getPreferredStepSize() << endl;
670  cout << " - Default Block Size: "
671  << plugin->getPreferredBlockSize() << endl;
672  cout << " - Minimum Channels: "
673  << plugin->getMinChannelCount() << endl;
674  cout << " - Maximum Channels: "
675  << plugin->getMaxChannelCount() << endl;
676 
677  } else if (verbosity == PluginIds) {
678  cout << "vamp:" << key << endl;
679  }
680 
681  Plugin::OutputList outputs =
682  plugin->getOutputDescriptors();
683 
684  if (verbosity == PluginInformationDetailed) {
685 
686  Plugin::ParameterList params = plugin->getParameterDescriptors();
687  for (size_t j = 0; j < params.size(); ++j) {
688  Plugin::ParameterDescriptor &pd(params[j]);
689  cout << "\nParameter " << j+1 << ": \"" << pd.name << "\"" << endl;
690  cout << " - Identifier: " << pd.identifier << endl;
691  cout << " - Description: \"" << pd.description << "\"" << endl;
692  if (pd.unit != "") {
693  cout << " - Unit: " << pd.unit << endl;
694  }
695  cout << " - Range: ";
696  cout << pd.minValue << " -> " << pd.maxValue << endl;
697  cout << " - Default: ";
698  cout << pd.defaultValue << endl;
699  if (pd.isQuantized) {
700  cout << " - Quantize Step: "
701  << pd.quantizeStep << endl;
702  }
703  if (!pd.valueNames.empty()) {
704  cout << " - Value Names: ";
705  for (size_t k = 0; k < pd.valueNames.size(); ++k) {
706  if (k > 0) cout << ", ";
707  cout << "\"" << pd.valueNames[k] << "\"";
708  }
709  cout << endl;
710  }
711  }
712 
713  if (outputs.empty()) {
714  cout << "\n** Note: This plugin reports no outputs!" << endl;
715  }
716  for (size_t j = 0; j < outputs.size(); ++j) {
717  Plugin::OutputDescriptor &od(outputs[j]);
718  cout << "\nOutput " << j+1 << ": \"" << od.name << "\"" << endl;
719  cout << " - Identifier: " << od.identifier << endl;
720  cout << " - Description: \"" << od.description << "\"" << endl;
721  if (od.unit != "") {
722  cout << " - Unit: " << od.unit << endl;
723  }
724  if (od.hasFixedBinCount) {
725  cout << " - Default Bin Count: " << od.binCount << endl;
726  }
727  if (!od.binNames.empty()) {
728  bool have = false;
729  for (size_t k = 0; k < od.binNames.size(); ++k) {
730  if (od.binNames[k] != "") {
731  have = true; break;
732  }
733  }
734  if (have) {
735  cout << " - Bin Names: ";
736  for (size_t k = 0; k < od.binNames.size(); ++k) {
737  if (k > 0) cout << ", ";
738  cout << "\"" << od.binNames[k] << "\"";
739  }
740  cout << endl;
741  }
742  }
743  if (od.hasKnownExtents) {
744  cout << " - Default Extents: ";
745  cout << od.minValue << " -> " << od.maxValue << endl;
746  }
747  if (od.isQuantized) {
748  cout << " - Quantize Step: "
749  << od.quantizeStep << endl;
750  }
751  cout << " - Sample Type: "
752  << (od.sampleType ==
753  Plugin::OutputDescriptor::OneSamplePerStep ?
754  "One Sample Per Step" :
755  od.sampleType ==
756  Plugin::OutputDescriptor::FixedSampleRate ?
757  "Fixed Sample Rate" :
758  "Variable Sample Rate") << endl;
759  if (od.sampleType !=
760  Plugin::OutputDescriptor::OneSamplePerStep) {
761  cout << " - Default Rate: "
762  << od.sampleRate << endl;
763  }
764  cout << " - Has Duration: "
765  << (od.hasDuration ? "Yes" : "No") << endl;
766  }
767  }
768 
769  if (outputs.size() > 1 || verbosity == PluginOutputIds) {
770  for (size_t j = 0; j < outputs.size(); ++j) {
771  if (verbosity == PluginInformation) {
772  cout << " (" << j << ") "
773  << outputs[j].name << ", \""
774  << outputs[j].identifier << "\"" << endl;
775  if (outputs[j].description != "") {
776  cout << " - "
777  << outputs[j].description << endl;
778  }
779  } else if (verbosity == PluginOutputIds) {
780  cout << "vamp:" << key << ":" << outputs[j].identifier << endl;
781  }
782  }
783  }
784 
785  ++index;
786 
787  delete plugin;
788  }
789  }
790 
791  if (verbosity == PluginInformation ||
792  verbosity == PluginInformationDetailed) {
793  cout << endl;
794  }
795 }
796 
797 void
799 {
800  PluginLoader *loader = PluginLoader::getInstance();
801 
802  vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
803 
804  set<string> printedcats;
805 
806  for (size_t i = 0; i < plugins.size(); ++i) {
807 
808  PluginLoader::PluginKey key = plugins[i];
809 
810  PluginLoader::PluginCategoryHierarchy category =
811  loader->getPluginCategory(key);
812 
813  Plugin *plugin = loader->loadPlugin(key, 48000);
814  if (!plugin) continue;
815 
816  string catstr = "";
817 
818  if (category.empty()) catstr = '|';
819  else {
820  for (size_t j = 0; j < category.size(); ++j) {
821  catstr += category[j];
822  catstr += '|';
823  if (printedcats.find(catstr) == printedcats.end()) {
824  std::cout << catstr << std::endl;
825  printedcats.insert(catstr);
826  }
827  }
828  }
829 
830  std::cout << catstr << key << ":::" << plugin->getName() << ":::" << plugin->getMaker() << ":::" << plugin->getDescription() << std::endl;
831  }
832 }
833 
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)
RealTime getTimestampAdjustment() const
Return the amount by which the timestamps supplied to process() are being incremented when they are p...
#define VAMP_SDK_VERSION
Definition: plugguard.h:74
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.
#define PLUGIN_SUFFIX
Definition: system.h:67
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.
Definition: vamp.h:53
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...
void printFeatures(int, int, int, Plugin::FeatureSet, ofstream *, bool frames)
PluginWrapper is a simple base class for adapter plugins.
Definition: PluginWrapper.h:62
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)
#define HOST_VERSION
Vamp::HostExt::PluginLoader is a convenience class for discovering and loading Vamp plugins using the...
Definition: PluginLoader.h:75
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)