annotate transform/Transform.cpp @ 558:1d7ebc05157e

* Some fairly simplistic code to set up layer type properties based on RDF data about feature types (both when running transforms and when importing features from RDF files).
author Chris Cannam
date Thu, 12 Feb 2009 15:26:43 +0000
parents 1b8c748fd7ea
children ecbd99d5d2c4
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@350 114 return
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@350 126 }
Chris@350 127
Chris@400 128 bool
Chris@400 129 Transform::operator<(const Transform &t) const
Chris@400 130 {
Chris@400 131 if (m_id != t.m_id) {
Chris@400 132 return m_id < t.m_id;
Chris@400 133 }
Chris@400 134 if (m_parameters != t.m_parameters) {
Chris@400 135 return mapLessThan<QString, float>(m_parameters, t.m_parameters);
Chris@400 136 }
Chris@400 137 if (m_configuration != t.m_configuration) {
Chris@400 138 return mapLessThan<QString, QString>(m_configuration, t.m_configuration);
Chris@400 139 }
Chris@400 140 if (m_program != t.m_program) {
Chris@400 141 return m_program < t.m_program;
Chris@400 142 }
Chris@508 143 if (m_summaryType != t.m_summaryType) {
Chris@508 144 return int(m_summaryType) < int(t.m_summaryType);
Chris@508 145 }
Chris@400 146 if (m_stepSize != t.m_stepSize) {
Chris@400 147 return m_stepSize < t.m_stepSize;
Chris@400 148 }
Chris@400 149 if (m_blockSize != t.m_blockSize) {
Chris@400 150 return m_blockSize < t.m_blockSize;
Chris@400 151 }
Chris@400 152 if (m_windowType != t.m_windowType) {
Chris@400 153 return m_windowType < t.m_windowType;
Chris@400 154 }
Chris@400 155 if (m_startTime != t.m_startTime) {
Chris@400 156 return m_startTime < t.m_startTime;
Chris@400 157 }
Chris@400 158 if (m_duration != t.m_duration) {
Chris@400 159 return m_duration < t.m_duration;
Chris@400 160 }
Chris@400 161 if (m_sampleRate != t.m_sampleRate) {
Chris@400 162 return m_sampleRate < t.m_sampleRate;
Chris@400 163 }
Chris@400 164 return false;
Chris@400 165 }
Chris@400 166
Chris@350 167 void
Chris@350 168 Transform::setIdentifier(TransformId id)
Chris@350 169 {
Chris@350 170 m_id = id;
Chris@350 171 }
Chris@350 172
Chris@350 173 TransformId
Chris@350 174 Transform::getIdentifier() const
Chris@350 175 {
Chris@350 176 return m_id;
Chris@350 177 }
Chris@350 178
Chris@328 179 QString
Chris@328 180 Transform::createIdentifier(QString type, QString soName, QString label,
Chris@328 181 QString output)
Chris@328 182 {
Chris@328 183 QString pluginId = PluginIdentifier::createIdentifier(type, soName, label);
Chris@328 184 return pluginId + ":" + output;
Chris@328 185 }
Chris@328 186
Chris@328 187 void
Chris@328 188 Transform::parseIdentifier(QString identifier,
Chris@328 189 QString &type, QString &soName,
Chris@328 190 QString &label, QString &output)
Chris@328 191 {
Chris@328 192 output = identifier.section(':', 3);
Chris@328 193 PluginIdentifier::parseIdentifier(identifier.section(':', 0, 2),
Chris@328 194 type, soName, label);
Chris@328 195 }
Chris@328 196
Chris@328 197 Transform::Type
Chris@328 198 Transform::getType() const
Chris@328 199 {
Chris@332 200 if (FeatureExtractionPluginFactory::instanceFor(getPluginIdentifier())) {
Chris@332 201 return FeatureExtraction;
Chris@332 202 } else {
Chris@332 203 // We don't have an unknown/invalid return value, so always
Chris@332 204 // return this
Chris@332 205 return RealTimeEffect;
Chris@332 206 }
Chris@328 207 }
Chris@328 208
Chris@328 209 QString
Chris@328 210 Transform::getPluginIdentifier() const
Chris@328 211 {
Chris@328 212 return m_id.section(':', 0, 2);
Chris@328 213 }
Chris@328 214
Chris@328 215 QString
Chris@328 216 Transform::getOutput() const
Chris@328 217 {
Chris@328 218 return m_id.section(':', 3);
Chris@328 219 }
Chris@328 220
Chris@353 221 void
Chris@353 222 Transform::setPluginIdentifier(QString pluginIdentifier)
Chris@353 223 {
Chris@353 224 m_id = pluginIdentifier + ':' + getOutput();
Chris@353 225 }
Chris@353 226
Chris@353 227 void
Chris@353 228 Transform::setOutput(QString output)
Chris@353 229 {
Chris@353 230 m_id = getPluginIdentifier() + ':' + output;
Chris@353 231 }
Chris@353 232
Chris@353 233 TransformId
Chris@353 234 Transform::getIdentifierForPluginOutput(QString pluginIdentifier,
Chris@353 235 QString output)
Chris@353 236 {
Chris@353 237 return pluginIdentifier + ':' + output;
Chris@353 238 }
Chris@353 239
Chris@350 240 const Transform::ParameterMap &
Chris@350 241 Transform::getParameters() const
Chris@350 242 {
Chris@350 243 return m_parameters;
Chris@350 244 }
Chris@350 245
Chris@328 246 void
Chris@350 247 Transform::setParameters(const ParameterMap &pm)
Chris@328 248 {
Chris@350 249 m_parameters = pm;
Chris@350 250 }
Chris@350 251
Chris@350 252 void
Chris@350 253 Transform::setParameter(QString name, float value)
Chris@350 254 {
Chris@403 255 // std::cerr << "Transform::setParameter(" << name.toStdString()
Chris@403 256 // << ") -> " << value << std::endl;
Chris@350 257 m_parameters[name] = value;
Chris@350 258 }
Chris@350 259
Chris@350 260 const Transform::ConfigurationMap &
Chris@350 261 Transform::getConfiguration() const
Chris@350 262 {
Chris@350 263 return m_configuration;
Chris@350 264 }
Chris@350 265
Chris@350 266 void
Chris@350 267 Transform::setConfiguration(const ConfigurationMap &cm)
Chris@350 268 {
Chris@350 269 m_configuration = cm;
Chris@350 270 }
Chris@350 271
Chris@350 272 void
Chris@350 273 Transform::setConfigurationValue(QString name, QString value)
Chris@350 274 {
Chris@350 275 std::cerr << "Transform::setConfigurationValue(" << name.toStdString()
Chris@350 276 << ") -> " << value.toStdString() << std::endl;
Chris@350 277 m_configuration[name] = value;
Chris@350 278 }
Chris@350 279
Chris@350 280 QString
Chris@366 281 Transform::getPluginVersion() const
Chris@366 282 {
Chris@366 283 return m_pluginVersion;
Chris@366 284 }
Chris@366 285
Chris@366 286 void
Chris@366 287 Transform::setPluginVersion(QString version)
Chris@366 288 {
Chris@366 289 m_pluginVersion = version;
Chris@366 290 }
Chris@366 291
Chris@366 292 QString
Chris@350 293 Transform::getProgram() const
Chris@350 294 {
Chris@350 295 return m_program;
Chris@350 296 }
Chris@350 297
Chris@350 298 void
Chris@350 299 Transform::setProgram(QString program)
Chris@350 300 {
Chris@350 301 m_program = program;
Chris@350 302 }
Chris@350 303
Chris@508 304 Transform::SummaryType
Chris@508 305 Transform::getSummaryType() const
Chris@508 306 {
Chris@508 307 return m_summaryType;
Chris@508 308 }
Chris@508 309
Chris@508 310 void
Chris@508 311 Transform::setSummaryType(SummaryType type)
Chris@508 312 {
Chris@508 313 m_summaryType = type;
Chris@508 314 }
Chris@328 315
Chris@350 316 size_t
Chris@350 317 Transform::getStepSize() const
Chris@350 318 {
Chris@350 319 return m_stepSize;
Chris@328 320 }
Chris@350 321
Chris@350 322 void
Chris@350 323 Transform::setStepSize(size_t s)
Chris@350 324 {
Chris@350 325 m_stepSize = s;
Chris@350 326 }
Chris@350 327
Chris@350 328 size_t
Chris@350 329 Transform::getBlockSize() const
Chris@350 330 {
Chris@350 331 return m_blockSize;
Chris@350 332 }
Chris@350 333
Chris@350 334 void
Chris@350 335 Transform::setBlockSize(size_t s)
Chris@350 336 {
Chris@350 337 m_blockSize = s;
Chris@350 338 }
Chris@350 339
Chris@350 340 WindowType
Chris@350 341 Transform::getWindowType() const
Chris@350 342 {
Chris@350 343 return m_windowType;
Chris@350 344 }
Chris@350 345
Chris@350 346 void
Chris@350 347 Transform::setWindowType(WindowType type)
Chris@350 348 {
Chris@350 349 m_windowType = type;
Chris@350 350 }
Chris@350 351
Chris@350 352 RealTime
Chris@350 353 Transform::getStartTime() const
Chris@350 354 {
Chris@350 355 return m_startTime;
Chris@350 356 }
Chris@350 357
Chris@350 358 void
Chris@350 359 Transform::setStartTime(RealTime t)
Chris@350 360 {
Chris@350 361 m_startTime = t;
Chris@350 362 }
Chris@350 363
Chris@350 364 RealTime
Chris@350 365 Transform::getDuration() const
Chris@350 366 {
Chris@350 367 return m_duration;
Chris@350 368 }
Chris@350 369
Chris@350 370 void
Chris@350 371 Transform::setDuration(RealTime d)
Chris@350 372 {
Chris@350 373 m_duration = d;
Chris@350 374 }
Chris@350 375
Chris@350 376 float
Chris@350 377 Transform::getSampleRate() const
Chris@350 378 {
Chris@350 379 return m_sampleRate;
Chris@350 380 }
Chris@350 381
Chris@350 382 void
Chris@350 383 Transform::setSampleRate(float rate)
Chris@350 384 {
Chris@350 385 m_sampleRate = rate;
Chris@350 386 }
Chris@350 387
Chris@350 388 void
Chris@350 389 Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const
Chris@350 390 {
Chris@350 391 out << indent;
Chris@350 392
Chris@350 393 bool haveContent = true;
Chris@350 394 if (m_parameters.empty() && m_configuration.empty()) haveContent = false;
Chris@350 395
Chris@396 396 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 397 .arg(encodeEntities(m_id))
Chris@366 398 .arg(encodeEntities(m_pluginVersion))
Chris@350 399 .arg(encodeEntities(m_program))
Chris@350 400 .arg(m_stepSize)
Chris@350 401 .arg(m_blockSize)
Chris@350 402 .arg(encodeEntities(Window<float>::getNameForType(m_windowType).c_str()))
Chris@350 403 .arg(encodeEntities(m_startTime.toString().c_str()))
Chris@350 404 .arg(encodeEntities(m_duration.toString().c_str()))
Chris@366 405 .arg(m_sampleRate);
Chris@366 406
Chris@508 407 if (m_summaryType != NoSummary) {
Chris@508 408 out << QString("\n summaryType=\"%1\"").arg(summaryTypeToString(m_summaryType));
Chris@508 409 }
Chris@508 410
Chris@366 411 if (extraAttributes != "") {
Chris@366 412 out << " " << extraAttributes;
Chris@366 413 }
Chris@350 414
Chris@350 415 if (haveContent) {
Chris@350 416
Chris@350 417 out << ">\n";
Chris@350 418
Chris@350 419 for (ParameterMap::const_iterator i = m_parameters.begin();
Chris@350 420 i != m_parameters.end(); ++i) {
Chris@350 421 out << indent << " "
Chris@350 422 << QString("<parameter name=\"%1\" value=\"%2\"/>\n")
Chris@350 423 .arg(encodeEntities(i->first))
Chris@350 424 .arg(i->second);
Chris@350 425 }
Chris@350 426
Chris@350 427 for (ConfigurationMap::const_iterator i = m_configuration.begin();
Chris@350 428 i != m_configuration.end(); ++i) {
Chris@350 429 out << indent << " "
Chris@350 430 << QString("<configuration name=\"%1\" value=\"%2\"/>\n")
Chris@350 431 .arg(encodeEntities(i->first))
Chris@350 432 .arg(encodeEntities(i->second));
Chris@350 433 }
Chris@350 434
Chris@350 435 out << indent << "</transform>\n";
Chris@350 436
Chris@350 437 } else {
Chris@350 438
Chris@350 439 out << "/>\n";
Chris@350 440 }
Chris@350 441 }
Chris@350 442
Chris@508 443 Transform::SummaryType
Chris@508 444 Transform::stringToSummaryType(QString str)
Chris@508 445 {
Chris@508 446 str = str.toLower();
Chris@508 447 if (str == "minimum" || str == "min") return Minimum;
Chris@508 448 if (str == "maximum" || str == "max") return Maximum;
Chris@508 449 if (str == "mean") return Mean;
Chris@508 450 if (str == "median") return Median;
Chris@508 451 if (str == "mode") return Mode;
Chris@508 452 if (str == "sum") return Sum;
Chris@508 453 if (str == "variance") return Variance;
Chris@508 454 if (str == "standard-deviation" || str == "standardDeviation" ||
Chris@508 455 str == "standard deviation" || str == "sd") return StandardDeviation;
Chris@508 456 if (str == "count") return Count;
Chris@508 457 if (str == "") return NoSummary;
Chris@508 458 std::cerr << "Transform::stringToSummaryType: unknown summary type \""
Chris@508 459 << str.toStdString() << "\"" << std::endl;
Chris@508 460 return NoSummary;
Chris@508 461 }
Chris@508 462
Chris@508 463 QString
Chris@508 464 Transform::summaryTypeToString(SummaryType type)
Chris@508 465 {
Chris@508 466 switch (type) {
Chris@508 467 case Minimum: return "min";
Chris@508 468 case Maximum: return "max";
Chris@508 469 case Mean: return "mean";
Chris@508 470 case Median: return "median";
Chris@508 471 case Mode: return "mode";
Chris@508 472 case Sum: return "sum";
Chris@508 473 case Variance: return "variance";
Chris@508 474 case StandardDeviation: return "sd";
Chris@508 475 case Count: return "count";
Chris@508 476 case NoSummary: return "";
Chris@508 477 default:
Chris@508 478 std::cerr << "Transform::summaryTypeToString: unexpected summary type "
Chris@508 479 << int(type) << std::endl;
Chris@508 480 return "";
Chris@508 481 }
Chris@508 482 }
Chris@508 483
Chris@350 484 void
Chris@350 485 Transform::setFromXmlAttributes(const QXmlAttributes &attrs)
Chris@350 486 {
Chris@350 487 if (attrs.value("id") != "") {
Chris@350 488 setIdentifier(attrs.value("id"));
Chris@350 489 }
Chris@350 490
Chris@366 491 if (attrs.value("pluginVersion") != "") {
Chris@366 492 setPluginVersion(attrs.value("pluginVersion"));
Chris@366 493 }
Chris@366 494
Chris@350 495 if (attrs.value("program") != "") {
Chris@350 496 setProgram(attrs.value("program"));
Chris@350 497 }
Chris@350 498
Chris@350 499 if (attrs.value("stepSize") != "") {
Chris@350 500 setStepSize(attrs.value("stepSize").toInt());
Chris@350 501 }
Chris@350 502
Chris@350 503 if (attrs.value("blockSize") != "") {
Chris@350 504 setBlockSize(attrs.value("blockSize").toInt());
Chris@350 505 }
Chris@350 506
Chris@350 507 if (attrs.value("windowType") != "") {
Chris@350 508 setWindowType(Window<float>::getTypeForName
Chris@350 509 (attrs.value("windowType").toStdString()));
Chris@350 510 }
Chris@350 511
Chris@350 512 if (attrs.value("startTime") != "") {
Chris@350 513 setStartTime(RealTime::fromString(attrs.value("startTime").toStdString()));
Chris@350 514 }
Chris@350 515
Chris@350 516 if (attrs.value("duration") != "") {
Chris@350 517 setStartTime(RealTime::fromString(attrs.value("duration").toStdString()));
Chris@350 518 }
Chris@350 519
Chris@350 520 if (attrs.value("sampleRate") != "") {
Chris@350 521 setSampleRate(attrs.value("sampleRate").toFloat());
Chris@350 522 }
Chris@508 523
Chris@508 524 if (attrs.value("summaryType") != "") {
Chris@508 525 setSummaryType(stringToSummaryType(attrs.value("summaryType")));
Chris@508 526 }
Chris@350 527 }
Chris@350 528