annotate transform/Transform.cpp @ 661:a4faa1840384

* If a FileSource URL won't convert at all in strict mode, try again in tolerant mode (necessary for e.g. filenames with square brackets in them)
author Chris Cannam
date Tue, 19 Oct 2010 21:47:55 +0100
parents ecbd99d5d2c4
children b4a8d8221eaf
rev   line source
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@508 34 m_summaryType(NoSummary),
Chris@328 35 m_stepSize(0),
Chris@328 36 m_blockSize(0),
Chris@328 37 m_windowType(HanningWindow),
Chris@328 38 m_sampleRate(0)
Chris@320 39 {
Chris@320 40 }
Chris@320 41
Chris@350 42 Transform::Transform(QString xml) :
Chris@508 43 m_summaryType(NoSummary),
Chris@350 44 m_stepSize(0),
Chris@350 45 m_blockSize(0),
Chris@350 46 m_windowType(HanningWindow),
Chris@350 47 m_sampleRate(0)
Chris@350 48 {
Chris@350 49 QDomDocument doc;
Chris@350 50
Chris@350 51 QString error;
Chris@350 52 int errorLine;
Chris@350 53 int errorColumn;
Chris@350 54
Chris@350 55 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) {
Chris@350 56 std::cerr << "Transform::Transform: Error in parsing XML: "
Chris@350 57 << error.toStdString() << " at line " << errorLine
Chris@350 58 << ", column " << errorColumn << std::endl;
Chris@350 59 std::cerr << "Input follows:" << std::endl;
Chris@350 60 std::cerr << xml.toStdString() << std::endl;
Chris@350 61 std::cerr << "Input ends." << std::endl;
Chris@350 62 return;
Chris@350 63 }
Chris@350 64
Chris@350 65 QDomElement transformElt = doc.firstChildElement("transform");
Chris@350 66 QDomNamedNodeMap attrNodes = transformElt.attributes();
Chris@350 67 QXmlAttributes attrs;
Chris@350 68
Chris@350 69 for (unsigned int i = 0; i < attrNodes.length(); ++i) {
Chris@350 70 QDomAttr attr = attrNodes.item(i).toAttr();
Chris@350 71 if (!attr.isNull()) attrs.append(attr.name(), "", "", attr.value());
Chris@350 72 }
Chris@350 73
Chris@350 74 setFromXmlAttributes(attrs);
Chris@350 75
Chris@350 76 for (QDomElement paramElt = transformElt.firstChildElement("parameter");
Chris@350 77 !paramElt.isNull();
Chris@350 78 paramElt = paramElt.nextSiblingElement("parameter")) {
Chris@350 79
Chris@350 80 QDomNamedNodeMap paramAttrs = paramElt.attributes();
Chris@350 81
Chris@350 82 QDomAttr nameAttr = paramAttrs.namedItem("name").toAttr();
Chris@350 83 if (nameAttr.isNull() || nameAttr.value() == "") continue;
Chris@350 84
Chris@350 85 QDomAttr valueAttr = paramAttrs.namedItem("value").toAttr();
Chris@350 86 if (valueAttr.isNull() || valueAttr.value() == "") continue;
Chris@350 87
Chris@350 88 setParameter(nameAttr.value(), valueAttr.value().toFloat());
Chris@350 89 }
Chris@350 90
Chris@350 91 for (QDomElement configElt = transformElt.firstChildElement("configuration");
Chris@350 92 !configElt.isNull();
Chris@350 93 configElt = configElt.nextSiblingElement("configuration")) {
Chris@350 94
Chris@350 95 QDomNamedNodeMap configAttrs = configElt.attributes();
Chris@350 96
Chris@350 97 QDomAttr nameAttr = configAttrs.namedItem("name").toAttr();
Chris@350 98 if (nameAttr.isNull() || nameAttr.value() == "") continue;
Chris@350 99
Chris@350 100 QDomAttr valueAttr = configAttrs.namedItem("value").toAttr();
Chris@350 101 if (valueAttr.isNull() || valueAttr.value() == "") continue;
Chris@350 102
Chris@350 103 setConfigurationValue(nameAttr.value(), valueAttr.value());
Chris@350 104 }
Chris@350 105 }
Chris@350 106
Chris@320 107 Transform::~Transform()
Chris@320 108 {
Chris@320 109 }
Chris@320 110
Chris@350 111 bool
Chris@400 112 Transform::operator==(const Transform &t) const
Chris@350 113 {
Chris@583 114 bool identical =
Chris@350 115 m_id == t.m_id &&
Chris@350 116 m_parameters == t.m_parameters &&
Chris@350 117 m_configuration == t.m_configuration &&
Chris@350 118 m_program == t.m_program &&
Chris@508 119 m_summaryType == t.m_summaryType &&
Chris@350 120 m_stepSize == t.m_stepSize &&
Chris@350 121 m_blockSize == t.m_blockSize &&
Chris@350 122 m_windowType == t.m_windowType &&
Chris@350 123 m_startTime == t.m_startTime &&
Chris@350 124 m_duration == t.m_duration &&
Chris@350 125 m_sampleRate == t.m_sampleRate;
Chris@583 126 /*
Chris@583 127 std::cerr << "Transform::operator==: identical = " << identical << std::endl;
Chris@583 128 std::cerr << "A = " << std::endl;
Chris@583 129 std::cerr << toXmlString().toStdString() << std::endl;
Chris@583 130 std::cerr << "B = " << std::endl;
Chris@583 131 std::cerr << t.toXmlString().toStdString() << std::endl;
Chris@583 132 */
Chris@583 133 return identical;
Chris@350 134 }
Chris@350 135
Chris@400 136 bool
Chris@400 137 Transform::operator<(const Transform &t) const
Chris@400 138 {
Chris@400 139 if (m_id != t.m_id) {
Chris@400 140 return m_id < t.m_id;
Chris@400 141 }
Chris@400 142 if (m_parameters != t.m_parameters) {
Chris@400 143 return mapLessThan<QString, float>(m_parameters, t.m_parameters);
Chris@400 144 }
Chris@400 145 if (m_configuration != t.m_configuration) {
Chris@400 146 return mapLessThan<QString, QString>(m_configuration, t.m_configuration);
Chris@400 147 }
Chris@400 148 if (m_program != t.m_program) {
Chris@400 149 return m_program < t.m_program;
Chris@400 150 }
Chris@508 151 if (m_summaryType != t.m_summaryType) {
Chris@508 152 return int(m_summaryType) < int(t.m_summaryType);
Chris@508 153 }
Chris@400 154 if (m_stepSize != t.m_stepSize) {
Chris@400 155 return m_stepSize < t.m_stepSize;
Chris@400 156 }
Chris@400 157 if (m_blockSize != t.m_blockSize) {
Chris@400 158 return m_blockSize < t.m_blockSize;
Chris@400 159 }
Chris@400 160 if (m_windowType != t.m_windowType) {
Chris@400 161 return m_windowType < t.m_windowType;
Chris@400 162 }
Chris@400 163 if (m_startTime != t.m_startTime) {
Chris@400 164 return m_startTime < t.m_startTime;
Chris@400 165 }
Chris@400 166 if (m_duration != t.m_duration) {
Chris@400 167 return m_duration < t.m_duration;
Chris@400 168 }
Chris@400 169 if (m_sampleRate != t.m_sampleRate) {
Chris@400 170 return m_sampleRate < t.m_sampleRate;
Chris@400 171 }
Chris@400 172 return false;
Chris@400 173 }
Chris@400 174
Chris@350 175 void
Chris@350 176 Transform::setIdentifier(TransformId id)
Chris@350 177 {
Chris@350 178 m_id = id;
Chris@350 179 }
Chris@350 180
Chris@350 181 TransformId
Chris@350 182 Transform::getIdentifier() const
Chris@350 183 {
Chris@350 184 return m_id;
Chris@350 185 }
Chris@350 186
Chris@328 187 QString
Chris@328 188 Transform::createIdentifier(QString type, QString soName, QString label,
Chris@328 189 QString output)
Chris@328 190 {
Chris@328 191 QString pluginId = PluginIdentifier::createIdentifier(type, soName, label);
Chris@328 192 return pluginId + ":" + output;
Chris@328 193 }
Chris@328 194
Chris@328 195 void
Chris@328 196 Transform::parseIdentifier(QString identifier,
Chris@328 197 QString &type, QString &soName,
Chris@328 198 QString &label, QString &output)
Chris@328 199 {
Chris@328 200 output = identifier.section(':', 3);
Chris@328 201 PluginIdentifier::parseIdentifier(identifier.section(':', 0, 2),
Chris@328 202 type, soName, label);
Chris@328 203 }
Chris@328 204
Chris@328 205 Transform::Type
Chris@328 206 Transform::getType() const
Chris@328 207 {
Chris@332 208 if (FeatureExtractionPluginFactory::instanceFor(getPluginIdentifier())) {
Chris@332 209 return FeatureExtraction;
Chris@332 210 } else {
Chris@332 211 // We don't have an unknown/invalid return value, so always
Chris@332 212 // return this
Chris@332 213 return RealTimeEffect;
Chris@332 214 }
Chris@328 215 }
Chris@328 216
Chris@328 217 QString
Chris@328 218 Transform::getPluginIdentifier() const
Chris@328 219 {
Chris@328 220 return m_id.section(':', 0, 2);
Chris@328 221 }
Chris@328 222
Chris@328 223 QString
Chris@328 224 Transform::getOutput() const
Chris@328 225 {
Chris@328 226 return m_id.section(':', 3);
Chris@328 227 }
Chris@328 228
Chris@353 229 void
Chris@353 230 Transform::setPluginIdentifier(QString pluginIdentifier)
Chris@353 231 {
Chris@353 232 m_id = pluginIdentifier + ':' + getOutput();
Chris@353 233 }
Chris@353 234
Chris@353 235 void
Chris@353 236 Transform::setOutput(QString output)
Chris@353 237 {
Chris@353 238 m_id = getPluginIdentifier() + ':' + output;
Chris@353 239 }
Chris@353 240
Chris@353 241 TransformId
Chris@353 242 Transform::getIdentifierForPluginOutput(QString pluginIdentifier,
Chris@353 243 QString output)
Chris@353 244 {
Chris@353 245 return pluginIdentifier + ':' + output;
Chris@353 246 }
Chris@353 247
Chris@350 248 const Transform::ParameterMap &
Chris@350 249 Transform::getParameters() const
Chris@350 250 {
Chris@350 251 return m_parameters;
Chris@350 252 }
Chris@350 253
Chris@328 254 void
Chris@350 255 Transform::setParameters(const ParameterMap &pm)
Chris@328 256 {
Chris@350 257 m_parameters = pm;
Chris@350 258 }
Chris@350 259
Chris@350 260 void
Chris@350 261 Transform::setParameter(QString name, float value)
Chris@350 262 {
Chris@403 263 // std::cerr << "Transform::setParameter(" << name.toStdString()
Chris@403 264 // << ") -> " << value << std::endl;
Chris@350 265 m_parameters[name] = value;
Chris@350 266 }
Chris@350 267
Chris@350 268 const Transform::ConfigurationMap &
Chris@350 269 Transform::getConfiguration() const
Chris@350 270 {
Chris@350 271 return m_configuration;
Chris@350 272 }
Chris@350 273
Chris@350 274 void
Chris@350 275 Transform::setConfiguration(const ConfigurationMap &cm)
Chris@350 276 {
Chris@350 277 m_configuration = cm;
Chris@350 278 }
Chris@350 279
Chris@350 280 void
Chris@350 281 Transform::setConfigurationValue(QString name, QString value)
Chris@350 282 {
Chris@350 283 std::cerr << "Transform::setConfigurationValue(" << name.toStdString()
Chris@350 284 << ") -> " << value.toStdString() << std::endl;
Chris@350 285 m_configuration[name] = value;
Chris@350 286 }
Chris@350 287
Chris@350 288 QString
Chris@366 289 Transform::getPluginVersion() const
Chris@366 290 {
Chris@366 291 return m_pluginVersion;
Chris@366 292 }
Chris@366 293
Chris@366 294 void
Chris@366 295 Transform::setPluginVersion(QString version)
Chris@366 296 {
Chris@366 297 m_pluginVersion = version;
Chris@366 298 }
Chris@366 299
Chris@366 300 QString
Chris@350 301 Transform::getProgram() const
Chris@350 302 {
Chris@350 303 return m_program;
Chris@350 304 }
Chris@350 305
Chris@350 306 void
Chris@350 307 Transform::setProgram(QString program)
Chris@350 308 {
Chris@350 309 m_program = program;
Chris@350 310 }
Chris@350 311
Chris@508 312 Transform::SummaryType
Chris@508 313 Transform::getSummaryType() const
Chris@508 314 {
Chris@508 315 return m_summaryType;
Chris@508 316 }
Chris@508 317
Chris@508 318 void
Chris@508 319 Transform::setSummaryType(SummaryType type)
Chris@508 320 {
Chris@508 321 m_summaryType = type;
Chris@508 322 }
Chris@328 323
Chris@350 324 size_t
Chris@350 325 Transform::getStepSize() const
Chris@350 326 {
Chris@350 327 return m_stepSize;
Chris@328 328 }
Chris@350 329
Chris@350 330 void
Chris@350 331 Transform::setStepSize(size_t s)
Chris@350 332 {
Chris@350 333 m_stepSize = s;
Chris@350 334 }
Chris@350 335
Chris@350 336 size_t
Chris@350 337 Transform::getBlockSize() const
Chris@350 338 {
Chris@350 339 return m_blockSize;
Chris@350 340 }
Chris@350 341
Chris@350 342 void
Chris@350 343 Transform::setBlockSize(size_t s)
Chris@350 344 {
Chris@350 345 m_blockSize = s;
Chris@350 346 }
Chris@350 347
Chris@350 348 WindowType
Chris@350 349 Transform::getWindowType() const
Chris@350 350 {
Chris@350 351 return m_windowType;
Chris@350 352 }
Chris@350 353
Chris@350 354 void
Chris@350 355 Transform::setWindowType(WindowType type)
Chris@350 356 {
Chris@350 357 m_windowType = type;
Chris@350 358 }
Chris@350 359
Chris@350 360 RealTime
Chris@350 361 Transform::getStartTime() const
Chris@350 362 {
Chris@350 363 return m_startTime;
Chris@350 364 }
Chris@350 365
Chris@350 366 void
Chris@350 367 Transform::setStartTime(RealTime t)
Chris@350 368 {
Chris@350 369 m_startTime = t;
Chris@350 370 }
Chris@350 371
Chris@350 372 RealTime
Chris@350 373 Transform::getDuration() const
Chris@350 374 {
Chris@350 375 return m_duration;
Chris@350 376 }
Chris@350 377
Chris@350 378 void
Chris@350 379 Transform::setDuration(RealTime d)
Chris@350 380 {
Chris@350 381 m_duration = d;
Chris@350 382 }
Chris@350 383
Chris@350 384 float
Chris@350 385 Transform::getSampleRate() const
Chris@350 386 {
Chris@350 387 return m_sampleRate;
Chris@350 388 }
Chris@350 389
Chris@350 390 void
Chris@350 391 Transform::setSampleRate(float rate)
Chris@350 392 {
Chris@350 393 m_sampleRate = rate;
Chris@350 394 }
Chris@350 395
Chris@350 396 void
Chris@350 397 Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const
Chris@350 398 {
Chris@350 399 out << indent;
Chris@350 400
Chris@350 401 bool haveContent = true;
Chris@350 402 if (m_parameters.empty() && m_configuration.empty()) haveContent = false;
Chris@350 403
Chris@396 404 out << QString("<transform\n id=\"%1\"\n pluginVersion=\"%2\"\n program=\"%3\"\n stepSize=\"%4\"\n blockSize=\"%5\"\n windowType=\"%6\"\n startTime=\"%7\"\n duration=\"%8\"\n sampleRate=\"%9\"")
Chris@350 405 .arg(encodeEntities(m_id))
Chris@366 406 .arg(encodeEntities(m_pluginVersion))
Chris@350 407 .arg(encodeEntities(m_program))
Chris@350 408 .arg(m_stepSize)
Chris@350 409 .arg(m_blockSize)
Chris@350 410 .arg(encodeEntities(Window<float>::getNameForType(m_windowType).c_str()))
Chris@350 411 .arg(encodeEntities(m_startTime.toString().c_str()))
Chris@350 412 .arg(encodeEntities(m_duration.toString().c_str()))
Chris@366 413 .arg(m_sampleRate);
Chris@366 414
Chris@508 415 if (m_summaryType != NoSummary) {
Chris@508 416 out << QString("\n summaryType=\"%1\"").arg(summaryTypeToString(m_summaryType));
Chris@508 417 }
Chris@508 418
Chris@366 419 if (extraAttributes != "") {
Chris@366 420 out << " " << extraAttributes;
Chris@366 421 }
Chris@350 422
Chris@350 423 if (haveContent) {
Chris@350 424
Chris@350 425 out << ">\n";
Chris@350 426
Chris@350 427 for (ParameterMap::const_iterator i = m_parameters.begin();
Chris@350 428 i != m_parameters.end(); ++i) {
Chris@350 429 out << indent << " "
Chris@350 430 << QString("<parameter name=\"%1\" value=\"%2\"/>\n")
Chris@350 431 .arg(encodeEntities(i->first))
Chris@350 432 .arg(i->second);
Chris@350 433 }
Chris@350 434
Chris@350 435 for (ConfigurationMap::const_iterator i = m_configuration.begin();
Chris@350 436 i != m_configuration.end(); ++i) {
Chris@350 437 out << indent << " "
Chris@350 438 << QString("<configuration name=\"%1\" value=\"%2\"/>\n")
Chris@350 439 .arg(encodeEntities(i->first))
Chris@350 440 .arg(encodeEntities(i->second));
Chris@350 441 }
Chris@350 442
Chris@350 443 out << indent << "</transform>\n";
Chris@350 444
Chris@350 445 } else {
Chris@350 446
Chris@350 447 out << "/>\n";
Chris@350 448 }
Chris@350 449 }
Chris@350 450
Chris@508 451 Transform::SummaryType
Chris@508 452 Transform::stringToSummaryType(QString str)
Chris@508 453 {
Chris@508 454 str = str.toLower();
Chris@508 455 if (str == "minimum" || str == "min") return Minimum;
Chris@508 456 if (str == "maximum" || str == "max") return Maximum;
Chris@508 457 if (str == "mean") return Mean;
Chris@508 458 if (str == "median") return Median;
Chris@508 459 if (str == "mode") return Mode;
Chris@508 460 if (str == "sum") return Sum;
Chris@508 461 if (str == "variance") return Variance;
Chris@508 462 if (str == "standard-deviation" || str == "standardDeviation" ||
Chris@508 463 str == "standard deviation" || str == "sd") return StandardDeviation;
Chris@508 464 if (str == "count") return Count;
Chris@508 465 if (str == "") return NoSummary;
Chris@508 466 std::cerr << "Transform::stringToSummaryType: unknown summary type \""
Chris@508 467 << str.toStdString() << "\"" << std::endl;
Chris@508 468 return NoSummary;
Chris@508 469 }
Chris@508 470
Chris@508 471 QString
Chris@508 472 Transform::summaryTypeToString(SummaryType type)
Chris@508 473 {
Chris@508 474 switch (type) {
Chris@508 475 case Minimum: return "min";
Chris@508 476 case Maximum: return "max";
Chris@508 477 case Mean: return "mean";
Chris@508 478 case Median: return "median";
Chris@508 479 case Mode: return "mode";
Chris@508 480 case Sum: return "sum";
Chris@508 481 case Variance: return "variance";
Chris@508 482 case StandardDeviation: return "sd";
Chris@508 483 case Count: return "count";
Chris@508 484 case NoSummary: return "";
Chris@508 485 default:
Chris@508 486 std::cerr << "Transform::summaryTypeToString: unexpected summary type "
Chris@508 487 << int(type) << std::endl;
Chris@508 488 return "";
Chris@508 489 }
Chris@508 490 }
Chris@508 491
Chris@350 492 void
Chris@350 493 Transform::setFromXmlAttributes(const QXmlAttributes &attrs)
Chris@350 494 {
Chris@350 495 if (attrs.value("id") != "") {
Chris@350 496 setIdentifier(attrs.value("id"));
Chris@350 497 }
Chris@350 498
Chris@366 499 if (attrs.value("pluginVersion") != "") {
Chris@366 500 setPluginVersion(attrs.value("pluginVersion"));
Chris@366 501 }
Chris@366 502
Chris@350 503 if (attrs.value("program") != "") {
Chris@350 504 setProgram(attrs.value("program"));
Chris@350 505 }
Chris@350 506
Chris@350 507 if (attrs.value("stepSize") != "") {
Chris@350 508 setStepSize(attrs.value("stepSize").toInt());
Chris@350 509 }
Chris@350 510
Chris@350 511 if (attrs.value("blockSize") != "") {
Chris@350 512 setBlockSize(attrs.value("blockSize").toInt());
Chris@350 513 }
Chris@350 514
Chris@350 515 if (attrs.value("windowType") != "") {
Chris@350 516 setWindowType(Window<float>::getTypeForName
Chris@350 517 (attrs.value("windowType").toStdString()));
Chris@350 518 }
Chris@350 519
Chris@350 520 if (attrs.value("startTime") != "") {
Chris@350 521 setStartTime(RealTime::fromString(attrs.value("startTime").toStdString()));
Chris@350 522 }
Chris@350 523
Chris@350 524 if (attrs.value("duration") != "") {
Chris@350 525 setStartTime(RealTime::fromString(attrs.value("duration").toStdString()));
Chris@350 526 }
Chris@350 527
Chris@350 528 if (attrs.value("sampleRate") != "") {
Chris@350 529 setSampleRate(attrs.value("sampleRate").toFloat());
Chris@350 530 }
Chris@508 531
Chris@508 532 if (attrs.value("summaryType") != "") {
Chris@508 533 setSummaryType(stringToSummaryType(attrs.value("summaryType")));
Chris@508 534 }
Chris@350 535 }
Chris@350 536