svcore
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006-2007 Chris Cannam and QMUL. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "Transform.h" 00017 00018 #include "plugin/PluginIdentifier.h" 00019 00020 #include "plugin/FeatureExtractionPluginFactory.h" 00021 00022 #include <QXmlAttributes> 00023 00024 #include <QDomDocument> 00025 #include <QDomElement> 00026 #include <QDomNamedNodeMap> 00027 #include <QDomAttr> 00028 00029 #include <QTextStream> 00030 00031 #include <iostream> 00032 00033 Transform::Transform() : 00034 m_summaryType(NoSummary), 00035 m_stepSize(0), 00036 m_blockSize(0), 00037 m_windowType(HanningWindow), 00038 m_sampleRate(0) 00039 { 00040 } 00041 00042 Transform::Transform(QString xml) : 00043 m_summaryType(NoSummary), 00044 m_stepSize(0), 00045 m_blockSize(0), 00046 m_windowType(HanningWindow), 00047 m_sampleRate(0) 00048 { 00049 QDomDocument doc; 00050 00051 QString error; 00052 int errorLine; 00053 int errorColumn; 00054 00055 if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) { 00056 cerr << "Transform::Transform: Error in parsing XML: " 00057 << error << " at line " << errorLine 00058 << ", column " << errorColumn << endl; 00059 cerr << "Input follows:" << endl; 00060 cerr << xml << endl; 00061 cerr << "Input ends." << endl; 00062 return; 00063 } 00064 00065 QDomElement transformElt = doc.firstChildElement("transform"); 00066 QDomNamedNodeMap attrNodes = transformElt.attributes(); 00067 QXmlAttributes attrs; 00068 00069 for (int i = 0; i < attrNodes.length(); ++i) { 00070 QDomAttr attr = attrNodes.item(i).toAttr(); 00071 if (!attr.isNull()) attrs.append(attr.name(), "", "", attr.value()); 00072 } 00073 00074 setFromXmlAttributes(attrs); 00075 00076 for (QDomElement paramElt = transformElt.firstChildElement("parameter"); 00077 !paramElt.isNull(); 00078 paramElt = paramElt.nextSiblingElement("parameter")) { 00079 00080 QDomNamedNodeMap paramAttrs = paramElt.attributes(); 00081 00082 QDomAttr nameAttr = paramAttrs.namedItem("name").toAttr(); 00083 if (nameAttr.isNull() || nameAttr.value() == "") continue; 00084 00085 QDomAttr valueAttr = paramAttrs.namedItem("value").toAttr(); 00086 if (valueAttr.isNull() || valueAttr.value() == "") continue; 00087 00088 setParameter(nameAttr.value(), valueAttr.value().toFloat()); 00089 } 00090 00091 for (QDomElement configElt = transformElt.firstChildElement("configuration"); 00092 !configElt.isNull(); 00093 configElt = configElt.nextSiblingElement("configuration")) { 00094 00095 QDomNamedNodeMap configAttrs = configElt.attributes(); 00096 00097 QDomAttr nameAttr = configAttrs.namedItem("name").toAttr(); 00098 if (nameAttr.isNull() || nameAttr.value() == "") continue; 00099 00100 QDomAttr valueAttr = configAttrs.namedItem("value").toAttr(); 00101 if (valueAttr.isNull() || valueAttr.value() == "") continue; 00102 00103 setConfigurationValue(nameAttr.value(), valueAttr.value()); 00104 } 00105 } 00106 00107 Transform::~Transform() 00108 { 00109 } 00110 00111 bool 00112 Transform::operator==(const Transform &t) const 00113 { 00114 bool identical = 00115 m_id == t.m_id && 00116 m_parameters == t.m_parameters && 00117 m_configuration == t.m_configuration && 00118 m_program == t.m_program && 00119 m_summaryType == t.m_summaryType && 00120 m_stepSize == t.m_stepSize && 00121 m_blockSize == t.m_blockSize && 00122 m_windowType == t.m_windowType && 00123 m_startTime == t.m_startTime && 00124 m_duration == t.m_duration && 00125 m_sampleRate == t.m_sampleRate; 00126 /* 00127 SVDEBUG << "Transform::operator==: identical = " << identical << endl; 00128 cerr << "A = " << endl; 00129 cerr << toXmlString() << endl; 00130 cerr << "B = " << endl; 00131 cerr << t.toXmlString() << endl; 00132 */ 00133 return identical; 00134 } 00135 00136 bool 00137 Transform::operator<(const Transform &t) const 00138 { 00139 if (m_id != t.m_id) { 00140 return m_id < t.m_id; 00141 } 00142 if (m_parameters != t.m_parameters) { 00143 return mapLessThan<QString, float>(m_parameters, t.m_parameters); 00144 } 00145 if (m_configuration != t.m_configuration) { 00146 return mapLessThan<QString, QString>(m_configuration, t.m_configuration); 00147 } 00148 if (m_program != t.m_program) { 00149 return m_program < t.m_program; 00150 } 00151 if (m_summaryType != t.m_summaryType) { 00152 return int(m_summaryType) < int(t.m_summaryType); 00153 } 00154 if (m_stepSize != t.m_stepSize) { 00155 return m_stepSize < t.m_stepSize; 00156 } 00157 if (m_blockSize != t.m_blockSize) { 00158 return m_blockSize < t.m_blockSize; 00159 } 00160 if (m_windowType != t.m_windowType) { 00161 return m_windowType < t.m_windowType; 00162 } 00163 if (m_startTime != t.m_startTime) { 00164 return m_startTime < t.m_startTime; 00165 } 00166 if (m_duration != t.m_duration) { 00167 return m_duration < t.m_duration; 00168 } 00169 if (m_sampleRate != t.m_sampleRate) { 00170 return m_sampleRate < t.m_sampleRate; 00171 } 00172 return false; 00173 } 00174 00175 void 00176 Transform::setIdentifier(TransformId id) 00177 { 00178 m_id = id; 00179 } 00180 00181 TransformId 00182 Transform::getIdentifier() const 00183 { 00184 return m_id; 00185 } 00186 00187 QString 00188 Transform::createIdentifier(QString type, QString soName, QString label, 00189 QString output) 00190 { 00191 QString pluginId = PluginIdentifier::createIdentifier(type, soName, label); 00192 return pluginId + ":" + output; 00193 } 00194 00195 void 00196 Transform::parseIdentifier(QString identifier, 00197 QString &type, QString &soName, 00198 QString &label, QString &output) 00199 { 00200 output = identifier.section(':', 3); 00201 PluginIdentifier::parseIdentifier(identifier.section(':', 0, 2), 00202 type, soName, label); 00203 } 00204 00205 Transform::Type 00206 Transform::getType() const 00207 { 00208 if (FeatureExtractionPluginFactory::instanceFor(getPluginIdentifier())) { 00209 return FeatureExtraction; 00210 } else { 00211 // We don't have an unknown/invalid return value, so always 00212 // return this 00213 return RealTimeEffect; 00214 } 00215 } 00216 00217 QString 00218 Transform::getPluginIdentifier() const 00219 { 00220 return m_id.section(':', 0, 2); 00221 } 00222 00223 QString 00224 Transform::getOutput() const 00225 { 00226 return m_id.section(':', 3); 00227 } 00228 00229 void 00230 Transform::setPluginIdentifier(QString pluginIdentifier) 00231 { 00232 m_id = pluginIdentifier + ':' + getOutput(); 00233 } 00234 00235 void 00236 Transform::setOutput(QString output) 00237 { 00238 m_id = getPluginIdentifier() + ':' + output; 00239 } 00240 00241 TransformId 00242 Transform::getIdentifierForPluginOutput(QString pluginIdentifier, 00243 QString output) 00244 { 00245 return pluginIdentifier + ':' + output; 00246 } 00247 00248 const Transform::ParameterMap & 00249 Transform::getParameters() const 00250 { 00251 return m_parameters; 00252 } 00253 00254 void 00255 Transform::setParameters(const ParameterMap &pm) 00256 { 00257 m_parameters = pm; 00258 } 00259 00260 void 00261 Transform::setParameter(QString name, float value) 00262 { 00263 // SVDEBUG << "Transform::setParameter(" << name// << ") -> " << value << endl; 00264 m_parameters[name] = value; 00265 } 00266 00267 const Transform::ConfigurationMap & 00268 Transform::getConfiguration() const 00269 { 00270 return m_configuration; 00271 } 00272 00273 void 00274 Transform::setConfiguration(const ConfigurationMap &cm) 00275 { 00276 m_configuration = cm; 00277 } 00278 00279 void 00280 Transform::setConfigurationValue(QString name, QString value) 00281 { 00282 SVDEBUG << "Transform::setConfigurationValue(" << name << ") -> " << value << endl; 00283 m_configuration[name] = value; 00284 } 00285 00286 QString 00287 Transform::getPluginVersion() const 00288 { 00289 return m_pluginVersion; 00290 } 00291 00292 void 00293 Transform::setPluginVersion(QString version) 00294 { 00295 m_pluginVersion = version; 00296 } 00297 00298 QString 00299 Transform::getProgram() const 00300 { 00301 return m_program; 00302 } 00303 00304 void 00305 Transform::setProgram(QString program) 00306 { 00307 m_program = program; 00308 } 00309 00310 Transform::SummaryType 00311 Transform::getSummaryType() const 00312 { 00313 return m_summaryType; 00314 } 00315 00316 void 00317 Transform::setSummaryType(SummaryType type) 00318 { 00319 m_summaryType = type; 00320 } 00321 00322 int 00323 Transform::getStepSize() const 00324 { 00325 return m_stepSize; 00326 } 00327 00328 void 00329 Transform::setStepSize(int s) 00330 { 00331 m_stepSize = s; 00332 } 00333 00334 int 00335 Transform::getBlockSize() const 00336 { 00337 return m_blockSize; 00338 } 00339 00340 void 00341 Transform::setBlockSize(int s) 00342 { 00343 m_blockSize = s; 00344 } 00345 00346 WindowType 00347 Transform::getWindowType() const 00348 { 00349 return m_windowType; 00350 } 00351 00352 void 00353 Transform::setWindowType(WindowType type) 00354 { 00355 m_windowType = type; 00356 } 00357 00358 RealTime 00359 Transform::getStartTime() const 00360 { 00361 return m_startTime; 00362 } 00363 00364 void 00365 Transform::setStartTime(RealTime t) 00366 { 00367 m_startTime = t; 00368 } 00369 00370 RealTime 00371 Transform::getDuration() const 00372 { 00373 return m_duration; 00374 } 00375 00376 void 00377 Transform::setDuration(RealTime d) 00378 { 00379 m_duration = d; 00380 } 00381 00382 float 00383 Transform::getSampleRate() const 00384 { 00385 return m_sampleRate; 00386 } 00387 00388 void 00389 Transform::setSampleRate(float rate) 00390 { 00391 m_sampleRate = rate; 00392 } 00393 00394 void 00395 Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const 00396 { 00397 out << indent; 00398 00399 bool haveContent = true; 00400 if (m_parameters.empty() && m_configuration.empty()) haveContent = false; 00401 00402 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\"") 00403 .arg(encodeEntities(m_id)) 00404 .arg(encodeEntities(m_pluginVersion)) 00405 .arg(encodeEntities(m_program)) 00406 .arg(m_stepSize) 00407 .arg(m_blockSize) 00408 .arg(encodeEntities(Window<float>::getNameForType(m_windowType).c_str())) 00409 .arg(encodeEntities(m_startTime.toString().c_str())) 00410 .arg(encodeEntities(m_duration.toString().c_str())) 00411 .arg(m_sampleRate); 00412 00413 if (m_summaryType != NoSummary) { 00414 out << QString("\n summaryType=\"%1\"").arg(summaryTypeToString(m_summaryType)); 00415 } 00416 00417 if (extraAttributes != "") { 00418 out << " " << extraAttributes; 00419 } 00420 00421 if (haveContent) { 00422 00423 out << ">\n"; 00424 00425 for (ParameterMap::const_iterator i = m_parameters.begin(); 00426 i != m_parameters.end(); ++i) { 00427 out << indent << " " 00428 << QString("<parameter name=\"%1\" value=\"%2\"/>\n") 00429 .arg(encodeEntities(i->first)) 00430 .arg(i->second); 00431 } 00432 00433 for (ConfigurationMap::const_iterator i = m_configuration.begin(); 00434 i != m_configuration.end(); ++i) { 00435 out << indent << " " 00436 << QString("<configuration name=\"%1\" value=\"%2\"/>\n") 00437 .arg(encodeEntities(i->first)) 00438 .arg(encodeEntities(i->second)); 00439 } 00440 00441 out << indent << "</transform>\n"; 00442 00443 } else { 00444 00445 out << "/>\n"; 00446 } 00447 } 00448 00449 Transform::SummaryType 00450 Transform::stringToSummaryType(QString str) 00451 { 00452 str = str.toLower(); 00453 if (str == "minimum" || str == "min") return Minimum; 00454 if (str == "maximum" || str == "max") return Maximum; 00455 if (str == "mean") return Mean; 00456 if (str == "median") return Median; 00457 if (str == "mode") return Mode; 00458 if (str == "sum") return Sum; 00459 if (str == "variance") return Variance; 00460 if (str == "standard-deviation" || str == "standardDeviation" || 00461 str == "standard deviation" || str == "sd") return StandardDeviation; 00462 if (str == "count") return Count; 00463 if (str == "") return NoSummary; 00464 SVDEBUG << "Transform::stringToSummaryType: unknown summary type \"" 00465 << str << "\"" << endl; 00466 return NoSummary; 00467 } 00468 00469 QString 00470 Transform::summaryTypeToString(SummaryType type) 00471 { 00472 switch (type) { 00473 case Minimum: return "min"; 00474 case Maximum: return "max"; 00475 case Mean: return "mean"; 00476 case Median: return "median"; 00477 case Mode: return "mode"; 00478 case Sum: return "sum"; 00479 case Variance: return "variance"; 00480 case StandardDeviation: return "sd"; 00481 case Count: return "count"; 00482 case NoSummary: return ""; 00483 default: 00484 SVDEBUG << "Transform::summaryTypeToString: unexpected summary type " 00485 << int(type) << endl; 00486 return ""; 00487 } 00488 } 00489 00490 void 00491 Transform::setFromXmlAttributes(const QXmlAttributes &attrs) 00492 { 00493 if (attrs.value("id") != "") { 00494 setIdentifier(attrs.value("id")); 00495 } 00496 00497 if (attrs.value("pluginVersion") != "") { 00498 setPluginVersion(attrs.value("pluginVersion")); 00499 } 00500 00501 if (attrs.value("program") != "") { 00502 setProgram(attrs.value("program")); 00503 } 00504 00505 if (attrs.value("stepSize") != "") { 00506 setStepSize(attrs.value("stepSize").toInt()); 00507 } 00508 00509 if (attrs.value("blockSize") != "") { 00510 setBlockSize(attrs.value("blockSize").toInt()); 00511 } 00512 00513 if (attrs.value("windowType") != "") { 00514 setWindowType(Window<float>::getTypeForName 00515 (attrs.value("windowType").toStdString())); 00516 } 00517 00518 if (attrs.value("startTime") != "") { 00519 setStartTime(RealTime::fromString(attrs.value("startTime").toStdString())); 00520 } 00521 00522 if (attrs.value("duration") != "") { 00523 setStartTime(RealTime::fromString(attrs.value("duration").toStdString())); 00524 } 00525 00526 if (attrs.value("sampleRate") != "") { 00527 setSampleRate(attrs.value("sampleRate").toFloat()); 00528 } 00529 00530 if (attrs.value("summaryType") != "") { 00531 setSummaryType(stringToSummaryType(attrs.value("summaryType"))); 00532 } 00533 } 00534