VampPluginSDK 2.10
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
65using namespace std;
66
67using Vamp::Plugin;
69using Vamp::RealTime;
73
74#define HOST_VERSION "1.5"
75
81};
82
83void printFeatures(int, int,
84 const Plugin::OutputDescriptor &, int,
85 const Plugin::FeatureSet &, ofstream *, bool frames);
86void transformInput(float *, size_t);
87void fft(unsigned int, bool, double *, double *, double *, double *);
88void printPluginPath(bool verbose);
91void listPluginsInLibrary(string soname);
92int runPlugin(string myname, string soname, string id, string output,
93 int outputNo, string inputFile, string outfilename, bool frames);
94
95void usage(const char *name)
96{
97 cerr << "\n"
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"
102 "Usage:\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"
136 << endl;
137 exit(2);
138}
139
140int main(int argc, char **argv)
141{
142 char *scooter = argv[0];
143 char *name = 0;
144 while (scooter && *scooter) {
145 if (*scooter == '/' || *scooter == '\\') name = ++scooter;
146 else ++scooter;
147 }
148 if (!name || !*name) name = argv[0];
149
150 if (argc < 2) usage(name);
151
152 if (argc == 2) {
153
154 if (!strcmp(argv[1], "-v")) {
155
156 cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl
157 << "Vamp API version: " << VAMP_API_VERSION << endl
158 << "Vamp SDK version: " << VAMP_SDK_VERSION << endl;
159 return 0;
160
161 } else if (!strcmp(argv[1], "-l") || !strcmp(argv[1], "--list")) {
162
163 printPluginPath(true);
165 return 0;
166
167 } else if (!strcmp(argv[1], "-L") || !strcmp(argv[1], "--list-full")) {
168
170 return 0;
171
172 } else if (!strcmp(argv[1], "-p")) {
173
174 printPluginPath(false);
175 return 0;
176
177 } else if (!strcmp(argv[1], "--list-ids")) {
178
180 return 0;
181
182 } else if (!strcmp(argv[1], "--list-outputs")) {
183
185 return 0;
186
187 } else if (!strcmp(argv[1], "--list-by-category")) {
188
190 return 0;
191
192 } else usage(name);
193 }
194
195 if (argc < 3) usage(name);
196
197 bool useFrames = false;
198
199 int base = 1;
200 if (!strcmp(argv[1], "-s")) {
201 useFrames = true;
202 base = 2;
203 }
204
205 string soname = argv[base];
206 string wavname = argv[base+1];
207 string plugid = "";
208 string output = "";
209 int outputNo = -1;
210 string outfilename;
211
212 if (argc >= base+3) {
213
214 int idx = base+2;
215
216 if (isdigit(*argv[idx])) {
217 outputNo = atoi(argv[idx++]);
218 }
219
220 if (argc == idx + 2) {
221 if (!strcmp(argv[idx], "-o")) {
222 outfilename = argv[idx+1];
223 } else usage(name);
224 } else if (argc != idx) {
225 (usage(name));
226 }
227 }
228
229 cerr << endl << name << ": Running..." << endl;
230
231 cerr << "Reading file: \"" << wavname << "\", writing to ";
232 if (outfilename == "") {
233 cerr << "standard output" << endl;
234 } else {
235 cerr << "\"" << outfilename << "\"" << endl;
236 }
237
238 string::size_type sep = soname.find(':');
239
240 if (sep != string::npos) {
241 plugid = soname.substr(sep + 1);
242 soname = soname.substr(0, sep);
243
244 sep = plugid.find(':');
245 if (sep != string::npos) {
246 output = plugid.substr(sep + 1);
247 plugid = plugid.substr(0, sep);
248 }
249 }
250
251 if (plugid == "") {
252 usage(name);
253 }
254
255 if (output != "" && outputNo != -1) {
256 usage(name);
257 }
258
259 if (output == "" && outputNo == -1) {
260 outputNo = 0;
261 }
262
263 return runPlugin(name, soname, plugid, output, outputNo,
264 wavname, outfilename, useFrames);
265}
266
267
268int runPlugin(string myname, string soname, string id,
269 string output, int outputNo, string wavname,
270 string outfilename, bool useFrames)
271{
273
274 PluginLoader::PluginKey key = loader->composePluginKey(soname, id);
275
276 SNDFILE *sndfile;
277 SF_INFO sfinfo;
278 memset(&sfinfo, 0, sizeof(SF_INFO));
279
280 sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo);
281 if (!sndfile) {
282 cerr << myname << ": ERROR: Failed to open input file \""
283 << wavname << "\": " << sf_strerror(sndfile) << endl;
284 return 1;
285 }
286
287 ofstream *out = 0;
288 if (outfilename != "") {
289 out = new ofstream(outfilename.c_str(), ios::out);
290 if (!*out) {
291 cerr << myname << ": ERROR: Failed to open output file \""
292 << outfilename << "\" for writing" << endl;
293 delete out;
294 return 1;
295 }
296 }
297
298 Plugin *plugin = loader->loadPlugin
299 (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL_SAFE);
300 if (!plugin) {
301 cerr << myname << ": ERROR: Failed to load plugin \"" << id
302 << "\" from library \"" << soname << "\"" << endl;
303 sf_close(sndfile);
304 if (out) {
305 out->close();
306 delete out;
307 }
308 return 1;
309 }
310
311 cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl;
312
313 // Note that the following would be much simpler if we used a
314 // PluginBufferingAdapter as well -- i.e. if we had passed
315 // PluginLoader::ADAPT_ALL to loader->loadPlugin() above, instead
316 // of ADAPT_ALL_SAFE. Then we could simply specify our own block
317 // size, keep the step size equal to the block size, and ignore
318 // the plugin's bleatings. However, there are some issues with
319 // using a PluginBufferingAdapter that make the results sometimes
320 // technically different from (if effectively the same as) the
321 // un-adapted plugin, so we aren't doing that here. See the
322 // PluginBufferingAdapter documentation for details.
323
324 int blockSize = plugin->getPreferredBlockSize();
325 int stepSize = plugin->getPreferredStepSize();
326
327 if (blockSize == 0) {
328 blockSize = 1024;
329 }
330 if (stepSize == 0) {
331 if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
332 stepSize = blockSize/2;
333 } else {
334 stepSize = blockSize;
335 }
336 } else if (stepSize > blockSize) {
337 cerr << "WARNING: stepSize " << stepSize << " > blockSize " << blockSize << ", resetting blockSize to ";
338 if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
339 blockSize = stepSize * 2;
340 } else {
341 blockSize = stepSize;
342 }
343 cerr << blockSize << endl;
344 }
345 int overlapSize = blockSize - stepSize;
346 sf_count_t currentStep = 0;
347 int finalStepsRemaining = max(1, (blockSize / stepSize) - 1); // at end of file, this many part-silent frames needed after we hit EOF
348
349 int channels = sfinfo.channels;
350
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];
354
355 cerr << "Using block size = " << blockSize << ", step size = "
356 << stepSize << endl;
357
358 // The channel queries here are for informational purposes only --
359 // a PluginChannelAdapter is being used automatically behind the
360 // scenes, and it will take case of any channel mismatch
361
362 int minch = plugin->getMinChannelCount();
363 int maxch = plugin->getMaxChannelCount();
364 cerr << "Plugin accepts " << minch << " -> " << maxch << " channel(s)" << endl;
365 cerr << "Sound file has " << channels << " (will mix/augment if necessary)" << endl;
366
367 Plugin::OutputList outputs = plugin->getOutputDescriptors();
368 Plugin::OutputDescriptor od;
369 Plugin::FeatureSet features;
370
371 int returnValue = 1;
372 int progress = 0;
373
374 RealTime rt;
375 PluginWrapper *wrapper = 0;
376 RealTime adjustment = RealTime::zeroTime;
377
378 if (outputs.empty()) {
379 cerr << "ERROR: Plugin has no outputs!" << endl;
380 goto done;
381 }
382
383 if (outputNo < 0) {
384
385 for (size_t oi = 0; oi < outputs.size(); ++oi) {
386 if (outputs[oi].identifier == output) {
387 outputNo = oi;
388 break;
389 }
390 }
391
392 if (outputNo < 0) {
393 cerr << "ERROR: Non-existent output \"" << output << "\" requested" << endl;
394 goto done;
395 }
396
397 } else {
398
399 if (int(outputs.size()) <= outputNo) {
400 cerr << "ERROR: Output " << outputNo << " requested, but plugin has only " << outputs.size() << " output(s)" << endl;
401 goto done;
402 }
403 }
404
405 od = outputs[outputNo];
406 cerr << "Output is: \"" << od.identifier << "\"" << endl;
407
408 if (!plugin->initialise(channels, stepSize, blockSize)) {
409 cerr << "ERROR: Plugin initialise (channels = " << channels
410 << ", stepSize = " << stepSize << ", blockSize = "
411 << blockSize << ") failed." << endl;
412 goto done;
413 }
414
415 wrapper = dynamic_cast<PluginWrapper *>(plugin);
416 if (wrapper) {
417 // See documentation for
418 // PluginInputDomainAdapter::getTimestampAdjustment
421 if (ida) adjustment = ida->getTimestampAdjustment();
422 }
423
424 // Here we iterate over the frames, avoiding asking the numframes in case it's streaming input.
425 do {
426
427 int count;
428
429 if ((blockSize==stepSize) || (currentStep==0)) {
430 // read a full fresh block
431 if ((count = sf_readf_float(sndfile, filebuf, blockSize)) < 0) {
432 cerr << "ERROR: sf_readf_float failed: " << sf_strerror(sndfile) << endl;
433 break;
434 }
435 if (count != blockSize) --finalStepsRemaining;
436 } else {
437 // otherwise shunt the existing data down and read the remainder.
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;
441 break;
442 }
443 if (count != stepSize) --finalStepsRemaining;
444 count += overlapSize;
445 }
446
447 for (int c = 0; c < channels; ++c) {
448 int j = 0;
449 while (j < count) {
450 plugbuf[c][j] = filebuf[j * sfinfo.channels + c];
451 ++j;
452 }
453 while (j < blockSize) {
454 plugbuf[c][j] = 0.0f;
455 ++j;
456 }
457 }
458
459 rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
460
461 features = plugin->process(plugbuf, rt);
462
464 (RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
465 sfinfo.samplerate, od, outputNo, features, out, useFrames);
466
467 if (sfinfo.frames > 0){
468 int pp = progress;
469 progress = (int)((float(currentStep * stepSize) / sfinfo.frames) * 100.f + 0.5f);
470 if (progress != pp && out) {
471 cerr << "\r" << progress << "%";
472 }
473 }
474
475 ++currentStep;
476
477 } while (finalStepsRemaining > 0);
478
479 if (out) cerr << "\rDone" << endl;
480
481 rt = RealTime::frame2RealTime(currentStep * stepSize, sfinfo.samplerate);
482
483 features = plugin->getRemainingFeatures();
484
485 printFeatures(RealTime::realTime2Frame(rt + adjustment, sfinfo.samplerate),
486 sfinfo.samplerate, od, outputNo, features, out, useFrames);
487
488 returnValue = 0;
489
490done:
491 delete plugin;
492 if (out) {
493 out->close();
494 delete out;
495 }
496 sf_close(sndfile);
497 return returnValue;
498}
499
500static double
501toSeconds(const RealTime &time)
502{
503 return time.sec + double(time.nsec + 1) / 1000000000.0;
504}
505
506void
507printFeatures(int frame, int sr,
508 const Plugin::OutputDescriptor &output, int outputNo,
509 const Plugin::FeatureSet &features, ofstream *out, bool useFrames)
510{
511 static int featureCount = -1;
512
513 if (features.find(outputNo) == features.end()) return;
514
515 for (size_t i = 0; i < features.at(outputNo).size(); ++i) {
516
517 const Plugin::Feature &f = features.at(outputNo).at(i);
518
519 bool haveRt = false;
520 RealTime rt;
521
522 if (output.sampleType == Plugin::OutputDescriptor::VariableSampleRate) {
523 rt = f.timestamp;
524 haveRt = true;
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));
529 }
530 rt = RealTime::fromSeconds(double(n) / output.sampleRate);
531 haveRt = true;
532 featureCount = n;
533 }
534
535 if (useFrames) {
536
537 int displayFrame = frame;
538
539 if (haveRt) {
540 displayFrame = RealTime::realTime2Frame(rt, sr);
541 }
542
543 (out ? *out : cout) << displayFrame;
544
545 if (f.hasDuration) {
546 displayFrame = RealTime::realTime2Frame(f.duration, sr);
547 (out ? *out : cout) << "," << displayFrame;
548 }
549
550 (out ? *out : cout) << ":";
551
552 } else {
553
554 if (!haveRt) {
555 rt = RealTime::frame2RealTime(frame, sr);
556 }
557
558 (out ? *out : cout) << rt.toString();
559
560 if (f.hasDuration) {
561 rt = f.duration;
562 (out ? *out : cout) << "," << rt.toString();
563 }
564
565 (out ? *out : cout) << ":";
566 }
567
568 for (unsigned int j = 0; j < f.values.size(); ++j) {
569 (out ? *out : cout) << " " << f.values[j];
570 }
571 (out ? *out : cout) << " " << f.label;
572
573 (out ? *out : cout) << endl;
574 }
575}
576
577void
578printPluginPath(bool verbose)
579{
580 if (verbose) {
581 cout << "\nVamp plugin search path: ";
582 }
583
584 vector<string> path = PluginHostAdapter::getPluginPath();
585 for (size_t i = 0; i < path.size(); ++i) {
586 if (verbose) {
587 cout << "[" << path[i] << "]";
588 } else {
589 cout << path[i] << endl;
590 }
591 }
592
593 if (verbose) cout << endl;
594}
595
596static
597string
598header(string text, int level)
599{
600 string out = '\n' + text + '\n';
601 for (size_t i = 0; i < text.length(); ++i) {
602 out += (level == 1 ? '=' : level == 2 ? '-' : '~');
603 }
604 out += '\n';
605 return out;
606}
607
608void
610{
612
613 if (verbosity == PluginInformation) {
614 cout << "\nVamp plugin libraries found in search path:" << endl;
615 }
616
617 vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
618 typedef multimap<string, PluginLoader::PluginKey>
619 LibraryMap;
620 LibraryMap libraryMap;
621
622 for (size_t i = 0; i < plugins.size(); ++i) {
623 string path = loader->getLibraryPathForPlugin(plugins[i]);
624 libraryMap.insert(LibraryMap::value_type(path, plugins[i]));
625 }
626
627 string prevPath = "";
628 int index = 0;
629
630 for (LibraryMap::iterator i = libraryMap.begin();
631 i != libraryMap.end(); ++i) {
632
633 string path = i->first;
634 PluginLoader::PluginKey key = i->second;
635
636 if (path != prevPath) {
637 prevPath = path;
638 index = 0;
639 if (verbosity == PluginInformation) {
640 cout << "\n " << path << ":" << endl;
641 } else if (verbosity == PluginInformationDetailed) {
642 string::size_type ki = i->second.find(':');
643 string text = "Library \"" + i->second.substr(0, ki) + "\"";
644 cout << "\n" << header(text, 1);
645 }
646 }
647
648 Plugin *plugin = loader->loadPlugin(key, 48000);
649 if (plugin) {
650
651 char c = char('A' + index);
652 if (c > 'Z') c = char('a' + (index - 26));
653
655 loader->getPluginCategory(key);
656 string catstr;
657 if (!category.empty()) {
658 for (size_t ci = 0; ci < category.size(); ++ci) {
659 if (ci > 0) catstr += " > ";
660 catstr += category[ci];
661 }
662 }
663
664 if (verbosity == PluginInformation) {
665
666 cout << " [" << c << "] [v"
667 << plugin->getVampApiVersion() << "] "
668 << plugin->getName() << ", \""
669 << plugin->getIdentifier() << "\"" << " ["
670 << plugin->getMaker() << "]" << endl;
671
672 if (catstr != "") {
673 cout << " > " << catstr << endl;
674 }
675
676 if (plugin->getDescription() != "") {
677 cout << " - " << plugin->getDescription() << endl;
678 }
679
680 } else if (verbosity == PluginInformationDetailed) {
681
682 cout << header(plugin->getName(), 2);
683 cout << " - Identifier: "
684 << key << endl;
685 cout << " - Plugin Version: "
686 << plugin->getPluginVersion() << endl;
687 cout << " - Vamp API Version: "
688 << plugin->getVampApiVersion() << endl;
689 cout << " - Maker: \""
690 << plugin->getMaker() << "\"" << endl;
691 cout << " - Copyright: \""
692 << plugin->getCopyright() << "\"" << endl;
693 cout << " - Description: \""
694 << plugin->getDescription() << "\"" << endl;
695 cout << " - Input Domain: "
697 "Time Domain" : "Frequency Domain") << endl;
698 cout << " - Default Step Size: "
699 << plugin->getPreferredStepSize() << endl;
700 cout << " - Default Block Size: "
701 << plugin->getPreferredBlockSize() << endl;
702 cout << " - Minimum Channels: "
703 << plugin->getMinChannelCount() << endl;
704 cout << " - Maximum Channels: "
705 << plugin->getMaxChannelCount() << endl;
706
707 } else if (verbosity == PluginIds) {
708 cout << "vamp:" << key << endl;
709 }
710
711 Plugin::OutputList outputs =
712 plugin->getOutputDescriptors();
713
714 if (verbosity == PluginInformationDetailed) {
715
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;
722 if (pd.unit != "") {
723 cout << " - Unit: " << pd.unit << endl;
724 }
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;
732 }
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] << "\"";
738 }
739 cout << endl;
740 }
741 }
742
743 if (outputs.empty()) {
744 cout << "\n** Note: This plugin reports no outputs!" << endl;
745 }
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;
751 if (od.unit != "") {
752 cout << " - Unit: " << od.unit << endl;
753 }
754 if (od.hasFixedBinCount) {
755 cout << " - Default Bin Count: " << od.binCount << endl;
756 }
757 if (!od.binNames.empty()) {
758 bool have = false;
759 for (size_t k = 0; k < od.binNames.size(); ++k) {
760 if (od.binNames[k] != "") {
761 have = true; break;
762 }
763 }
764 if (have) {
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] << "\"";
769 }
770 cout << endl;
771 }
772 }
773 if (od.hasKnownExtents) {
774 cout << " - Default Extents: ";
775 cout << od.minValue << " -> " << od.maxValue << endl;
776 }
777 if (od.isQuantized) {
778 cout << " - Quantize Step: "
779 << od.quantizeStep << endl;
780 }
781 cout << " - Sample Type: "
782 << (od.sampleType ==
784 "One Sample Per Step" :
785 od.sampleType ==
787 "Fixed Sample Rate" :
788 "Variable Sample Rate") << endl;
789 if (od.sampleType !=
791 cout << " - Default Rate: "
792 << od.sampleRate << endl;
793 }
794 cout << " - Has Duration: "
795 << (od.hasDuration ? "Yes" : "No") << endl;
796 }
797 }
798
799 if (outputs.size() > 1 || verbosity == PluginOutputIds) {
800 for (size_t j = 0; j < outputs.size(); ++j) {
801 if (verbosity == PluginInformation) {
802 cout << " (" << j << ") "
803 << outputs[j].name << ", \""
804 << outputs[j].identifier << "\"" << endl;
805 if (outputs[j].description != "") {
806 cout << " - "
807 << outputs[j].description << endl;
808 }
809 } else if (verbosity == PluginOutputIds) {
810 cout << "vamp:" << key << ":" << outputs[j].identifier << endl;
811 }
812 }
813 }
814
815 ++index;
816
817 delete plugin;
818 }
819 }
820
821 if (verbosity == PluginInformation ||
822 verbosity == PluginInformationDetailed) {
823 cout << endl;
824 }
825}
826
827void
829{
831
832 vector<PluginLoader::PluginKey> plugins = loader->listPlugins();
833
834 set<string> printedcats;
835
836 for (size_t i = 0; i < plugins.size(); ++i) {
837
838 PluginLoader::PluginKey key = plugins[i];
839
841 loader->getPluginCategory(key);
842
843 Plugin *plugin = loader->loadPlugin(key, 48000);
844 if (!plugin) continue;
845
846 string catstr = "";
847
848 if (category.empty()) catstr = '|';
849 else {
850 for (size_t j = 0; j < category.size(); ++j) {
851 catstr += category[j];
852 catstr += '|';
853 if (printedcats.find(catstr) == printedcats.end()) {
854 std::cout << catstr << std::endl;
855 printedcats.insert(catstr);
856 }
857 }
858 }
859
860 std::cout << catstr << key << ":::" << plugin->getName() << ":::" << plugin->getMaker() << ":::" << plugin->getDescription() << std::endl;
861 }
862}
863
PluginInputDomainAdapter is a Vamp plugin adapter that converts time-domain input into frequency-doma...
RealTime getTimestampAdjustment() const
Return the amount by which the timestamps supplied to process() are being incremented when they are p...
Vamp::HostExt::PluginLoader is a convenience class for discovering and loading Vamp plugins using the...
Definition: PluginLoader.h:76
Plugin * loadPlugin(PluginKey key, float inputSampleRate, int adapterFlags=0)
Load a Vamp plugin, given its identifying key.
std::string PluginKey
PluginKey is a string type that is used to identify a plugin uniquely within the scope of "the curren...
Definition: PluginLoader.h:104
std::string getLibraryPathForPlugin(PluginKey plugin)
Return the file path of the dynamic library from which the given plugin will be loaded (if available)...
static PluginLoader * getInstance()
Obtain a pointer to the singleton instance of PluginLoader.
PluginCategoryHierarchy getPluginCategory(PluginKey plugin)
Return the category hierarchy for a Vamp plugin, given its identifying key.
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...
std::vector< std::string > PluginCategoryHierarchy
PluginCategoryHierarchy is a sequence of general->specific category names, as may be associated with ...
Definition: PluginLoader.h:122
PluginKeyList listPlugins()
Search for all available Vamp plugins, and return a list of them in the order in which they were foun...
PluginWrapper is a simple base class for adapter plugins.
Definition: PluginWrapper.h:66
WrapperType * getWrapper()
Return a pointer to the plugin wrapper of type WrapperType surrounding this wrapper's plugin,...
virtual ParameterList getParameterDescriptors() const
Get the controllable parameters of this plugin.
virtual std::string getName() const =0
Get a human-readable name or title of the plugin.
std::vector< ParameterDescriptor > ParameterList
virtual std::string getMaker() const =0
Get the name of the author or vendor of the plugin in human-readable form.
virtual std::string getDescription() const =0
Get a human-readable description for the plugin, typically a line of text that may optionally be disp...
virtual int getPluginVersion() const =0
Get the version number of the plugin.
virtual unsigned int getVampApiVersion() const
Get the Vamp API compatibility level of the plugin.
virtual std::string getCopyright() const =0
Get the copyright statement or licensing summary for the plugin.
virtual std::string getIdentifier() const =0
Get the computer-usable name of the plugin.
PluginHostAdapter is a wrapper class that a Vamp host can use to make the C-language VampPluginDescri...
static std::vector< std::string > getPluginPath()
Vamp::Plugin is a base class for plugin instance classes that provide feature extraction from audio o...
virtual size_t getMaxChannelCount() const
Get the maximum supported number of input channels.
std::vector< OutputDescriptor > OutputList
virtual size_t getPreferredStepSize() const
Get the preferred step size (window increment – the distance in sample frames between the start frame...
std::map< int, FeatureList > FeatureSet
virtual size_t getMinChannelCount() const
Get the minimum supported number of input channels.
virtual OutputList getOutputDescriptors() const =0
Get the outputs of this plugin.
virtual InputDomain getInputDomain() const =0
Get the plugin's required input domain.
virtual size_t getPreferredBlockSize() const
Get the preferred block size (window size – the number of sample frames passed in each block to the p...
virtual FeatureSet process(const float *const *inputBuffers, RealTime timestamp)=0
Process a single block of input data.
virtual FeatureSet getRemainingFeatures()=0
After all blocks have been processed, calculate and return any remaining features derived from the co...
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,...
#define VAMP_SDK_VERSION
Definition: plugguard.h:74
@ OneSamplePerStep
Results from each process() align with that call's block start.
@ FixedSampleRate
Results are evenly spaced in time (sampleRate specified below)
@ VariableSampleRate
Results are unevenly spaced and have individual timestamps.
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
std::string toString() const
Return a human-readable debug-type string to full precision (probably not a format to show to a user ...
static RealTime frame2RealTime(long frame, unsigned int sampleRate)
Convert a sample frame at the given sample rate into a RealTime.
static const RealTime zeroTime
static long realTime2Frame(const RealTime &r, unsigned int sampleRate)
Convert a RealTime into a sample frame at the given sample rate.
static RealTime fromSeconds(double sec)
#define PLUGIN_SUFFIX
Definition: system.h:67
int main(int argc, char **argv)
void printPluginPath(bool verbose)
void listPluginsInLibrary(string soname)
int runPlugin(string myname, string soname, string id, string output, int outputNo, string inputFile, string outfilename, bool frames)
static string header(string text, int level)
void usage(const char *name)
void enumeratePlugins(Verbosity)
#define HOST_VERSION
void fft(unsigned int, bool, double *, double *, double *, double *)
@ PluginInformationDetailed
@ PluginOutputIds
@ PluginIds
@ PluginInformation
void printFeatures(int, int, const Plugin::OutputDescriptor &, int, const Plugin::FeatureSet &, ofstream *, bool frames)
static double toSeconds(const RealTime &time)
void transformInput(float *, size_t)
void printPluginCategoryList()
#define VAMP_API_VERSION
Plugin API version.
Definition: vamp.h:53