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@384
|
22 #include <QXmlAttributes>
|
Chris@384
|
23
|
Chris@384
|
24 #include <QDomDocument>
|
Chris@384
|
25 #include <QDomElement>
|
Chris@384
|
26 #include <QDomNamedNodeMap>
|
Chris@384
|
27 #include <QDomAttr>
|
Chris@384
|
28
|
Chris@384
|
29 #include <QTextStream>
|
Chris@384
|
30
|
Chris@384
|
31 #include <iostream>
|
Chris@384
|
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@384
|
41 Transform::Transform(QString xml) :
|
Chris@384
|
42 m_stepSize(0),
|
Chris@384
|
43 m_blockSize(0),
|
Chris@384
|
44 m_windowType(HanningWindow),
|
Chris@384
|
45 m_sampleRate(0)
|
Chris@384
|
46 {
|
Chris@384
|
47 QDomDocument doc;
|
Chris@384
|
48
|
Chris@384
|
49 QString error;
|
Chris@384
|
50 int errorLine;
|
Chris@384
|
51 int errorColumn;
|
Chris@384
|
52
|
Chris@384
|
53 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
|
Chris@384
|
54 std::cerr << "Transform::Transform: Error in parsing XML: "
|
Chris@384
|
55 << error.toStdString() << " at line " << errorLine
|
Chris@384
|
56 << ", column " << errorColumn << std::endl;
|
Chris@384
|
57 std::cerr << "Input follows:" << std::endl;
|
Chris@384
|
58 std::cerr << xml.toStdString() << std::endl;
|
Chris@384
|
59 std::cerr << "Input ends." << std::endl;
|
Chris@384
|
60 return;
|
Chris@384
|
61 }
|
Chris@384
|
62
|
Chris@384
|
63 QDomElement transformElt = doc.firstChildElement("transform");
|
Chris@384
|
64 QDomNamedNodeMap attrNodes = transformElt.attributes();
|
Chris@384
|
65 QXmlAttributes attrs;
|
Chris@384
|
66
|
Chris@384
|
67 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
|
Chris@384
|
68 QDomAttr attr = attrNodes.item(i).toAttr();
|
Chris@384
|
69 if (!attr.isNull()) attrs.append(attr.name(), "", "", attr.value());
|
Chris@384
|
70 }
|
Chris@384
|
71
|
Chris@384
|
72 setFromXmlAttributes(attrs);
|
Chris@384
|
73
|
Chris@384
|
74 for (QDomElement paramElt = transformElt.firstChildElement("parameter");
|
Chris@384
|
75 !paramElt.isNull();
|
Chris@384
|
76 paramElt = paramElt.nextSiblingElement("parameter")) {
|
Chris@384
|
77
|
Chris@384
|
78 QDomNamedNodeMap paramAttrs = paramElt.attributes();
|
Chris@384
|
79
|
Chris@384
|
80 QDomAttr nameAttr = paramAttrs.namedItem("name").toAttr();
|
Chris@384
|
81 if (nameAttr.isNull() || nameAttr.value() == "") continue;
|
Chris@384
|
82
|
Chris@384
|
83 QDomAttr valueAttr = paramAttrs.namedItem("value").toAttr();
|
Chris@384
|
84 if (valueAttr.isNull() || valueAttr.value() == "") continue;
|
Chris@384
|
85
|
Chris@384
|
86 setParameter(nameAttr.value(), valueAttr.value().toFloat());
|
Chris@384
|
87 }
|
Chris@384
|
88
|
Chris@384
|
89 for (QDomElement configElt = transformElt.firstChildElement("configuration");
|
Chris@384
|
90 !configElt.isNull();
|
Chris@384
|
91 configElt = configElt.nextSiblingElement("configuration")) {
|
Chris@384
|
92
|
Chris@384
|
93 QDomNamedNodeMap configAttrs = configElt.attributes();
|
Chris@384
|
94
|
Chris@384
|
95 QDomAttr nameAttr = configAttrs.namedItem("name").toAttr();
|
Chris@384
|
96 if (nameAttr.isNull() || nameAttr.value() == "") continue;
|
Chris@384
|
97
|
Chris@384
|
98 QDomAttr valueAttr = configAttrs.namedItem("value").toAttr();
|
Chris@384
|
99 if (valueAttr.isNull() || valueAttr.value() == "") continue;
|
Chris@384
|
100
|
Chris@384
|
101 setConfigurationValue(nameAttr.value(), valueAttr.value());
|
Chris@384
|
102 }
|
Chris@384
|
103 }
|
Chris@384
|
104
|
Chris@320
|
105 Transform::~Transform()
|
Chris@320
|
106 {
|
Chris@320
|
107 }
|
Chris@320
|
108
|
Chris@384
|
109 bool
|
Chris@384
|
110 Transform::operator==(const Transform &t)
|
Chris@384
|
111 {
|
Chris@384
|
112 return
|
Chris@384
|
113 m_id == t.m_id &&
|
Chris@384
|
114 m_parameters == t.m_parameters &&
|
Chris@384
|
115 m_configuration == t.m_configuration &&
|
Chris@384
|
116 m_program == t.m_program &&
|
Chris@384
|
117 m_stepSize == t.m_stepSize &&
|
Chris@384
|
118 m_blockSize == t.m_blockSize &&
|
Chris@384
|
119 m_windowType == t.m_windowType &&
|
Chris@384
|
120 m_startTime == t.m_startTime &&
|
Chris@384
|
121 m_duration == t.m_duration &&
|
Chris@384
|
122 m_sampleRate == t.m_sampleRate;
|
Chris@384
|
123 }
|
Chris@384
|
124
|
Chris@384
|
125 void
|
Chris@384
|
126 Transform::setIdentifier(TransformId id)
|
Chris@384
|
127 {
|
Chris@384
|
128 m_id = id;
|
Chris@384
|
129 }
|
Chris@384
|
130
|
Chris@384
|
131 TransformId
|
Chris@384
|
132 Transform::getIdentifier() const
|
Chris@384
|
133 {
|
Chris@384
|
134 return m_id;
|
Chris@384
|
135 }
|
Chris@384
|
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@328
|
179 void
|
Chris@384
|
180 Transform::setPluginIdentifier(QString pluginIdentifier)
|
Chris@328
|
181 {
|
Chris@384
|
182 m_id = pluginIdentifier + ':' + getOutput();
|
Chris@384
|
183 }
|
Chris@384
|
184
|
Chris@384
|
185 void
|
Chris@384
|
186 Transform::setOutput(QString output)
|
Chris@384
|
187 {
|
Chris@384
|
188 m_id = getPluginIdentifier() + ':' + output;
|
Chris@384
|
189 }
|
Chris@384
|
190
|
Chris@384
|
191 TransformId
|
Chris@384
|
192 Transform::getIdentifierForPluginOutput(QString pluginIdentifier,
|
Chris@384
|
193 QString output)
|
Chris@384
|
194 {
|
Chris@384
|
195 return pluginIdentifier + ':' + output;
|
Chris@384
|
196 }
|
Chris@384
|
197
|
Chris@384
|
198 const Transform::ParameterMap &
|
Chris@384
|
199 Transform::getParameters() const
|
Chris@384
|
200 {
|
Chris@384
|
201 return m_parameters;
|
Chris@384
|
202 }
|
Chris@384
|
203
|
Chris@384
|
204 void
|
Chris@384
|
205 Transform::setParameters(const ParameterMap &pm)
|
Chris@384
|
206 {
|
Chris@384
|
207 m_parameters = pm;
|
Chris@384
|
208 }
|
Chris@384
|
209
|
Chris@384
|
210 void
|
Chris@384
|
211 Transform::setParameter(QString name, float value)
|
Chris@384
|
212 {
|
Chris@384
|
213 std::cerr << "Transform::setParameter(" << name.toStdString()
|
Chris@384
|
214 << ") -> " << value << std::endl;
|
Chris@384
|
215 m_parameters[name] = value;
|
Chris@384
|
216 }
|
Chris@384
|
217
|
Chris@384
|
218 const Transform::ConfigurationMap &
|
Chris@384
|
219 Transform::getConfiguration() const
|
Chris@384
|
220 {
|
Chris@384
|
221 return m_configuration;
|
Chris@384
|
222 }
|
Chris@384
|
223
|
Chris@384
|
224 void
|
Chris@384
|
225 Transform::setConfiguration(const ConfigurationMap &cm)
|
Chris@384
|
226 {
|
Chris@384
|
227 m_configuration = cm;
|
Chris@384
|
228 }
|
Chris@384
|
229
|
Chris@384
|
230 void
|
Chris@384
|
231 Transform::setConfigurationValue(QString name, QString value)
|
Chris@384
|
232 {
|
Chris@384
|
233 std::cerr << "Transform::setConfigurationValue(" << name.toStdString()
|
Chris@384
|
234 << ") -> " << value.toStdString() << std::endl;
|
Chris@384
|
235 m_configuration[name] = value;
|
Chris@384
|
236 }
|
Chris@384
|
237
|
Chris@384
|
238 QString
|
Chris@384
|
239 Transform::getPluginVersion() const
|
Chris@384
|
240 {
|
Chris@384
|
241 return m_pluginVersion;
|
Chris@384
|
242 }
|
Chris@384
|
243
|
Chris@384
|
244 void
|
Chris@384
|
245 Transform::setPluginVersion(QString version)
|
Chris@384
|
246 {
|
Chris@384
|
247 m_pluginVersion = version;
|
Chris@384
|
248 }
|
Chris@384
|
249
|
Chris@384
|
250 QString
|
Chris@384
|
251 Transform::getProgram() const
|
Chris@384
|
252 {
|
Chris@384
|
253 return m_program;
|
Chris@384
|
254 }
|
Chris@384
|
255
|
Chris@384
|
256 void
|
Chris@384
|
257 Transform::setProgram(QString program)
|
Chris@384
|
258 {
|
Chris@384
|
259 m_program = program;
|
Chris@384
|
260 }
|
Chris@384
|
261
|
Chris@328
|
262
|
Chris@384
|
263 size_t
|
Chris@384
|
264 Transform::getStepSize() const
|
Chris@384
|
265 {
|
Chris@384
|
266 return m_stepSize;
|
Chris@328
|
267 }
|
Chris@384
|
268
|
Chris@384
|
269 void
|
Chris@384
|
270 Transform::setStepSize(size_t s)
|
Chris@384
|
271 {
|
Chris@384
|
272 m_stepSize = s;
|
Chris@384
|
273 }
|
Chris@384
|
274
|
Chris@384
|
275 size_t
|
Chris@384
|
276 Transform::getBlockSize() const
|
Chris@384
|
277 {
|
Chris@384
|
278 return m_blockSize;
|
Chris@384
|
279 }
|
Chris@384
|
280
|
Chris@384
|
281 void
|
Chris@384
|
282 Transform::setBlockSize(size_t s)
|
Chris@384
|
283 {
|
Chris@384
|
284 m_blockSize = s;
|
Chris@384
|
285 }
|
Chris@384
|
286
|
Chris@384
|
287 WindowType
|
Chris@384
|
288 Transform::getWindowType() const
|
Chris@384
|
289 {
|
Chris@384
|
290 return m_windowType;
|
Chris@384
|
291 }
|
Chris@384
|
292
|
Chris@384
|
293 void
|
Chris@384
|
294 Transform::setWindowType(WindowType type)
|
Chris@384
|
295 {
|
Chris@384
|
296 m_windowType = type;
|
Chris@384
|
297 }
|
Chris@384
|
298
|
Chris@384
|
299 RealTime
|
Chris@384
|
300 Transform::getStartTime() const
|
Chris@384
|
301 {
|
Chris@384
|
302 return m_startTime;
|
Chris@384
|
303 }
|
Chris@384
|
304
|
Chris@384
|
305 void
|
Chris@384
|
306 Transform::setStartTime(RealTime t)
|
Chris@384
|
307 {
|
Chris@384
|
308 m_startTime = t;
|
Chris@384
|
309 }
|
Chris@384
|
310
|
Chris@384
|
311 RealTime
|
Chris@384
|
312 Transform::getDuration() const
|
Chris@384
|
313 {
|
Chris@384
|
314 return m_duration;
|
Chris@384
|
315 }
|
Chris@384
|
316
|
Chris@384
|
317 void
|
Chris@384
|
318 Transform::setDuration(RealTime d)
|
Chris@384
|
319 {
|
Chris@384
|
320 m_duration = d;
|
Chris@384
|
321 }
|
Chris@384
|
322
|
Chris@384
|
323 float
|
Chris@384
|
324 Transform::getSampleRate() const
|
Chris@384
|
325 {
|
Chris@384
|
326 return m_sampleRate;
|
Chris@384
|
327 }
|
Chris@384
|
328
|
Chris@384
|
329 void
|
Chris@384
|
330 Transform::setSampleRate(float rate)
|
Chris@384
|
331 {
|
Chris@384
|
332 m_sampleRate = rate;
|
Chris@384
|
333 }
|
Chris@384
|
334
|
Chris@384
|
335 void
|
Chris@384
|
336 Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const
|
Chris@384
|
337 {
|
Chris@384
|
338 out << indent;
|
Chris@384
|
339
|
Chris@384
|
340 bool haveContent = true;
|
Chris@384
|
341 if (m_parameters.empty() && m_configuration.empty()) haveContent = false;
|
Chris@384
|
342
|
Chris@384
|
343 out << QString("<transform id=\"%1\" pluginVersion=\"%2\" program=\"%3\" stepSize=\"%4\" blockSize=\"%5\" windowType=\"%6\" startTime=\"%7\" duration=\"%8\" sampleRate=\"%9\"")
|
Chris@384
|
344 .arg(encodeEntities(m_id))
|
Chris@384
|
345 .arg(encodeEntities(m_pluginVersion))
|
Chris@384
|
346 .arg(encodeEntities(m_program))
|
Chris@384
|
347 .arg(m_stepSize)
|
Chris@384
|
348 .arg(m_blockSize)
|
Chris@384
|
349 .arg(encodeEntities(Window<float>::getNameForType(m_windowType).c_str()))
|
Chris@384
|
350 .arg(encodeEntities(m_startTime.toString().c_str()))
|
Chris@384
|
351 .arg(encodeEntities(m_duration.toString().c_str()))
|
Chris@384
|
352 .arg(m_sampleRate);
|
Chris@384
|
353
|
Chris@384
|
354 if (extraAttributes != "") {
|
Chris@384
|
355 out << " " << extraAttributes;
|
Chris@384
|
356 }
|
Chris@384
|
357
|
Chris@384
|
358 if (haveContent) {
|
Chris@384
|
359
|
Chris@384
|
360 out << ">\n";
|
Chris@384
|
361
|
Chris@384
|
362 for (ParameterMap::const_iterator i = m_parameters.begin();
|
Chris@384
|
363 i != m_parameters.end(); ++i) {
|
Chris@384
|
364 out << indent << " "
|
Chris@384
|
365 << QString("<parameter name=\"%1\" value=\"%2\"/>\n")
|
Chris@384
|
366 .arg(encodeEntities(i->first))
|
Chris@384
|
367 .arg(i->second);
|
Chris@384
|
368 }
|
Chris@384
|
369
|
Chris@384
|
370 for (ConfigurationMap::const_iterator i = m_configuration.begin();
|
Chris@384
|
371 i != m_configuration.end(); ++i) {
|
Chris@384
|
372 out << indent << " "
|
Chris@384
|
373 << QString("<configuration name=\"%1\" value=\"%2\"/>\n")
|
Chris@384
|
374 .arg(encodeEntities(i->first))
|
Chris@384
|
375 .arg(encodeEntities(i->second));
|
Chris@384
|
376 }
|
Chris@384
|
377
|
Chris@384
|
378 out << indent << "</transform>\n";
|
Chris@384
|
379
|
Chris@384
|
380 } else {
|
Chris@384
|
381
|
Chris@384
|
382 out << "/>\n";
|
Chris@384
|
383 }
|
Chris@384
|
384 }
|
Chris@384
|
385
|
Chris@384
|
386 void
|
Chris@384
|
387 Transform::setFromXmlAttributes(const QXmlAttributes &attrs)
|
Chris@384
|
388 {
|
Chris@384
|
389 if (attrs.value("id") != "") {
|
Chris@384
|
390 setIdentifier(attrs.value("id"));
|
Chris@384
|
391 }
|
Chris@384
|
392
|
Chris@384
|
393 if (attrs.value("pluginVersion") != "") {
|
Chris@384
|
394 setPluginVersion(attrs.value("pluginVersion"));
|
Chris@384
|
395 }
|
Chris@384
|
396
|
Chris@384
|
397 if (attrs.value("program") != "") {
|
Chris@384
|
398 setProgram(attrs.value("program"));
|
Chris@384
|
399 }
|
Chris@384
|
400
|
Chris@384
|
401 if (attrs.value("stepSize") != "") {
|
Chris@384
|
402 setStepSize(attrs.value("stepSize").toInt());
|
Chris@384
|
403 }
|
Chris@384
|
404
|
Chris@384
|
405 if (attrs.value("blockSize") != "") {
|
Chris@384
|
406 setBlockSize(attrs.value("blockSize").toInt());
|
Chris@384
|
407 }
|
Chris@384
|
408
|
Chris@384
|
409 if (attrs.value("windowType") != "") {
|
Chris@384
|
410 setWindowType(Window<float>::getTypeForName
|
Chris@384
|
411 (attrs.value("windowType").toStdString()));
|
Chris@384
|
412 }
|
Chris@384
|
413
|
Chris@384
|
414 if (attrs.value("startTime") != "") {
|
Chris@384
|
415 setStartTime(RealTime::fromString(attrs.value("startTime").toStdString()));
|
Chris@384
|
416 }
|
Chris@384
|
417
|
Chris@384
|
418 if (attrs.value("duration") != "") {
|
Chris@384
|
419 setStartTime(RealTime::fromString(attrs.value("duration").toStdString()));
|
Chris@384
|
420 }
|
Chris@384
|
421
|
Chris@384
|
422 if (attrs.value("sampleRate") != "") {
|
Chris@384
|
423 setSampleRate(attrs.value("sampleRate").toFloat());
|
Chris@384
|
424 }
|
Chris@384
|
425 }
|
Chris@384
|
426
|