annotate transform/Transform.cpp @ 875:3e6ed8a8577b tonioni

Use a sparse time-value model only for outputs with fixed bin count of 1, not for those with unknown bin count. (Precursor to using more than one model for outputs with unknown bin count)
author Chris Cannam
date Tue, 28 Jan 2014 18:52:22 +0000
parents e802e550a1f2
children 06579b8ffb7b
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@843 56 cerr << "Transform::Transform: Error in parsing XML: "
Chris@686 57 << error << " at line " << errorLine
Chris@843 58 << ", column " << errorColumn << endl;
Chris@843 59 cerr << "Input follows:" << endl;
Chris@843 60 cerr << xml << endl;
Chris@843 61 cerr << "Input ends." << 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@690 127 SVDEBUG << "Transform::operator==: identical = " << identical << endl;
Chris@843 128 cerr << "A = " << endl;
Chris@843 129 cerr << toXmlString() << endl;
Chris@843 130 cerr << "B = " << endl;
Chris@843 131 cerr << t.toXmlString() << 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@690 263 // SVDEBUG << "Transform::setParameter(" << name// << ") -> " << value << endl;
Chris@350 264 m_parameters[name] = value;
Chris@350 265 }
Chris@350 266
Chris@350 267 const Transform::ConfigurationMap &
Chris@350 268 Transform::getConfiguration() const
Chris@350 269 {
Chris@350 270 return m_configuration;
Chris@350 271 }
Chris@350 272
Chris@350 273 void
Chris@350 274 Transform::setConfiguration(const ConfigurationMap &cm)
Chris@350 275 {
Chris@350 276 m_configuration = cm;
Chris@350 277 }
Chris@350 278
Chris@350 279 void
Chris@350 280 Transform::setConfigurationValue(QString name, QString value)
Chris@350 281 {
Chris@690 282 SVDEBUG << "Transform::setConfigurationValue(" << name << ") -> " << value << endl;
Chris@350 283 m_configuration[name] = value;
Chris@350 284 }
Chris@350 285
Chris@350 286 QString
Chris@366 287 Transform::getPluginVersion() const
Chris@366 288 {
Chris@366 289 return m_pluginVersion;
Chris@366 290 }
Chris@366 291
Chris@366 292 void
Chris@366 293 Transform::setPluginVersion(QString version)
Chris@366 294 {
Chris@366 295 m_pluginVersion = version;
Chris@366 296 }
Chris@366 297
Chris@366 298 QString
Chris@350 299 Transform::getProgram() const
Chris@350 300 {
Chris@350 301 return m_program;
Chris@350 302 }
Chris@350 303
Chris@350 304 void
Chris@350 305 Transform::setProgram(QString program)
Chris@350 306 {
Chris@350 307 m_program = program;
Chris@350 308 }
Chris@350 309
Chris@508 310 Transform::SummaryType
Chris@508 311 Transform::getSummaryType() const
Chris@508 312 {
Chris@508 313 return m_summaryType;
Chris@508 314 }
Chris@508 315
Chris@508 316 void
Chris@508 317 Transform::setSummaryType(SummaryType type)
Chris@508 318 {
Chris@508 319 m_summaryType = type;
Chris@508 320 }
Chris@328 321
Chris@350 322 size_t
Chris@350 323 Transform::getStepSize() const
Chris@350 324 {
Chris@350 325 return m_stepSize;
Chris@328 326 }
Chris@350 327
Chris@350 328 void
Chris@350 329 Transform::setStepSize(size_t s)
Chris@350 330 {
Chris@350 331 m_stepSize = s;
Chris@350 332 }
Chris@350 333
Chris@350 334 size_t
Chris@350 335 Transform::getBlockSize() const
Chris@350 336 {
Chris@350 337 return m_blockSize;
Chris@350 338 }
Chris@350 339
Chris@350 340 void
Chris@350 341 Transform::setBlockSize(size_t s)
Chris@350 342 {
Chris@350 343 m_blockSize = s;
Chris@350 344 }
Chris@350 345
Chris@350 346 WindowType
Chris@350 347 Transform::getWindowType() const
Chris@350 348 {
Chris@350 349 return m_windowType;
Chris@350 350 }
Chris@350 351
Chris@350 352 void
Chris@350 353 Transform::setWindowType(WindowType type)
Chris@350 354 {
Chris@350 355 m_windowType = type;
Chris@350 356 }
Chris@350 357
Chris@350 358 RealTime
Chris@350 359 Transform::getStartTime() const
Chris@350 360 {
Chris@350 361 return m_startTime;
Chris@350 362 }
Chris@350 363
Chris@350 364 void
Chris@350 365 Transform::setStartTime(RealTime t)
Chris@350 366 {
Chris@350 367 m_startTime = t;
Chris@350 368 }
Chris@350 369
Chris@350 370 RealTime
Chris@350 371 Transform::getDuration() const
Chris@350 372 {
Chris@350 373 return m_duration;
Chris@350 374 }
Chris@350 375
Chris@350 376 void
Chris@350 377 Transform::setDuration(RealTime d)
Chris@350 378 {
Chris@350 379 m_duration = d;
Chris@350 380 }
Chris@350 381
Chris@350 382 float
Chris@350 383 Transform::getSampleRate() const
Chris@350 384 {
Chris@350 385 return m_sampleRate;
Chris@350 386 }
Chris@350 387
Chris@350 388 void
Chris@350 389 Transform::setSampleRate(float rate)
Chris@350 390 {
Chris@350 391 m_sampleRate = rate;
Chris@350 392 }
Chris@350 393
Chris@350 394 void
Chris@350 395 Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const
Chris@350 396 {
Chris@350 397 out << indent;
Chris@350 398
Chris@350 399 bool haveContent = true;
Chris@350 400 if (m_parameters.empty() && m_configuration.empty()) haveContent = false;
Chris@350 401
Chris@396 402 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 403 .arg(encodeEntities(m_id))
Chris@366 404 .arg(encodeEntities(m_pluginVersion))
Chris@350 405 .arg(encodeEntities(m_program))
Chris@350 406 .arg(m_stepSize)
Chris@350 407 .arg(m_blockSize)
Chris@350 408 .arg(encodeEntities(Window<float>::getNameForType(m_windowType).c_str()))
Chris@350 409 .arg(encodeEntities(m_startTime.toString().c_str()))
Chris@350 410 .arg(encodeEntities(m_duration.toString().c_str()))
Chris@366 411 .arg(m_sampleRate);
Chris@366 412
Chris@508 413 if (m_summaryType != NoSummary) {
Chris@508 414 out << QString("\n summaryType=\"%1\"").arg(summaryTypeToString(m_summaryType));
Chris@508 415 }
Chris@508 416
Chris@366 417 if (extraAttributes != "") {
Chris@366 418 out << " " << extraAttributes;
Chris@366 419 }
Chris@350 420
Chris@350 421 if (haveContent) {
Chris@350 422
Chris@350 423 out << ">\n";
Chris@350 424
Chris@350 425 for (ParameterMap::const_iterator i = m_parameters.begin();
Chris@350 426 i != m_parameters.end(); ++i) {
Chris@350 427 out << indent << " "
Chris@350 428 << QString("<parameter name=\"%1\" value=\"%2\"/>\n")
Chris@350 429 .arg(encodeEntities(i->first))
Chris@350 430 .arg(i->second);
Chris@350 431 }
Chris@350 432
Chris@350 433 for (ConfigurationMap::const_iterator i = m_configuration.begin();
Chris@350 434 i != m_configuration.end(); ++i) {
Chris@350 435 out << indent << " "
Chris@350 436 << QString("<configuration name=\"%1\" value=\"%2\"/>\n")
Chris@350 437 .arg(encodeEntities(i->first))
Chris@350 438 .arg(encodeEntities(i->second));
Chris@350 439 }
Chris@350 440
Chris@350 441 out << indent << "</transform>\n";
Chris@350 442
Chris@350 443 } else {
Chris@350 444
Chris@350 445 out << "/>\n";
Chris@350 446 }
Chris@350 447 }
Chris@350 448
Chris@508 449 Transform::SummaryType
Chris@508 450 Transform::stringToSummaryType(QString str)
Chris@508 451 {
Chris@508 452 str = str.toLower();
Chris@508 453 if (str == "minimum" || str == "min") return Minimum;
Chris@508 454 if (str == "maximum" || str == "max") return Maximum;
Chris@508 455 if (str == "mean") return Mean;
Chris@508 456 if (str == "median") return Median;
Chris@508 457 if (str == "mode") return Mode;
Chris@508 458 if (str == "sum") return Sum;
Chris@508 459 if (str == "variance") return Variance;
Chris@508 460 if (str == "standard-deviation" || str == "standardDeviation" ||
Chris@508 461 str == "standard deviation" || str == "sd") return StandardDeviation;
Chris@508 462 if (str == "count") return Count;
Chris@508 463 if (str == "") return NoSummary;
Chris@690 464 SVDEBUG << "Transform::stringToSummaryType: unknown summary type \""
Chris@687 465 << str << "\"" << endl;
Chris@508 466 return NoSummary;
Chris@508 467 }
Chris@508 468
Chris@508 469 QString
Chris@508 470 Transform::summaryTypeToString(SummaryType type)
Chris@508 471 {
Chris@508 472 switch (type) {
Chris@508 473 case Minimum: return "min";
Chris@508 474 case Maximum: return "max";
Chris@508 475 case Mean: return "mean";
Chris@508 476 case Median: return "median";
Chris@508 477 case Mode: return "mode";
Chris@508 478 case Sum: return "sum";
Chris@508 479 case Variance: return "variance";
Chris@508 480 case StandardDeviation: return "sd";
Chris@508 481 case Count: return "count";
Chris@508 482 case NoSummary: return "";
Chris@508 483 default:
Chris@690 484 SVDEBUG << "Transform::summaryTypeToString: unexpected summary type "
Chris@687 485 << int(type) << endl;
Chris@508 486 return "";
Chris@508 487 }
Chris@508 488 }
Chris@508 489
Chris@350 490 void
Chris@350 491 Transform::setFromXmlAttributes(const QXmlAttributes &attrs)
Chris@350 492 {
Chris@350 493 if (attrs.value("id") != "") {
Chris@350 494 setIdentifier(attrs.value("id"));
Chris@350 495 }
Chris@350 496
Chris@366 497 if (attrs.value("pluginVersion") != "") {
Chris@366 498 setPluginVersion(attrs.value("pluginVersion"));
Chris@366 499 }
Chris@366 500
Chris@350 501 if (attrs.value("program") != "") {
Chris@350 502 setProgram(attrs.value("program"));
Chris@350 503 }
Chris@350 504
Chris@350 505 if (attrs.value("stepSize") != "") {
Chris@350 506 setStepSize(attrs.value("stepSize").toInt());
Chris@350 507 }
Chris@350 508
Chris@350 509 if (attrs.value("blockSize") != "") {
Chris@350 510 setBlockSize(attrs.value("blockSize").toInt());
Chris@350 511 }
Chris@350 512
Chris@350 513 if (attrs.value("windowType") != "") {
Chris@350 514 setWindowType(Window<float>::getTypeForName
Chris@350 515 (attrs.value("windowType").toStdString()));
Chris@350 516 }
Chris@350 517
Chris@350 518 if (attrs.value("startTime") != "") {
Chris@350 519 setStartTime(RealTime::fromString(attrs.value("startTime").toStdString()));
Chris@350 520 }
Chris@350 521
Chris@350 522 if (attrs.value("duration") != "") {
Chris@350 523 setStartTime(RealTime::fromString(attrs.value("duration").toStdString()));
Chris@350 524 }
Chris@350 525
Chris@350 526 if (attrs.value("sampleRate") != "") {
Chris@350 527 setSampleRate(attrs.value("sampleRate").toFloat());
Chris@350 528 }
Chris@508 529
Chris@508 530 if (attrs.value("summaryType") != "") {
Chris@508 531 setSummaryType(stringToSummaryType(attrs.value("summaryType")));
Chris@508 532 }
Chris@350 533 }
Chris@350 534