cannam@138
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
cannam@138
|
2
|
cannam@138
|
3 #include "vamp-sdk/PluginHostAdapter.h"
|
cannam@138
|
4 #include "vamp-sdk/hostext/PluginChannelAdapter.h"
|
cannam@138
|
5 #include "vamp-sdk/hostext/PluginInputDomainAdapter.h"
|
cannam@138
|
6 #include "vamp-sdk/hostext/PluginLoader.h"
|
cannam@138
|
7 #include "vamp/vamp.h"
|
cannam@138
|
8
|
cannam@138
|
9 #include <iostream>
|
cannam@138
|
10 #include <fstream>
|
cannam@138
|
11 #include <sstream>
|
cannam@138
|
12 #include <sndfile.h>
|
cannam@138
|
13
|
cannam@138
|
14 #include <cmath>
|
cannam@138
|
15
|
cannam@138
|
16 using std::cout;
|
cannam@138
|
17 using std::cin;
|
cannam@138
|
18 using std::cerr;
|
cannam@138
|
19 using std::getline;
|
cannam@138
|
20 using std::endl;
|
cannam@138
|
21 using std::string;
|
cannam@138
|
22 using std::vector;
|
cannam@138
|
23 using std::ofstream;
|
cannam@138
|
24 using std::ios;
|
cannam@138
|
25
|
cannam@138
|
26 using Vamp::HostExt::PluginLoader;
|
cannam@138
|
27 using Vamp::Plugin;
|
cannam@138
|
28
|
cannam@138
|
29 /*
|
cannam@138
|
30
|
cannam@138
|
31 usage:
|
cannam@138
|
32
|
cannam@138
|
33 template-generator vamp:aubioonset:onsets
|
cannam@138
|
34
|
cannam@138
|
35 */
|
cannam@138
|
36
|
cannam@138
|
37 string programURI = "http://www.vamp-plugins.org/doap.rdf#template-generator";
|
cannam@138
|
38
|
cannam@138
|
39 void usage()
|
cannam@138
|
40 {
|
cannam@138
|
41 cerr << "usage: template-generator [PLUGIN_BASE_URI YOUR_URI] vamp:soname:plugin[:output]" << endl;
|
cannam@138
|
42 exit(2);
|
cannam@138
|
43 }
|
cannam@138
|
44
|
cannam@138
|
45 template <class T>
|
cannam@138
|
46 inline string to_string (const T& t)
|
cannam@138
|
47 {
|
cannam@138
|
48 std::stringstream ss;
|
cannam@138
|
49 ss << t;
|
cannam@138
|
50 return ss.str();
|
cannam@138
|
51 }
|
cannam@138
|
52
|
cannam@138
|
53 string describe_namespaces(Plugin* plugin, string pluginBundleBaseURI)
|
cannam@138
|
54 {
|
cannam@138
|
55 string res=\
|
cannam@138
|
56 "@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n\
|
cannam@138
|
57 @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .\n\
|
cannam@139
|
58 @prefix vamp: <http://www.purl.org/ontology/vamp/> .\n\
|
cannam@139
|
59 @prefix vampex: <http://www.purl.org/ontology/vamp/examples/> .\n\
|
cannam@138
|
60 @prefix plugbase: <"+pluginBundleBaseURI+"> .\n\
|
cannam@138
|
61 @prefix owl: <http://www.w3.org/2002/07/owl#> .\n\
|
cannam@138
|
62 @prefix dc: <http://purl.org/dc/elements/1.1/> .\n\
|
cannam@138
|
63 @prefix af: <http://purl.org/ontology/af/> .\n\
|
cannam@138
|
64 @prefix foaf: <http://xmlns.com/foaf/0.1/> .\n\
|
cannam@138
|
65 @prefix cc: <http://web.resource.org/cc/> .\n\
|
cannam@138
|
66 @prefix thisplug: <"+pluginBundleBaseURI+plugin->getIdentifier()+"#> .\n\
|
cannam@138
|
67 @prefix : <> .\n\n";
|
cannam@138
|
68
|
cannam@138
|
69 return res;
|
cannam@138
|
70 }
|
cannam@138
|
71
|
cannam@138
|
72 string describe_doc(Plugin* plugin, string describerURI)
|
cannam@138
|
73 {
|
cannam@138
|
74 string res=\
|
cannam@138
|
75 "<> a vamp:PluginDescription ;\n\
|
cannam@138
|
76 foaf:maker <"+describerURI+"> ;\n\
|
cannam@138
|
77 foaf:maker <"+programURI+"> ;\n\
|
cannam@138
|
78 foaf:primaryTopic plugbase:"+plugin->getIdentifier()+" .\n\n";
|
cannam@138
|
79 return res;
|
cannam@138
|
80 }
|
cannam@138
|
81
|
cannam@138
|
82
|
cannam@138
|
83 string describe_plugin(Plugin* plugin)
|
cannam@138
|
84 {
|
cannam@138
|
85 string res=\
|
cannam@138
|
86 "plugbase:"+plugin->getIdentifier()+" a vamp:Plugin ;\n\
|
cannam@138
|
87 dc:title \""+plugin->getName()+"\" ;\n\
|
cannam@139
|
88 vamp:name \""+plugin->getName()+"\" ;\n\
|
cannam@138
|
89 dc:description \""+plugin->getDescription()+"\" ;\n\
|
cannam@138
|
90 foaf:maker [ foaf:name \""+plugin->getMaker()+"\"] ; # FIXME could give plugin author's URI here\n\
|
cannam@138
|
91 cc:license <FIXME license for the plugin> ; \n\
|
cannam@138
|
92 vamp:identifier \""+plugin->getIdentifier()+"\" ;\n\
|
cannam@138
|
93 vamp:vamp_API_version vamp:api_version_"+to_string(plugin->getVampApiVersion())+" ;\n\
|
cannam@138
|
94 owl:versionInfo \""+to_string(plugin->getPluginVersion())+"\" ;\n";
|
cannam@138
|
95 if (plugin->getInputDomain() == Vamp::Plugin::FrequencyDomain)
|
cannam@138
|
96 res+=" vamp:input_domain vamp:FrequencyDomain ;\n\n";
|
cannam@138
|
97 else
|
cannam@138
|
98 res+=" vamp:input_domain vamp:TimeDomain ;\n\n";
|
cannam@138
|
99
|
cannam@138
|
100
|
cannam@138
|
101 Plugin::ParameterList params = plugin->getParameterDescriptors();
|
cannam@138
|
102 for (Plugin::ParameterList::const_iterator i = params.begin(); i != params.end(); i++)
|
cannam@138
|
103 res+=" vamp:parameter_descriptor thisplug:param_"+(*i).identifier+" ;\n";
|
cannam@138
|
104 res+="\n";
|
cannam@138
|
105
|
cannam@138
|
106 Plugin::OutputList outputs = plugin->getOutputDescriptors();
|
cannam@138
|
107 for (Plugin::OutputList::const_iterator i = outputs.begin(); i!= outputs.end(); i++)
|
cannam@138
|
108 res+=" vamp:output_descriptor thisplug:output_"+(*i).identifier+" ;\n";
|
cannam@138
|
109 res+=" .\n";
|
cannam@138
|
110
|
cannam@138
|
111 return res;
|
cannam@138
|
112 }
|
cannam@138
|
113
|
cannam@138
|
114 string describe_param(Plugin::ParameterDescriptor p)
|
cannam@138
|
115 {
|
cannam@138
|
116 string res=\
|
cannam@138
|
117 "thisplug:param_"+p.identifier+" a vamp:ParameterDescriptor ;\n\
|
cannam@138
|
118 vamp:identifier \""+p.identifier+"\" ;\n\
|
cannam@138
|
119 dc:title \""+p.name+"\" ;\n\
|
cannam@138
|
120 dc:format \""+p.unit+"\" ;\n\
|
cannam@139
|
121 vamp:min_value "+to_string(p.minValue)+" ;\n\
|
cannam@139
|
122 vamp:max_value "+to_string(p.maxValue)+" ;\n\
|
cannam@139
|
123 vamp:default_value "+to_string(p.defaultValue)+" .\n\n";
|
cannam@138
|
124 return res;
|
cannam@138
|
125 }
|
cannam@138
|
126
|
cannam@138
|
127 string describe_output(Plugin::OutputDescriptor o)
|
cannam@138
|
128 {
|
cannam@138
|
129
|
cannam@139
|
130 //we need to distinguish here between different output types:
|
cannam@139
|
131 //DenseOutput
|
cannam@139
|
132 //SparseOutput
|
cannam@139
|
133 //TrackLevelOutput
|
cannam@139
|
134
|
cannam@139
|
135
|
cannam@139
|
136 //SparseOutput: variable sample rate. Events are not evenly spaced so we need to record the time associated with the event as it its not ensured that we have an event after the next one (but there is not time to set the duration, it has to be calculated as the different between 2 different events). The timestamp must be read.
|
cannam@139
|
137
|
cannam@139
|
138 string res;
|
cannam@139
|
139
|
cannam@139
|
140 if (o.sampleType == Plugin::OutputDescriptor::VariableSampleRate)
|
cannam@138
|
141 {
|
cannam@139
|
142
|
cannam@139
|
143 res=\
|
cannam@139
|
144 "thisplug:output_"+o.identifier+" a vamp:SparseOutput ;\n\
|
cannam@139
|
145 vamp:identifier \""+o.identifier+"\" ;\n\
|
cannam@139
|
146 dc:title \""+o.name+"\" ;\n\
|
cannam@139
|
147 dc:description \""+o.description+"\" ;\n\
|
cannam@139
|
148 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\
|
cannam@139
|
149 vamp:is_quantized \""+(o.isQuantized == 1 ? "true" : "false")+"\" ;\n\
|
cannam@139
|
150 vamp:unit \""+(o.unit)+"\" ;\n";
|
cannam@139
|
151
|
cannam@139
|
152
|
cannam@139
|
153
|
cannam@139
|
154 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading...
|
cannam@139
|
155 if (o.hasFixedBinCount)
|
cannam@139
|
156 {
|
cannam@139
|
157 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n";
|
cannam@139
|
158 res+=" vamp:bin_names (";
|
cannam@138
|
159
|
cannam@138
|
160 unsigned int i;
|
cannam@138
|
161 for (i=0; i+1 < o.binNames.size(); i++)
|
cannam@138
|
162 res+=" \""+o.binNames[i]+"\"";
|
cannam@138
|
163 if (i < o.binNames.size())
|
cannam@138
|
164 res+=" \""+o.binNames[i]+"\"";
|
cannam@138
|
165 res+=");\n";
|
cannam@139
|
166 }
|
cannam@139
|
167
|
cannam@139
|
168 if (o.isQuantized)
|
cannam@139
|
169 {
|
cannam@139
|
170 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n";
|
cannam@139
|
171 }
|
cannam@139
|
172
|
cannam@139
|
173 res+=" vamp:sample_type vamp:VariableSampleRate ;\n";
|
cannam@138
|
174 if (o.sampleRate > 0.0f)
|
cannam@138
|
175 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n";
|
cannam@139
|
176
|
cannam@139
|
177 }
|
cannam@138
|
178
|
cannam@139
|
179 //If we do not have SparseOutput, then we have DenseOutput. TrackLevelOutput can not be inferred from the plugin directly without actually
|
cannam@139
|
180 //running the plugin.
|
cannam@139
|
181 else{
|
cannam@139
|
182
|
cannam@139
|
183 res=\
|
cannam@139
|
184 "thisplug:output_"+o.identifier+" a vamp:DenseOutput ;\n\
|
cannam@139
|
185 vamp:identifier \""+o.identifier+"\" ;\n\
|
cannam@139
|
186 dc:title \""+o.name+"\" ;\n\
|
cannam@139
|
187 dc:description \""+o.description+"\" ;\n\
|
cannam@139
|
188 vamp:fixed_bin_count \""+(o.hasFixedBinCount == 1 ? "true" : "false")+"\" ;\n\
|
cannam@139
|
189 vamp:is_quantised \""+(o.isQuantized == 1 ? "true" : "false")+"\" ;\n\
|
cannam@139
|
190 vamp:unit \""+(o.unit)+"\" ;\n";
|
cannam@139
|
191
|
cannam@139
|
192
|
cannam@139
|
193
|
cannam@139
|
194 // FIXME ? Bin names may vary based on plugin setup, so including them here might be misleading...
|
cannam@139
|
195 if (o.hasFixedBinCount)
|
cannam@139
|
196 {
|
cannam@139
|
197 res+=" vamp:bin_count "+to_string(o.binCount)+" ;\n";
|
cannam@139
|
198 res+=" vamp:bin_names (";
|
cannam@139
|
199
|
cannam@139
|
200 unsigned int i;
|
cannam@139
|
201 for (i=0; i+1 < o.binNames.size(); i++)
|
cannam@139
|
202 res+=" \""+o.binNames[i]+"\"";
|
cannam@139
|
203 if (i < o.binNames.size())
|
cannam@139
|
204 res+=" \""+o.binNames[i]+"\"";
|
cannam@139
|
205 res+=");\n";
|
cannam@139
|
206 }
|
cannam@139
|
207
|
cannam@139
|
208 if (o.isQuantized)
|
cannam@139
|
209 {
|
cannam@139
|
210 res+=" vamp:quantize_step "+to_string(o.quantizeStep)+" ;\n";
|
cannam@139
|
211 }
|
cannam@139
|
212
|
cannam@139
|
213
|
cannam@139
|
214 else if (o.sampleType == Plugin::OutputDescriptor::FixedSampleRate)
|
cannam@139
|
215 {
|
cannam@139
|
216 res+=" vamp:sample_type vamp:FixedSampleRate ;\n";
|
cannam@139
|
217 res+=" vamp:sample_rate "+to_string(o.sampleRate)+" ;\n";
|
cannam@139
|
218 }
|
cannam@139
|
219 else if (o.sampleType == Plugin::OutputDescriptor::OneSamplePerStep)
|
cannam@139
|
220 res+=" vamp:sample_type vamp:OneSamplePerStep ;\n";
|
cannam@139
|
221 else
|
cannam@139
|
222 {
|
cannam@139
|
223 cerr<<"Incomprehensible sampleType for output descriptor "+o.identifier<<" !"<<endl;
|
cannam@139
|
224 exit(1);
|
cannam@139
|
225 }
|
cannam@139
|
226 }
|
cannam@139
|
227
|
cannam@139
|
228 //There is no way to know this in advance, but we can use the km a bit for this.
|
cannam@138
|
229 res+=" vamp:computes_feature_type <FIXME feature type URI> ;\n";
|
cannam@138
|
230 res+=" vamp:computes_event_type <FIXME event type URI> ;\n";
|
cannam@138
|
231 res+=" .\n";
|
cannam@138
|
232
|
cannam@138
|
233 return res;
|
cannam@138
|
234 }
|
cannam@139
|
235
|
cannam@138
|
236 string describe(Plugin* plugin, string pluginBundleBaseURI, string describerURI)
|
cannam@138
|
237 {
|
cannam@138
|
238 string res = describe_namespaces(plugin, pluginBundleBaseURI);
|
cannam@138
|
239
|
cannam@138
|
240 res += describe_doc(plugin, describerURI);
|
cannam@138
|
241
|
cannam@138
|
242 res += describe_plugin(plugin);
|
cannam@138
|
243
|
cannam@138
|
244 Plugin::ParameterList params = plugin->getParameterDescriptors();
|
cannam@138
|
245 for (Plugin::ParameterList::const_iterator i = params.begin(); i != params.end(); i++)
|
cannam@138
|
246 res += describe_param(*i);
|
cannam@138
|
247
|
cannam@138
|
248 Plugin::OutputList outputs = plugin->getOutputDescriptors();
|
cannam@138
|
249 for (Plugin::OutputList::const_iterator i = outputs.begin(); i!= outputs.end(); i++)
|
cannam@138
|
250 res += describe_output(*i);
|
cannam@138
|
251
|
cannam@138
|
252 return res;
|
cannam@138
|
253 }
|
cannam@138
|
254
|
cannam@138
|
255 int main(int argc, char **argv)
|
cannam@138
|
256 {
|
cannam@138
|
257 if (argc != 2 && argc != 4) usage();
|
cannam@138
|
258
|
cannam@138
|
259 std::string pluginName = argv[argc-1];
|
cannam@138
|
260
|
cannam@138
|
261 if (pluginName.substr(0, 5) == "vamp:") {
|
cannam@138
|
262 pluginName = pluginName.substr(5);
|
cannam@138
|
263 }
|
cannam@138
|
264
|
cannam@138
|
265 Vamp::Plugin *plugin = PluginLoader::getInstance()->loadPlugin
|
cannam@138
|
266 (pluginName, size_t(44100), PluginLoader::ADAPT_ALL_SAFE);
|
cannam@138
|
267
|
cannam@138
|
268 if (!plugin) {
|
cannam@138
|
269 cerr << "ERROR: Plugin \"" << pluginName << "\" could not be loaded" << endl;
|
cannam@138
|
270 exit(1);
|
cannam@138
|
271 }
|
cannam@138
|
272
|
cannam@138
|
273 string pluginBundleBaseURI, describerURI;
|
cannam@138
|
274
|
cannam@138
|
275 if (argc == 4)
|
cannam@138
|
276 {
|
cannam@138
|
277 pluginBundleBaseURI = argv[1];
|
cannam@138
|
278 describerURI = argv[2];
|
cannam@138
|
279 }
|
cannam@138
|
280 else
|
cannam@138
|
281 {
|
cannam@138
|
282 cerr << "Please enter the base URI for the plugin bundle : ";
|
cannam@138
|
283 getline(cin, pluginBundleBaseURI);
|
cannam@138
|
284 cerr << "Please enter your URI : ";
|
cannam@138
|
285 getline(cin, describerURI);
|
cannam@138
|
286 }
|
cannam@138
|
287
|
cannam@138
|
288 cout << describe(plugin, pluginBundleBaseURI, describerURI) << endl;
|
cannam@138
|
289
|
cannam@138
|
290 return 0;
|
cannam@138
|
291 }
|
cannam@138
|
292
|
cannam@138
|
293
|