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 << " --list-full\n\n"
118  " -- List all data reported by all the Vamp plugins in the library search\n"
119  " path in a very verbose human-readable format.\n\n"
120  " " << name << " --list-ids\n\n"
121  " -- List the plugins in the search path in a terse machine-readable format,\n"
122  " in the form vamp:soname:identifier.\n\n"
123  " " << name << " --list-outputs\n\n"
124  " -- List the outputs for plugins in the search path in a machine-readable\n"
125  " format, in the form vamp:soname:identifier:output.\n\n"
126  " " << name << " --list-by-category\n\n"
127  " -- List the plugins as a plugin index by category, in a machine-readable\n"
128  " format. The format may change in future releases.\n\n"
129  " " << name << " -p\n\n"
130  " -- Print out the Vamp library search path.\n\n"
131  " " << name << " -v\n\n"
132  " -- Display version information only.\n"
133  << endl;
134  exit(2);
135 }
136 
137 int main(int argc, char **argv)
138 {
139  char *scooter = argv[0];
140  char *name = 0;
141  while (scooter && *scooter) {
142  if (*scooter == '/' || *scooter == '\\') name = ++scooter;
143  else ++scooter;
144  }
145  if (!name || !*name) name = argv[0];
146 
147  if (argc < 2) usage(name);
148 
149  if (argc == 2) {
150 
151  if (!strcmp(argv[1], "-v")) {
152 
153  cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl
154  << "Vamp API version: " << VAMP_API_VERSION << endl
155  << "Vamp SDK version: " << VAMP_SDK_VERSION << endl;
156  return 0;
157 
158  } else if (!strcmp(argv[1], "-l") || !strcmp(argv[1], "--list")) {
159 
160  printPluginPath(true);
162  return 0;
163 
164  } else if (!strcmp(argv[1], "--list-full")) {
165 
167  return 0;
168 
169  } else if (!strcmp(argv[1], "-p")) {
170 
171  printPluginPath(false);
172  return 0;
173 
174  } else if (!strcmp(argv[1], "--list-ids")) {
175 
177  return 0;
178 
179  } else if (!strcmp(argv[1], "--list-outputs")) {
180 
182  return 0;
183 
184  } else if (!strcmp(argv[1], "--list-by-category")) {
185 
187  return 0;
188 
189  } else usage(name);
190  }
191 
192  if (argc < 3) usage(name);
193 
194  bool useFrames = false;
195 
196  int base = 1;
197  if (!strcmp(argv[1], "-s")) {
198  useFrames = true;
199  base = 2;
200  }
201 
202  string soname = argv[base];
203  string wavname = argv[base+1];
204  string plugid = "";
205  string output = "";
206  int outputNo = -1;
207  string outfilename;
208 
209  if (argc >= base+3) {
210 
211  int idx = base+2;
212 
213  if (isdigit(*argv[idx])) {
214  outputNo = atoi(argv[idx++]);
215  }
216 
217  if (argc == idx + 2) {
218  if (!strcmp(argv[idx], "-o")) {
219  outfilename = argv[idx+1];
220  } else usage(name);
221  } else if (argc != idx) {
222  (usage(name));
223  }
224  }
225 
226  cerr << endl << name << ": Running..." << endl;
227 
228  cerr << "Reading file: \"" << wavname << "\", writing to ";
229  if (outfilename == "") {
230  cerr << "standard output" << endl;
231  } else {
232  cerr << "\"" << outfilename << "\"" << endl;
233  }
234 
235  string::size_type sep = soname.find(':');
236 
237  if (sep != string::npos) {
238  plugid = soname.substr(sep + 1);
239  soname = soname.substr(0, sep);
240 
241  sep = plugid.find(':');
242  if (sep != string::npos) {
243  output = plugid.substr(sep + 1);
244  plugid = plugid.substr(0, sep);
245  }
246  }
247 
248  if (plugid == "") {
249  usage(name);
250  }
251 
252  if (output != "" && outputNo != -1) {
253  usage(name);
254  }
255 
256  if (output == "" && outputNo == -1) {
257  outputNo = 0;
258  }
259 
260  return runPlugin(name, soname, plugid, output, outputNo,
261  wavname, outfilename, useFrames);
262 }
263 
264 
265 int runPlugin(string myname, string soname, string id,
266  string output, int outputNo, string wavname,
267  string outfilename, bool useFrames)
268 {
269  PluginLoader *loader = PluginLoader::getInstance();
270 
271  PluginLoader::PluginKey key = loader->composePluginKey(soname, id);
272 
273  SNDFILE *sndfile;
274  SF_INFO sfinfo;
275  memset(&sfinfo, 0, sizeof(SF_INFO));
276 
277  sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo);
278  if (!sndfile) {
279  cerr << myname << ": ERROR: Failed to open input file \""
280  << wavname << "\": " << sf_strerror(sndfile) << endl;
281  return 1;
282  }
283 
284  ofstream *out = 0;
285  if (outfilename != "") {
286  out = new ofstream(outfilename.c_str(), ios::out);
287  if (!*out) {
288  cerr << myname << ": ERROR: Failed to open output file \""
289  << outfilename << "\" for writing" << endl;
290  delete out;
291  return 1;
292  }
293  }
294 
295  Plugin *plugin = loader->loadPlugin
296  (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE);
297  if (!plugin) {
298  cerr << myname << ": ERROR: Failed to load plugin \"" << id
299  << "\" from library \"" << soname << "\"" << endl;
300  sf_close(sndfile);
301  if (out) {
302  out->close();
303  delete out;
304  }
305  return 1;
306  }
307 
308  cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl;
309 
310  // Note that the following would be much simpler if we used a
311  // PluginBufferingAdapter as well -- i.e. if we had passed
312  // PluginLoader::ADAPT_ALL to loader->loadPlugin() above, instead
313  // of ADAPT_ALL_SAFE. Then we could simply specify our own block
314  // size, keep the step size equal to the block size, and ignore
315  // the plugin's bleatings. However, there are some issues with
316  // using a PluginBufferingAdapter that make the results sometimes
317  // technically different from (if effectively the same as) the
318  // un-adapted plugin, so we aren't doing that here. See the
319  // PluginBufferingAdapter documentation for details.
320 
321  int blockSize = plugin->getPreferredBlockSize();
322  int stepSize = plugin->getPreferredStepSize();
323 
324  if (blockSize == 0) {
325  blockSize = 1024;
326  }
327  if (stepSize == 0) {
328  if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
329  stepSize = blockSize/2;
330  } else {
331  stepSize = blockSize;
332  }
333  } else if (stepSize > blockSize) {
334  cerr << "WARNING: stepSize " << stepSize << " > blockSize " << blockSize << ", resetting blockSize to ";
335  if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
336  blockSize = stepSize * 2;
337  } else {
338  blockSize = stepSize;
339  }
340  cerr << blockSize << endl;
341  }
342  int overlapSize = blockSize - stepSize;
343  sf_count_t currentStep = 0;
344  int finalStepsRemaining = max(1, (blockSize / stepSize) - 1); // at end of file, this many part-silent frames needed after we hit EOF
345 
346  int channels = sfinfo.channels;
347 
348  float *filebuf = new float[blockSize * channels];
349  float **plugbuf = new float*[channels];
350  for (int c = 0; c < channels; ++c) plugbuf[c] = new float[blockSize + 2];
351 
352  cerr << "Using block size = " << blockSize << ", step size = "
353  << stepSize << endl;
354 
355  // The channel queries here are for informational purposes only --
356  // a PluginChannelAdapter is being used automatically behind the
357  // scenes, and it will take case of any channel mismatch
358 
359  int minch = plugin->getMinChannelCount();
360  int maxch = plugin->getMaxChannelCount();
361  cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl;
362  cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl;
363 
364  Plugin::OutputList outputs = plugin->getOutputDescriptors();
365  Plugin::OutputDescriptor od;
366 
367  int returnValue = 1;
368  int progress = 0;
369 
370  RealTime rt;
371  PluginWrapper *wrapper = 0;
372  RealTime adjustment = RealTime::zeroTime;
373 
374  if (outputs.empty()) {
375  cerr << "ERROR: Plugin has no outputs!" << endl;
376  goto done;
377  }
378 
379  if (outputNo < 0) {
380 
381  for (size_t oi = 0; oi < outputs.size(); ++oi) {
382  if (outputs[oi].identifier == output) {
383  outputNo = oi;
384  break;
385  }
386  }
387 
388  if (outputNo < 0) {
389  cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl;
390  goto done;
391  }
392 
393  } else {
394 
395  if (int(outputs.size()) <= outputNo) {
396  cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl;
397  goto done;
398  }
399  }
400 
401  od = outputs[outputNo];
402  cerr << "Output is: \"" << od.identifier << "\"" << endl;
403 
404  if (!plugin->initialise(channels, stepSize, blockSize)) {
405  cerr << "ERROR: Plugin initialise (channels = " << channels
406  << ", stepSize = " << stepSize << ", blockSize = "
407  << blockSize << ") failed." << endl;
408  goto done;
409  }
410 
411  wrapper = dynamic_cast<PluginWrapper *>(plugin);
412  if (wrapper) {
413  // See documentation for
414  // PluginInputDomainAdapter::getTimestampAdjustment
417  if (ida) adjustment = ida->getTimestampAdjustment();
418  }
419 
420  // Here we iterate over the frames, avoiding asking the numframes in case it's streaming input.
421  do {
422 
423  int count;
424 
425  if ((blockSize==stepSize) || (currentStep==0)) {
426  // read a full fresh block
427  if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) {
428  cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
429  break;
430  }
431  if (count != blockSize) --finalStepsRemaining;
432  } else {
433  // otherwise shunt the existing data down and read the remainder.
434  memmove(filebuf, filebuf + (stepSize * channels), overlapSize * channels * sizeof(float));
435  if ((count = sf_readf_float(sndfile, filebuf + (overlapSize * channels), stepSize)) < 0) {
436  cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
437  break;
438  }
439  if (count != stepSize) --finalStepsRemaining;
440  count += overlapSize;
441  }
442 
443  for (int c = 0; c < channels; ++c) {
444  int j = 0;
445  while (j < count) {
446  plugbuf[c][j] = filebuf[j * sfinfo.channels + c];
447  ++j;
448  }
449  while (j < blockSize) {
450  plugbuf[c][j] = 0.0f;
451  ++j;
452  }
453  }
454 
455  rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
456 
458  (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
459  sfinfo.samplerate, outputNo, plugin->process(plugbuf, rt),
460  out, useFrames);
461 
462  if (sfinfo.frames > 0){
463  int pp = progress;
464  progress = lrintf((float(currentStep * stepSize) / sfinfo.frames) * 100.f);
465  if (progress != pp && out) {
466  cerr << "\r" << progress << "%";
467  }
468  }
469 
470  ++currentStep;
471 
472  } while (finalStepsRemaining > 0);
473 
474  if (out) cerr << "\rDone" << endl;
475 
476  rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
477 
478  printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
479  sfinfo.samplerate, outputNo,
480  plugin->getRemainingFeatures(), out, useFrames);
481 
482  returnValue = 0;
483 
484 done:
485  delete plugin;
486  if (out) {
487  out->close();
488  delete out;
489  }
490  sf_close(sndfile);
491  return returnValue;
492 }
493 
494 void
495 printFeatures(int frame, int sr, int output,
496  Plugin::FeatureSet features, ofstream *out, bool useFrames)
497 {
498  for (unsigned int i = 0; i < features[output].size(); ++i) {
499 
500  if (useFrames) {
501 
502  int displayFrame = frame;
503 
504  if (features[output][i].hasTimestamp) {
505  displayFrame = RealTime::realTime2Frame
506  (features[output][i].timestamp, sr);
507  }
508 
509  (out ? *out : cout) << displayFrame;
510 
511  if (features[output][i].hasDuration) {
512  displayFrame = RealTime::realTime2Frame
513  (features[output][i].duration, sr);
514  (out ? *out : cout) << "," << displayFrame;
515  }
516 
517  (out ? *out : cout) << ":";
518 
519  } else {
520 
521  RealTime rt = RealTime::frame2RealTime(frame, sr);
522 
523  if (features[output][i].hasTimestamp) {
524  rt = features[output][i].timestamp;
525  }
526 
527  (out ? *out : cout) << rt.toString();
528 
529  if (features[output][i].hasDuration) {
530  rt = features[output][i].duration;
531  (out ? *out : cout) << "," << rt.toString();
532  }
533 
534  (out ? *out : cout) << ":";
535  }
536 
537  for (unsigned int j = 0; j < features[output][i].values.size(); ++j) {
538  (out ? *out : cout) << " " << features[output][i].values[j];
539  }
540  (out ? *out : cout) << " " << features[output][i].label;
541 
542  (out ? *out : cout) << endl;
543  }
544 }
545 
546 void
547 printPluginPath(bool verbose)
548 {
549  if (verbose) {
550  cout << "\nVamp plugin search path: ";
551  }
552 
553  vector<string> path = PluginHostAdapter::getPluginPath();
554  for (size_t i = 0; i < path.size(); ++i) {
555  if (verbose) {
556  cout << "[" << path[i] << "]";
557  } else {
558  cout << path[i] << endl;
559  }
560  }
561 
562  if (verbose) cout << endl;
563 }
564 
565 static
566 string
567 header(string text, int level)
568 {
569  string out = '\n' + text + '\n';
570  for (size_t i = 0; i < text.length(); ++i) {
571  out += (level == 1 ? '=' : level == 2 ? '-' : '~');
572  }
573  out += '\n';
574  return out;
575 }
576 
577 void
579 {
580  PluginLoader *loader = PluginLoader::getInstance();
581 
582  if (verbosity == PluginInformation) {
583  cout << "\nVamp plugin libraries found in search path:" << endl;
584  }
585 
586  vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
587  typedef multimap<string, PluginLoader::PluginKey>
588  LibraryMap;
589  LibraryMap libraryMap;
590 
591  for (size_t i = 0; i < plugins.size(); ++i) {
592  string path = loader->getLibraryPathForPlugin(plugins[i]);
593  libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
594  }
595 
596  string prevPath = "";
597  int index = 0;
598 
599  for (LibraryMap::iterator i = libraryMap.begin();
600  i != libraryMap.end(); ++i) {
601 
602  string path = i->first;
603  PluginLoader::PluginKey key = i->second;
604 
605  if (path != prevPath) {
606  prevPath = path;
607  index = 0;
608  if (verbosity == PluginInformation) {
609  cout << "\n " << path << ":" << endl;
610  } else if (verbosity == PluginInformationDetailed) {
611  string::size_type ki = i->second.find(':');
612  string text = "Library \"" + i->second.substr(0, ki) + "\"";
613  cout << "\n" << header(text, 1);
614  }
615  }
616 
617  Plugin *plugin = loader->loadPlugin(key, 48000);
618  if (plugin) {
619 
620  char c = char('A' + index);
621  if (c > 'Z') c = char('a' + (index - 26));
622 
623  PluginLoader::PluginCategoryHierarchy category =
624  loader->getPluginCategory(key);
625  string catstr;
626  if (!category.empty()) {
627  for (size_t ci = 0; ci < category.size(); ++ci) {
628  if (ci > 0) catstr += " > ";
629  catstr += category[ci];
630  }
631  }
632 
633  if (verbosity == PluginInformation) {
634 
635  cout << " [" << c << "] [v"
636  << plugin->getVampApiVersion() << "] "
637  << plugin->getName() << ", \""
638  << plugin->getIdentifier() << "\"" << " ["
639  << plugin->getMaker() << "]" << endl;
640 
641  if (catstr != "") {
642  cout << " > " << catstr << endl;
643  }
644 
645  if (plugin->getDescription() != "") {
646  cout << " - " << plugin->getDescription() << endl;
647  }
648 
649  } else if (verbosity == PluginInformationDetailed) {
650 
651  cout << header(plugin->getName(), 2);
652  cout << " - Identifier: "
653  << key << endl;
654  cout << " - Plugin Version: "
655  << plugin->getPluginVersion() << endl;
656  cout << " - Vamp API Version: "
657  << plugin->getVampApiVersion() << endl;
658  cout << " - Maker: \""
659  << plugin->getMaker() << "\"" << endl;
660  cout << " - Copyright: \""
661  << plugin->getCopyright() << "\"" << endl;
662  cout << " - Description: \""
663  << plugin->getDescription() << "\"" << endl;
664  cout << " - Input Domain: "
665  << (plugin->getInputDomain() == Vamp::Plugin::TimeDomain ?
666  "Time Domain" : "Frequency Domain") << endl;
667  cout << " - Default Step Size: "
668  << plugin->getPreferredStepSize() << endl;
669  cout << " - Default Block Size: "
670  << plugin->getPreferredBlockSize() << endl;
671  cout << " - Minimum Channels: "
672  << plugin->getMinChannelCount() << endl;
673  cout << " - Maximum Channels: "
674  << plugin->getMaxChannelCount() << endl;
675 
676  } else if (verbosity == PluginIds) {
677  cout << "vamp:" << key << endl;
678  }
679 
680  Plugin::OutputList outputs =
681  plugin->getOutputDescriptors();
682 
683  if (verbosity == PluginInformationDetailed) {
684 
685  Plugin::ParameterList params = plugin->getParameterDescriptors();
686  for (size_t j = 0; j < params.size(); ++j) {
687  Plugin::ParameterDescriptor &pd(params[j]);
688  cout << "\nParameter " << j+1 << ": \"" << pd.name << "\"" << endl;
689  cout << " - Identifier: " << pd.identifier << endl;
690  cout << " - Description: \"" << pd.description << "\"" << endl;
691  if (pd.unit != "") {
692  cout << " - Unit: " << pd.unit << endl;
693  }
694  cout << " - Range: ";
695  cout << pd.minValue << " -> " << pd.maxValue << endl;
696  cout << " - Default: ";
697  cout << pd.defaultValue << endl;
698  if (pd.isQuantized) {
699  cout << " - Quantize Step: "
700  << pd.quantizeStep << endl;
701  }
702  if (!pd.valueNames.empty()) {
703  cout << " - Value Names: ";
704  for (size_t k = 0; k < pd.valueNames.size(); ++k) {
705  if (k > 0) cout << ", ";
706  cout << "\"" << pd.valueNames[k] << "\"";
707  }
708  cout << endl;
709  }
710  }
711 
712  if (outputs.empty()) {
713  cout << "\n** Note: This plugin reports no outputs!" << endl;
714  }
715  for (size_t j = 0; j < outputs.size(); ++j) {
716  Plugin::OutputDescriptor &od(outputs[j]);
717  cout << "\nOutput " << j+1 << ": \"" << od.name << "\"" << endl;
718  cout << " - Identifier: " << od.identifier << endl;
719  cout << " - Description: \"" << od.description << "\"" << endl;
720  if (od.unit != "") {
721  cout << " - Unit: " << od.unit << endl;
722  }
723  if (od.hasFixedBinCount) {
724  cout << " - Default Bin Count: " << od.binCount << endl;
725  }
726  if (!od.binNames.empty()) {
727  bool have = false;
728  for (size_t k = 0; k < od.binNames.size(); ++k) {
729  if (od.binNames[k] != "") {
730  have = true; break;
731  }
732  }
733  if (have) {
734  cout << " - Bin Names: ";
735  for (size_t k = 0; k < od.binNames.size(); ++k) {
736  if (k > 0) cout << ", ";
737  cout << "\"" << od.binNames[k] << "\"";
738  }
739  cout << endl;
740  }
741  }
742  if (od.hasKnownExtents) {
743  cout << " - Default Extents: ";
744  cout << od.minValue << " -> " << od.maxValue << endl;
745  }
746  if (od.isQuantized) {
747  cout << " - Quantize Step: "
748  << od.quantizeStep << endl;
749  }
750  cout << " - Sample Type: "
751  << (od.sampleType ==
752  Plugin::OutputDescriptor::OneSamplePerStep ?
753  "One Sample Per Step" :
754  od.sampleType ==
755  Plugin::OutputDescriptor::FixedSampleRate ?
756  "Fixed Sample Rate" :
757  "Variable Sample Rate") << endl;
758  if (od.sampleType !=
759  Plugin::OutputDescriptor::OneSamplePerStep) {
760  cout << " - Default Rate: "
761  << od.sampleRate << endl;
762  }
763  cout << " - Has Duration: "
764  << (od.hasDuration ? "Yes" : "No") << endl;
765  }
766  }
767 
768  if (outputs.size() > 1 || verbosity == PluginOutputIds) {
769  for (size_t j = 0; j < outputs.size(); ++j) {
770  if (verbosity == PluginInformation) {
771  cout << " (" << j << ") "
772  << outputs[j].name << ", \""
773  << outputs[j].identifier << "\"" << endl;
774  if (outputs[j].description != "") {
775  cout << " - "
776  << outputs[j].description << endl;
777  }
778  } else if (verbosity == PluginOutputIds) {
779  cout << "vamp:" << key << ":" << outputs[j].identifier << endl;
780  }
781  }
782  }
783 
784  ++index;
785 
786  delete plugin;
787  }
788  }
789 
790  if (verbosity == PluginInformation ||
791  verbosity == PluginInformationDetailed) {
792  cout << endl;
793  }
794 }
795 
796 void
798 {
799  PluginLoader *loader = PluginLoader::getInstance();
800 
801  vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
802 
803  set<string> printedcats;
804 
805  for (size_t i = 0; i < plugins.size(); ++i) {
806 
807  PluginLoader::PluginKey key = plugins[i];
808 
809  PluginLoader::PluginCategoryHierarchy category =
810  loader->getPluginCategory(key);
811 
812  Plugin *plugin = loader->loadPlugin(key, 48000);
813  if (!plugin) continue;
814 
815  string catstr = "";
816 
817  if (category.empty()) catstr = '|';
818  else {
819  for (size_t j = 0; j < category.size(); ++j) {
820  catstr += category[j];
821  catstr += '|';
822  if (printedcats.find(catstr) == printedcats.end()) {
823  std::cout << catstr << std::endl;
824  printedcats.insert(catstr);
825  }
826  }
827  }
828 
829  std::cout << catstr << key << ":::" << plugin->getName() << ":::" << plugin->getMaker() << ":::" << plugin->getDescription() << std::endl;
830  }
831 }
832 
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:72
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)