comparison host/vamp-simple-host.cpp @ 88:d17b9ca3b8c9

* add -o <file> option to vamp-simple-host
author cannam
date Fri, 12 Oct 2007 09:52:10 +0000
parents af0d86b8b692
children 200a663bace1
comparison
equal deleted inserted replaced
87:bd5d5ba29d3c 88:d17b9ca3b8c9
40 #include "vamp-sdk/hostext/PluginInputDomainAdapter.h" 40 #include "vamp-sdk/hostext/PluginInputDomainAdapter.h"
41 #include "vamp-sdk/hostext/PluginLoader.h" 41 #include "vamp-sdk/hostext/PluginLoader.h"
42 #include "vamp/vamp.h" 42 #include "vamp/vamp.h"
43 43
44 #include <iostream> 44 #include <iostream>
45 #include <fstream>
45 #include <sndfile.h> 46 #include <sndfile.h>
46 47
47 #include "system.h" 48 #include "system.h"
48 49
49 #include <cmath> 50 #include <cmath>
51 using std::cout; 52 using std::cout;
52 using std::cerr; 53 using std::cerr;
53 using std::endl; 54 using std::endl;
54 using std::string; 55 using std::string;
55 using std::vector; 56 using std::vector;
57 using std::ofstream;
58 using std::ios;
56 59
57 using Vamp::HostExt::PluginLoader; 60 using Vamp::HostExt::PluginLoader;
58 61
59 #define HOST_VERSION "1.1" 62 #define HOST_VERSION "1.1"
60 63
61 void printFeatures(int, int, int, Vamp::Plugin::FeatureSet); 64 void printFeatures(int, int, int, Vamp::Plugin::FeatureSet, ofstream *);
62 void transformInput(float *, size_t); 65 void transformInput(float *, size_t);
63 void fft(unsigned int, bool, double *, double *, double *, double *); 66 void fft(unsigned int, bool, double *, double *, double *, double *);
64 void printPluginPath(bool verbose); 67 void printPluginPath(bool verbose);
65 void enumeratePlugins(); 68 void enumeratePlugins();
66 void listPluginsInLibrary(string soname); 69 void listPluginsInLibrary(string soname);
67 int runPlugin(string myname, string soname, string id, string output, 70 int runPlugin(string myname, string soname, string id, string output,
68 int outputNo, string inputFile); 71 int outputNo, string inputFile, string outfilename);
69 72
70 void usage(const char *name) 73 void usage(const char *name)
71 { 74 {
72 cerr << "\n" 75 cerr << "\n"
73 << name << ": A simple Vamp plugin host.\n\n" 76 << name << ": A simple Vamp plugin host.\n\n"
74 "Centre for Digital Music, Queen Mary, University of London.\n" 77 "Centre for Digital Music, Queen Mary, University of London.\n"
75 "Copyright 2006-2007 Chris Cannam and QMUL.\n" 78 "Copyright 2006-2007 Chris Cannam and QMUL.\n"
76 "Freely redistributable; published under a BSD-style license.\n\n" 79 "Freely redistributable; published under a BSD-style license.\n\n"
77 "Usage:\n\n" 80 "Usage:\n\n"
78 " " << name << " pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin[:output] file.wav\n" 81 " " << name << " pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin[:output] file.wav [-o outfile.txt]\n"
79 " " << name << " pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin file.wav [outputno]\n\n" 82 " " << name << " pluginlibrary[." << PLUGIN_SUFFIX << "]:plugin file.wav [outputno] [-o outfile.txt]\n\n"
80 " -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n" 83 " -- Load plugin id \"plugin\" from \"pluginlibrary\" and run it on the\n"
81 " audio data in \"file.wav\", retrieving the named \"output\", or output\n" 84 " audio data in \"file.wav\", retrieving the named \"output\", or output\n"
82 " number \"outputno\" (the first output by default) and dumping it to\n" 85 " number \"outputno\" (the first output by default) and dumping it to\n"
83 " standard output.\n\n" 86 " standard output, or to \"outfile.txt\" if the -o option is given.\n\n"
84 " \"pluginlibrary\" should be a library name, not a file path; the\n" 87 " \"pluginlibrary\" should be a library name, not a file path; the\n"
85 " standard Vamp library search path will be used to locate it. If\n" 88 " standard Vamp library search path will be used to locate it. If\n"
86 " a file path is supplied, the directory part(s) will be ignored.\n\n" 89 " a file path is supplied, the directory part(s) will be ignored.\n\n"
87 " " << name << " -l\n\n" 90 " " << name << " -l\n\n"
88 " -- List the plugin libraries and Vamp plugins in the library search path.\n\n" 91 " -- List the plugin libraries and Vamp plugins in the library search path.\n\n"
102 if (*scooter == '/' || *scooter == '\\') name = ++scooter; 105 if (*scooter == '/' || *scooter == '\\') name = ++scooter;
103 else ++scooter; 106 else ++scooter;
104 } 107 }
105 if (!name || !*name) name = argv[0]; 108 if (!name || !*name) name = argv[0];
106 109
107 if (argc < 2 || argc > 4 || 110 if (argc < 2) usage(name);
108 (argc == 2 && 111
109 (!strcmp(argv[1], "-?") || 112 if (argc == 2) {
110 !strcmp(argv[1], "-h") || 113
111 !strcmp(argv[1], "--help")))) { 114 if (!strcmp(argv[1], "-v")) {
112 115
113 usage(name); // does not return 116 cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl
114 } 117 << "Vamp API version: " << VAMP_API_VERSION << endl
115 118 << "Vamp SDK version: " << VAMP_SDK_VERSION << endl;
116 if (argc == 2 && !strcmp(argv[1], "-v")) { 119 return 0;
117 cout << "Simple Vamp plugin host version: " << HOST_VERSION << endl 120
118 << "Vamp API version: " << VAMP_API_VERSION << endl 121 } else if (!strcmp(argv[1], "-l")) {
119 << "Vamp SDK version: " << VAMP_SDK_VERSION << endl; 122
120 return 0; 123 printPluginPath(true);
121 } 124 enumeratePlugins();
122 125 return 0;
123 if (argc == 2 && !strcmp(argv[1], "-l")) { 126
124 printPluginPath(true); 127 } else if (!strcmp(argv[1], "-p")) {
125 enumeratePlugins(); 128
126 return 0; 129 printPluginPath(false);
127 } 130 return 0;
128 if (argc == 2 && !strcmp(argv[1], "-p")) { 131
129 printPluginPath(false); 132 } else usage(name);
130 return 0; 133 }
131 } 134
132 135 if (argc < 3) usage(name);
133 cerr << endl << name << ": Running..." << endl;
134 136
135 string soname = argv[1]; 137 string soname = argv[1];
138 string wavname = argv[2];
136 string plugid = ""; 139 string plugid = "";
137 string output = ""; 140 string output = "";
138 int outputNo = -1; 141 int outputNo = -1;
139 string wavname; 142 string outfilename;
140 if (argc >= 3) wavname = argv[2]; 143
144 if (argc >= 4) {
145
146 int idx = 3;
147
148 if (isdigit(*argv[idx])) {
149 outputNo = atoi(argv[idx++]);
150 }
151
152 if (argc == idx + 2) {
153 if (!strcmp(argv[idx], "-o")) {
154 outfilename = argv[idx+1];
155 } else usage(name);
156 } else if (argc != idx) {
157 (usage(name));
158 }
159 }
160
161 cerr << endl << name << ": Running..." << endl;
162
163 cerr << "Reading file: \"" << wavname << "\", writing to ";
164 if (outfilename == "") {
165 cerr << "standard output" << endl;
166 } else {
167 cerr << "\"" << outfilename << "\"" << endl;
168 }
141 169
142 string::size_type sep = soname.find(':'); 170 string::size_type sep = soname.find(':');
143 171
144 if (sep != string::npos) { 172 if (sep != string::npos) {
145 plugid = soname.substr(sep + 1); 173 plugid = soname.substr(sep + 1);
154 182
155 if (plugid == "") { 183 if (plugid == "") {
156 usage(name); 184 usage(name);
157 } 185 }
158 186
159 if (argc == 4) outputNo = atoi(argv[3]);
160
161 if (output != "" && outputNo != -1) { 187 if (output != "" && outputNo != -1) {
162 usage(name); 188 usage(name);
163 } 189 }
164 190
165 if (output == "" && outputNo == -1) { 191 if (output == "" && outputNo == -1) {
166 outputNo = 0; 192 outputNo = 0;
167 } 193 }
168 194
169 return runPlugin(name, soname, plugid, output, outputNo, wavname); 195 return runPlugin(name, soname, plugid, output, outputNo,
196 wavname, outfilename);
170 } 197 }
171 198
172 199
173 int runPlugin(string myname, string soname, string id, 200 int runPlugin(string myname, string soname, string id,
174 string output, int outputNo, string wavname) 201 string output, int outputNo, string wavname,
202 string outfilename)
175 { 203 {
176 PluginLoader *loader = PluginLoader::getInstance(); 204 PluginLoader *loader = PluginLoader::getInstance();
177 205
178 PluginLoader::PluginKey key = loader->composePluginKey(soname, id); 206 PluginLoader::PluginKey key = loader->composePluginKey(soname, id);
179 207
184 sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo); 212 sndfile = sf_open(wavname.c_str(), SFM_READ, &sfinfo);
185 if (!sndfile) { 213 if (!sndfile) {
186 cerr << myname << ": ERROR: Failed to open input file \"" 214 cerr << myname << ": ERROR: Failed to open input file \""
187 << wavname << "\": " << sf_strerror(sndfile) << endl; 215 << wavname << "\": " << sf_strerror(sndfile) << endl;
188 return 1; 216 return 1;
217 }
218
219 ofstream *out = 0;
220 if (outfilename != "") {
221 out = new ofstream(outfilename.c_str(), ios::out);
222 if (!*out) {
223 cerr << myname << ": ERROR: Failed to open output file \""
224 << outfilename << "\" for writing" << endl;
225 delete out;
226 return 1;
227 }
189 } 228 }
190 229
191 Vamp::Plugin *plugin = loader->loadPlugin 230 Vamp::Plugin *plugin = loader->loadPlugin
192 (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL); 231 (key, sfinfo.samplerate, PluginLoader::ADAPT_ALL);
193 if (!plugin) { 232 if (!plugin) {
194 cerr << myname << ": ERROR: Failed to load plugin \"" << id 233 cerr << myname << ": ERROR: Failed to load plugin \"" << id
195 << "\" from library \"" << soname << "\"" << endl; 234 << "\" from library \"" << soname << "\"" << endl;
196 sf_close(sndfile); 235 sf_close(sndfile);
236 if (out) {
237 out->close();
238 delete out;
239 }
197 return 1; 240 return 1;
198 } 241 }
199 242
200 cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl; 243 cerr << "Running plugin: \"" << plugin->getIdentifier() << "\"..." << endl;
201 244
227 270
228 Vamp::Plugin::OutputList outputs = plugin->getOutputDescriptors(); 271 Vamp::Plugin::OutputList outputs = plugin->getOutputDescriptors();
229 Vamp::Plugin::OutputDescriptor od; 272 Vamp::Plugin::OutputDescriptor od;
230 273
231 int returnValue = 1; 274 int returnValue = 1;
275 int progress = 0;
232 276
233 if (outputs.empty()) { 277 if (outputs.empty()) {
234 cerr << "ERROR: Plugin has no outputs!" << endl; 278 cerr << "ERROR: Plugin has no outputs!" << endl;
235 goto done; 279 goto done;
236 } 280 }
293 } 337 }
294 } 338 }
295 339
296 printFeatures 340 printFeatures
297 (i, sfinfo.samplerate, outputNo, plugin->process 341 (i, sfinfo.samplerate, outputNo, plugin->process
298 (plugbuf, Vamp::RealTime::frame2RealTime(i, sfinfo.samplerate))); 342 (plugbuf, Vamp::RealTime::frame2RealTime(i, sfinfo.samplerate)),
299 } 343 out);
344
345 int pp = progress;
346 progress = lrintf((float(i) / sfinfo.frames) * 100.f);
347 if (progress != pp && out) {
348 cerr << "\r" << progress << "%";
349 }
350 }
351 if (out) cerr << "\rDone" << endl;
300 352
301 printFeatures(sfinfo.frames, sfinfo.samplerate, outputNo, 353 printFeatures(sfinfo.frames, sfinfo.samplerate, outputNo,
302 plugin->getRemainingFeatures()); 354 plugin->getRemainingFeatures(), out);
303 355
304 returnValue = 0; 356 returnValue = 0;
305 357
306 done: 358 done:
307 delete plugin; 359 delete plugin;
360 if (out) {
361 out->close();
362 delete out;
363 }
308 sf_close(sndfile); 364 sf_close(sndfile);
309 return returnValue; 365 return returnValue;
310 } 366 }
311 367
312 void 368 void
409 465
410 cout << endl; 466 cout << endl;
411 } 467 }
412 468
413 void 469 void
414 printFeatures(int frame, int sr, int output, Vamp::Plugin::FeatureSet features) 470 printFeatures(int frame, int sr, int output,
471 Vamp::Plugin::FeatureSet features, ofstream *out)
415 { 472 {
416 for (unsigned int i = 0; i < features[output].size(); ++i) { 473 for (unsigned int i = 0; i < features[output].size(); ++i) {
474
417 Vamp::RealTime rt = Vamp::RealTime::frame2RealTime(frame, sr); 475 Vamp::RealTime rt = Vamp::RealTime::frame2RealTime(frame, sr);
476
418 if (features[output][i].hasTimestamp) { 477 if (features[output][i].hasTimestamp) {
419 rt = features[output][i].timestamp; 478 rt = features[output][i].timestamp;
420 } 479 }
421 cout << rt.toString() << ":"; 480
481 (out ? *out : cout) << rt.toString() << ":";
482
422 for (unsigned int j = 0; j < features[output][i].values.size(); ++j) { 483 for (unsigned int j = 0; j < features[output][i].values.size(); ++j) {
423 cout << " " << features[output][i].values[j]; 484 (out ? *out : cout) << " " << features[output][i].values[j];
424 } 485 }
425 cout << endl; 486
487 (out ? *out : cout) << endl;
426 } 488 }
427 } 489 }
428 490
429 491
430 492