Chris@320
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@320
|
2
|
Chris@320
|
3 /*
|
Chris@320
|
4 Sonic Visualiser
|
Chris@320
|
5 An audio file viewer and annotation editor.
|
Chris@320
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@328
|
7 This file copyright 2006-2007 Chris Cannam and QMUL.
|
Chris@320
|
8
|
Chris@320
|
9 This program is free software; you can redistribute it and/or
|
Chris@320
|
10 modify it under the terms of the GNU General Public License as
|
Chris@320
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@320
|
12 License, or (at your option) any later version. See the file
|
Chris@320
|
13 COPYING included with this distribution for more information.
|
Chris@320
|
14 */
|
Chris@320
|
15
|
Chris@320
|
16 #include "Transform.h"
|
Chris@320
|
17
|
Chris@328
|
18 #include "plugin/PluginIdentifier.h"
|
Chris@328
|
19
|
Chris@332
|
20 #include "plugin/FeatureExtractionPluginFactory.h"
|
Chris@332
|
21
|
Chris@350
|
22 #include <QXmlAttributes>
|
Chris@350
|
23
|
Chris@350
|
24 #include <QDomDocument>
|
Chris@350
|
25 #include <QDomElement>
|
Chris@350
|
26 #include <QDomNamedNodeMap>
|
Chris@350
|
27 #include <QDomAttr>
|
Chris@350
|
28
|
Chris@350
|
29 #include <QTextStream>
|
Chris@350
|
30
|
Chris@350
|
31 #include <iostream>
|
Chris@350
|
32
|
Chris@328
|
33 Transform::Transform() :
|
Chris@328
|
34 m_stepSize(0),
|
Chris@328
|
35 m_blockSize(0),
|
Chris@328
|
36 m_windowType(HanningWindow),
|
Chris@328
|
37 m_sampleRate(0)
|
Chris@320
|
38 {
|
Chris@320
|
39 }
|
Chris@320
|
40
|
Chris@350
|
41 Transform::Transform(QString xml) :
|
Chris@350
|
42 m_stepSize(0),
|
Chris@350
|
43 m_blockSize(0),
|
Chris@350
|
44 m_windowType(HanningWindow),
|
Chris@350
|
45 m_sampleRate(0)
|
Chris@350
|
46 {
|
Chris@350
|
47 QDomDocument doc;
|
Chris@350
|
48
|
Chris@350
|
49 QString error;
|
Chris@350
|
50 int errorLine;
|
Chris@350
|
51 int errorColumn;
|
Chris@350
|
52
|
Chris@350
|
53 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
|
Chris@350
|
54 std::cerr << "Transform::Transform: Error in parsing XML: "
|
Chris@350
|
55 << error.toStdString() << " at line " << errorLine
|
Chris@350
|
56 << ", column " << errorColumn << std::endl;
|
Chris@350
|
57 std::cerr << "Input follows:" << std::endl;
|
Chris@350
|
58 std::cerr << xml.toStdString() << std::endl;
|
Chris@350
|
59 std::cerr << "Input ends." << std::endl;
|
Chris@350
|
60 return;
|
Chris@350
|
61 }
|
Chris@350
|
62
|
Chris@350
|
63 QDomElement transformElt = doc.firstChildElement("transform");
|
Chris@350
|
64 QDomNamedNodeMap attrNodes = transformElt.attributes();
|
Chris@350
|
65 QXmlAttributes attrs;
|
Chris@350
|
66
|
Chris@350
|
67 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
|
Chris@350
|
68 QDomAttr attr = attrNodes.item(i).toAttr();
|
Chris@350
|
69 if (!attr.isNull()) attrs.append(attr.name(), "", "", attr.value());
|
Chris@350
|
70 }
|
Chris@350
|
71
|
Chris@350
|
72 setFromXmlAttributes(attrs);
|
Chris@350
|
73
|
Chris@350
|
74 for (QDomElement paramElt = transformElt.firstChildElement("parameter");
|
Chris@350
|
75 !paramElt.isNull();
|
Chris@350
|
76 paramElt = paramElt.nextSiblingElement("parameter")) {
|
Chris@350
|
77
|
Chris@350
|
78 QDomNamedNodeMap paramAttrs = paramElt.attributes();
|
Chris@350
|
79
|
Chris@350
|
80 QDomAttr nameAttr = paramAttrs.namedItem("name").toAttr();
|
Chris@350
|
81 if (nameAttr.isNull() || nameAttr.value() == "") continue;
|
Chris@350
|
82
|
Chris@350
|
83 QDomAttr valueAttr = paramAttrs.namedItem("value").toAttr();
|
Chris@350
|
84 if (valueAttr.isNull() || valueAttr.value() == "") continue;
|
Chris@350
|
85
|
Chris@350
|
86 setParameter(nameAttr.value(), valueAttr.value().toFloat());
|
Chris@350
|
87 }
|
Chris@350
|
88
|
Chris@350
|
89 for (QDomElement configElt = transformElt.firstChildElement("configuration");
|
Chris@350
|
90 !configElt.isNull();
|
Chris@350
|
91 configElt = configElt.nextSiblingElement("configuration")) {
|
Chris@350
|
92
|
Chris@350
|
93 QDomNamedNodeMap configAttrs = configElt.attributes();
|
Chris@350
|
94
|
Chris@350
|
95 QDomAttr nameAttr = configAttrs.namedItem("name").toAttr();
|
Chris@350
|
96 if (nameAttr.isNull() || nameAttr.value() == "") continue;
|
Chris@350
|
97
|
Chris@350
|
98 QDomAttr valueAttr = configAttrs.namedItem("value").toAttr();
|
Chris@350
|
99 if (valueAttr.isNull() || valueAttr.value() == "") continue;
|
Chris@350
|
100
|
Chris@350
|
101 setConfigurationValue(nameAttr.value(), valueAttr.value());
|
Chris@350
|
102 }
|
Chris@350
|
103 }
|
Chris@350
|
104
|
Chris@320
|
105 Transform::~Transform()
|
Chris@320
|
106 {
|
Chris@320
|
107 }
|
Chris@320
|
108
|
Chris@350
|
109 bool
|
Chris@350
|
110 Transform::operator==(const Transform &t)
|
Chris@350
|
111 {
|
Chris@350
|
112 return
|
Chris@350
|
113 m_id == t.m_id &&
|
Chris@350
|
114 m_parameters == t.m_parameters &&
|
Chris@350
|
115 m_configuration == t.m_configuration &&
|
Chris@350
|
116 m_program == t.m_program &&
|
Chris@350
|
117 m_stepSize == t.m_stepSize &&
|
Chris@350
|
118 m_blockSize == t.m_blockSize &&
|
Chris@350
|
119 m_windowType == t.m_windowType &&
|
Chris@350
|
120 m_startTime == t.m_startTime &&
|
Chris@350
|
121 m_duration == t.m_duration &&
|
Chris@350
|
122 m_sampleRate == t.m_sampleRate;
|
Chris@350
|
123 }
|
Chris@350
|
124
|
Chris@350
|
125 void
|
Chris@350
|
126 Transform::setIdentifier(TransformId id)
|
Chris@350
|
127 {
|
Chris@350
|
128 m_id = id;
|
Chris@350
|
129 }
|
Chris@350
|
130
|
Chris@350
|
131 TransformId
|
Chris@350
|
132 Transform::getIdentifier() const
|
Chris@350
|
133 {
|
Chris@350
|
134 return m_id;
|
Chris@350
|
135 }
|
Chris@350
|
136
|
Chris@328
|
137 QString
|
Chris@328
|
138 Transform::createIdentifier(QString type, QString soName, QString label,
|
Chris@328
|
139 QString output)
|
Chris@328
|
140 {
|
Chris@328
|
141 QString pluginId = PluginIdentifier::createIdentifier(type, soName, label);
|
Chris@328
|
142 return pluginId + ":" + output;
|
Chris@328
|
143 }
|
Chris@328
|
144
|
Chris@328
|
145 void
|
Chris@328
|
146 Transform::parseIdentifier(QString identifier,
|
Chris@328
|
147 QString &type, QString &soName,
|
Chris@328
|
148 QString &label, QString &output)
|
Chris@328
|
149 {
|
Chris@328
|
150 output = identifier.section(':', 3);
|
Chris@328
|
151 PluginIdentifier::parseIdentifier(identifier.section(':', 0, 2),
|
Chris@328
|
152 type, soName, label);
|
Chris@328
|
153 }
|
Chris@328
|
154
|
Chris@328
|
155 Transform::Type
|
Chris@328
|
156 Transform::getType() const
|
Chris@328
|
157 {
|
Chris@332
|
158 if (FeatureExtractionPluginFactory::instanceFor(getPluginIdentifier())) {
|
Chris@332
|
159 return FeatureExtraction;
|
Chris@332
|
160 } else {
|
Chris@332
|
161 // We don't have an unknown/invalid return value, so always
|
Chris@332
|
162 // return this
|
Chris@332
|
163 return RealTimeEffect;
|
Chris@332
|
164 }
|
Chris@328
|
165 }
|
Chris@328
|
166
|
Chris@328
|
167 QString
|
Chris@328
|
168 Transform::getPluginIdentifier() const
|
Chris@328
|
169 {
|
Chris@328
|
170 return m_id.section(':', 0, 2);
|
Chris@328
|
171 }
|
Chris@328
|
172
|
Chris@328
|
173 QString
|
Chris@328
|
174 Transform::getOutput() const
|
Chris@328
|
175 {
|
Chris@328
|
176 return m_id.section(':', 3);
|
Chris@328
|
177 }
|
Chris@328
|
178
|
Chris@353
|
179 void
|
Chris@353
|
180 Transform::setPluginIdentifier(QString pluginIdentifier)
|
Chris@353
|
181 {
|
Chris@353
|
182 m_id = pluginIdentifier + ':' + getOutput();
|
Chris@353
|
183 }
|
Chris@353
|
184
|
Chris@353
|
185 void
|
Chris@353
|
186 Transform::setOutput(QString output)
|
Chris@353
|
187 {
|
Chris@353
|
188 m_id = getPluginIdentifier() + ':' + output;
|
Chris@353
|
189 }
|
Chris@353
|
190
|
Chris@353
|
191 TransformId
|
Chris@353
|
192 Transform::getIdentifierForPluginOutput(QString pluginIdentifier,
|
Chris@353
|
193 QString output)
|
Chris@353
|
194 {
|
Chris@353
|
195 return pluginIdentifier + ':' + output;
|
Chris@353
|
196 }
|
Chris@353
|
197
|
Chris@350
|
198 const Transform::ParameterMap &
|
Chris@350
|
199 Transform::getParameters() const
|
Chris@350
|
200 {
|
Chris@350
|
201 return m_parameters;
|
Chris@350
|
202 }
|
Chris@350
|
203
|
Chris@328
|
204 void
|
Chris@350
|
205 Transform::setParameters(const ParameterMap &pm)
|
Chris@328
|
206 {
|
Chris@350
|
207 m_parameters = pm;
|
Chris@350
|
208 }
|
Chris@350
|
209
|
Chris@350
|
210 void
|
Chris@350
|
211 Transform::setParameter(QString name, float value)
|
Chris@350
|
212 {
|
Chris@350
|
213 std::cerr << "Transform::setParameter(" << name.toStdString()
|
Chris@350
|
214 << ") -> " << value << std::endl;
|
Chris@350
|
215 m_parameters[name] = value;
|
Chris@350
|
216 }
|
Chris@350
|
217
|
Chris@350
|
218 const Transform::ConfigurationMap &
|
Chris@350
|
219 Transform::getConfiguration() const
|
Chris@350
|
220 {
|
Chris@350
|
221 return m_configuration;
|
Chris@350
|
222 }
|
Chris@350
|
223
|
Chris@350
|
224 void
|
Chris@350
|
225 Transform::setConfiguration(const ConfigurationMap &cm)
|
Chris@350
|
226 {
|
Chris@350
|
227 m_configuration = cm;
|
Chris@350
|
228 }
|
Chris@350
|
229
|
Chris@350
|
230 void
|
Chris@350
|
231 Transform::setConfigurationValue(QString name, QString value)
|
Chris@350
|
232 {
|
Chris@350
|
233 std::cerr << "Transform::setConfigurationValue(" << name.toStdString()
|
Chris@350
|
234 << ") -> " << value.toStdString() << std::endl;
|
Chris@350
|
235 m_configuration[name] = value;
|
Chris@350
|
236 }
|
Chris@350
|
237
|
Chris@350
|
238 QString
|
Chris@366
|
239 Transform::getPluginVersion() const
|
Chris@366
|
240 {
|
Chris@366
|
241 return m_pluginVersion;
|
Chris@366
|
242 }
|
Chris@366
|
243
|
Chris@366
|
244 void
|
Chris@366
|
245 Transform::setPluginVersion(QString version)
|
Chris@366
|
246 {
|
Chris@366
|
247 m_pluginVersion = version;
|
Chris@366
|
248 }
|
Chris@366
|
249
|
Chris@366
|
250 QString
|
Chris@350
|
251 Transform::getProgram() const
|
Chris@350
|
252 {
|
Chris@350
|
253 return m_program;
|
Chris@350
|
254 }
|
Chris@350
|
255
|
Chris@350
|
256 void
|
Chris@350
|
257 Transform::setProgram(QString program)
|
Chris@350
|
258 {
|
Chris@350
|
259 m_program = program;
|
Chris@350
|
260 }
|
Chris@350
|
261
|
Chris@328
|
262
|
Chris@350
|
263 size_t
|
Chris@350
|
264 Transform::getStepSize() const
|
Chris@350
|
265 {
|
Chris@350
|
266 return m_stepSize;
|
Chris@328
|
267 }
|
Chris@350
|
268
|
Chris@350
|
269 void
|
Chris@350
|
270 Transform::setStepSize(size_t s)
|
Chris@350
|
271 {
|
Chris@350
|
272 m_stepSize = s;
|
Chris@350
|
273 }
|
Chris@350
|
274
|
Chris@350
|
275 size_t
|
Chris@350
|
276 Transform::getBlockSize() const
|
Chris@350
|
277 {
|
Chris@350
|
278 return m_blockSize;
|
Chris@350
|
279 }
|
Chris@350
|
280
|
Chris@350
|
281 void
|
Chris@350
|
282 Transform::setBlockSize(size_t s)
|
Chris@350
|
283 {
|
Chris@350
|
284 m_blockSize = s;
|
Chris@350
|
285 }
|
Chris@350
|
286
|
Chris@350
|
287 WindowType
|
Chris@350
|
288 Transform::getWindowType() const
|
Chris@350
|
289 {
|
Chris@350
|
290 return m_windowType;
|
Chris@350
|
291 }
|
Chris@350
|
292
|
Chris@350
|
293 void
|
Chris@350
|
294 Transform::setWindowType(WindowType type)
|
Chris@350
|
295 {
|
Chris@350
|
296 m_windowType = type;
|
Chris@350
|
297 }
|
Chris@350
|
298
|
Chris@350
|
299 RealTime
|
Chris@350
|
300 Transform::getStartTime() const
|
Chris@350
|
301 {
|
Chris@350
|
302 return m_startTime;
|
Chris@350
|
303 }
|
Chris@350
|
304
|
Chris@350
|
305 void
|
Chris@350
|
306 Transform::setStartTime(RealTime t)
|
Chris@350
|
307 {
|
Chris@350
|
308 m_startTime = t;
|
Chris@350
|
309 }
|
Chris@350
|
310
|
Chris@350
|
311 RealTime
|
Chris@350
|
312 Transform::getDuration() const
|
Chris@350
|
313 {
|
Chris@350
|
314 return m_duration;
|
Chris@350
|
315 }
|
Chris@350
|
316
|
Chris@350
|
317 void
|
Chris@350
|
318 Transform::setDuration(RealTime d)
|
Chris@350
|
319 {
|
Chris@350
|
320 m_duration = d;
|
Chris@350
|
321 }
|
Chris@350
|
322
|
Chris@350
|
323 float
|
Chris@350
|
324 Transform::getSampleRate() const
|
Chris@350
|
325 {
|
Chris@350
|
326 return m_sampleRate;
|
Chris@350
|
327 }
|
Chris@350
|
328
|
Chris@350
|
329 void
|
Chris@350
|
330 Transform::setSampleRate(float rate)
|
Chris@350
|
331 {
|
Chris@350
|
332 m_sampleRate = rate;
|
Chris@350
|
333 }
|
Chris@350
|
334
|
Chris@350
|
335 void
|
Chris@350
|
336 Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const
|
Chris@350
|
337 {
|
Chris@350
|
338 out << indent;
|
Chris@350
|
339
|
Chris@350
|
340 bool haveContent = true;
|
Chris@350
|
341 if (m_parameters.empty() && m_configuration.empty()) haveContent = false;
|
Chris@350
|
342
|
Chris@366
|
343 out << QString("<transform id=\"%1\" pluginVersion=\"%2\" program=\"%3\" stepSize=\"%4\" blockSize=\"%5\" windowType=\"%6\" startTime=\"%7\" duration=\"%8\" sampleRate=\"%9\"")
|
Chris@350
|
344 .arg(encodeEntities(m_id))
|
Chris@366
|
345 .arg(encodeEntities(m_pluginVersion))
|
Chris@350
|
346 .arg(encodeEntities(m_program))
|
Chris@350
|
347 .arg(m_stepSize)
|
Chris@350
|
348 .arg(m_blockSize)
|
Chris@350
|
349 .arg(encodeEntities(Window<float>::getNameForType(m_windowType).c_str()))
|
Chris@350
|
350 .arg(encodeEntities(m_startTime.toString().c_str()))
|
Chris@350
|
351 .arg(encodeEntities(m_duration.toString().c_str()))
|
Chris@366
|
352 .arg(m_sampleRate);
|
Chris@366
|
353
|
Chris@366
|
354 if (extraAttributes != "") {
|
Chris@366
|
355 out << " " << extraAttributes;
|
Chris@366
|
356 }
|
Chris@350
|
357
|
Chris@350
|
358 if (haveContent) {
|
Chris@350
|
359
|
Chris@350
|
360 out << ">\n";
|
Chris@350
|
361
|
Chris@350
|
362 for (ParameterMap::const_iterator i = m_parameters.begin();
|
Chris@350
|
363 i != m_parameters.end(); ++i) {
|
Chris@350
|
364 out << indent << " "
|
Chris@350
|
365 << QString("<parameter name=\"%1\" value=\"%2\"/>\n")
|
Chris@350
|
366 .arg(encodeEntities(i->first))
|
Chris@350
|
367 .arg(i->second);
|
Chris@350
|
368 }
|
Chris@350
|
369
|
Chris@350
|
370 for (ConfigurationMap::const_iterator i = m_configuration.begin();
|
Chris@350
|
371 i != m_configuration.end(); ++i) {
|
Chris@350
|
372 out << indent << " "
|
Chris@350
|
373 << QString("<configuration name=\"%1\" value=\"%2\"/>\n")
|
Chris@350
|
374 .arg(encodeEntities(i->first))
|
Chris@350
|
375 .arg(encodeEntities(i->second));
|
Chris@350
|
376 }
|
Chris@350
|
377
|
Chris@350
|
378 out << indent << "</transform>\n";
|
Chris@350
|
379
|
Chris@350
|
380 } else {
|
Chris@350
|
381
|
Chris@350
|
382 out << "/>\n";
|
Chris@350
|
383 }
|
Chris@350
|
384 }
|
Chris@350
|
385
|
Chris@350
|
386 void
|
Chris@350
|
387 Transform::setFromXmlAttributes(const QXmlAttributes &attrs)
|
Chris@350
|
388 {
|
Chris@350
|
389 if (attrs.value("id") != "") {
|
Chris@350
|
390 setIdentifier(attrs.value("id"));
|
Chris@350
|
391 }
|
Chris@350
|
392
|
Chris@366
|
393 if (attrs.value("pluginVersion") != "") {
|
Chris@366
|
394 setPluginVersion(attrs.value("pluginVersion"));
|
Chris@366
|
395 }
|
Chris@366
|
396
|
Chris@350
|
397 if (attrs.value("program") != "") {
|
Chris@350
|
398 setProgram(attrs.value("program"));
|
Chris@350
|
399 }
|
Chris@350
|
400
|
Chris@350
|
401 if (attrs.value("stepSize") != "") {
|
Chris@350
|
402 setStepSize(attrs.value("stepSize").toInt());
|
Chris@350
|
403 }
|
Chris@350
|
404
|
Chris@350
|
405 if (attrs.value("blockSize") != "") {
|
Chris@350
|
406 setBlockSize(attrs.value("blockSize").toInt());
|
Chris@350
|
407 }
|
Chris@350
|
408
|
Chris@350
|
409 if (attrs.value("windowType") != "") {
|
Chris@350
|
410 setWindowType(Window<float>::getTypeForName
|
Chris@350
|
411 (attrs.value("windowType").toStdString()));
|
Chris@350
|
412 }
|
Chris@350
|
413
|
Chris@350
|
414 if (attrs.value("startTime") != "") {
|
Chris@350
|
415 setStartTime(RealTime::fromString(attrs.value("startTime").toStdString()));
|
Chris@350
|
416 }
|
Chris@350
|
417
|
Chris@350
|
418 if (attrs.value("duration") != "") {
|
Chris@350
|
419 setStartTime(RealTime::fromString(attrs.value("duration").toStdString()));
|
Chris@350
|
420 }
|
Chris@350
|
421
|
Chris@350
|
422 if (attrs.value("sampleRate") != "") {
|
Chris@350
|
423 setSampleRate(attrs.value("sampleRate").toFloat());
|
Chris@350
|
424 }
|
Chris@350
|
425 }
|
Chris@350
|
426
|