Mercurial > hg > vamp-plugin-sdk
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 |