Chris@320: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@320: Chris@320: /* Chris@320: Sonic Visualiser Chris@320: An audio file viewer and annotation editor. Chris@320: Centre for Digital Music, Queen Mary, University of London. Chris@328: This file copyright 2006-2007 Chris Cannam and QMUL. Chris@320: Chris@320: This program is free software; you can redistribute it and/or Chris@320: modify it under the terms of the GNU General Public License as Chris@320: published by the Free Software Foundation; either version 2 of the Chris@320: License, or (at your option) any later version. See the file Chris@320: COPYING included with this distribution for more information. Chris@320: */ Chris@320: Chris@320: #include "Transform.h" Chris@320: Chris@328: #include "plugin/PluginIdentifier.h" Chris@328: Chris@332: #include "plugin/FeatureExtractionPluginFactory.h" Chris@1138: #include "plugin/RealTimePluginFactory.h" Chris@332: Chris@350: #include Chris@350: Chris@350: #include Chris@350: #include Chris@350: #include Chris@350: #include Chris@350: Chris@350: #include Chris@350: Chris@350: #include Chris@350: Chris@328: Transform::Transform() : Chris@508: m_summaryType(NoSummary), Chris@328: m_stepSize(0), Chris@328: m_blockSize(0), Chris@328: m_windowType(HanningWindow), Chris@328: m_sampleRate(0) Chris@320: { Chris@320: } Chris@320: Chris@350: Transform::Transform(QString xml) : Chris@508: m_summaryType(NoSummary), Chris@350: m_stepSize(0), Chris@350: m_blockSize(0), Chris@350: m_windowType(HanningWindow), Chris@350: m_sampleRate(0) Chris@350: { Chris@350: QDomDocument doc; Chris@350: Chris@350: QString error; Chris@350: int errorLine; Chris@350: int errorColumn; Chris@350: Chris@350: if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) { Chris@1163: m_errorString = QString("%1 at line %2, column %3") Chris@1163: .arg(error).arg(errorLine).arg(errorColumn); Chris@350: return; Chris@350: } Chris@350: Chris@350: QDomElement transformElt = doc.firstChildElement("transform"); Chris@350: QDomNamedNodeMap attrNodes = transformElt.attributes(); Chris@350: QXmlAttributes attrs; Chris@350: Chris@930: for (int i = 0; i < attrNodes.length(); ++i) { Chris@350: QDomAttr attr = attrNodes.item(i).toAttr(); Chris@350: if (!attr.isNull()) attrs.append(attr.name(), "", "", attr.value()); Chris@350: } Chris@350: Chris@350: setFromXmlAttributes(attrs); Chris@350: Chris@350: for (QDomElement paramElt = transformElt.firstChildElement("parameter"); Chris@350: !paramElt.isNull(); Chris@350: paramElt = paramElt.nextSiblingElement("parameter")) { Chris@350: Chris@350: QDomNamedNodeMap paramAttrs = paramElt.attributes(); Chris@350: Chris@350: QDomAttr nameAttr = paramAttrs.namedItem("name").toAttr(); Chris@350: if (nameAttr.isNull() || nameAttr.value() == "") continue; Chris@350: Chris@350: QDomAttr valueAttr = paramAttrs.namedItem("value").toAttr(); Chris@350: if (valueAttr.isNull() || valueAttr.value() == "") continue; Chris@350: Chris@350: setParameter(nameAttr.value(), valueAttr.value().toFloat()); Chris@350: } Chris@350: Chris@350: for (QDomElement configElt = transformElt.firstChildElement("configuration"); Chris@350: !configElt.isNull(); Chris@350: configElt = configElt.nextSiblingElement("configuration")) { Chris@350: Chris@350: QDomNamedNodeMap configAttrs = configElt.attributes(); Chris@350: Chris@350: QDomAttr nameAttr = configAttrs.namedItem("name").toAttr(); Chris@350: if (nameAttr.isNull() || nameAttr.value() == "") continue; Chris@350: Chris@350: QDomAttr valueAttr = configAttrs.namedItem("value").toAttr(); Chris@350: if (valueAttr.isNull() || valueAttr.value() == "") continue; Chris@350: Chris@350: setConfigurationValue(nameAttr.value(), valueAttr.value()); Chris@350: } Chris@350: } Chris@350: Chris@320: Transform::~Transform() Chris@320: { Chris@320: } Chris@320: Chris@350: bool Chris@400: Transform::operator==(const Transform &t) const Chris@350: { Chris@583: bool identical = Chris@350: m_id == t.m_id && Chris@350: m_parameters == t.m_parameters && Chris@350: m_configuration == t.m_configuration && Chris@350: m_program == t.m_program && Chris@508: m_summaryType == t.m_summaryType && Chris@350: m_stepSize == t.m_stepSize && Chris@350: m_blockSize == t.m_blockSize && Chris@350: m_windowType == t.m_windowType && Chris@350: m_startTime == t.m_startTime && Chris@350: m_duration == t.m_duration && Chris@350: m_sampleRate == t.m_sampleRate; Chris@583: /* Chris@690: SVDEBUG << "Transform::operator==: identical = " << identical << endl; Chris@843: cerr << "A = " << endl; Chris@843: cerr << toXmlString() << endl; Chris@843: cerr << "B = " << endl; Chris@843: cerr << t.toXmlString() << endl; Chris@583: */ Chris@583: return identical; Chris@350: } Chris@350: Chris@400: bool Chris@400: Transform::operator<(const Transform &t) const Chris@400: { Chris@400: if (m_id != t.m_id) { Chris@400: return m_id < t.m_id; Chris@400: } Chris@400: if (m_parameters != t.m_parameters) { Chris@400: return mapLessThan(m_parameters, t.m_parameters); Chris@400: } Chris@400: if (m_configuration != t.m_configuration) { Chris@400: return mapLessThan(m_configuration, t.m_configuration); Chris@400: } Chris@400: if (m_program != t.m_program) { Chris@400: return m_program < t.m_program; Chris@400: } Chris@508: if (m_summaryType != t.m_summaryType) { Chris@508: return int(m_summaryType) < int(t.m_summaryType); Chris@508: } Chris@400: if (m_stepSize != t.m_stepSize) { Chris@400: return m_stepSize < t.m_stepSize; Chris@400: } Chris@400: if (m_blockSize != t.m_blockSize) { Chris@400: return m_blockSize < t.m_blockSize; Chris@400: } Chris@400: if (m_windowType != t.m_windowType) { Chris@400: return m_windowType < t.m_windowType; Chris@400: } Chris@400: if (m_startTime != t.m_startTime) { Chris@400: return m_startTime < t.m_startTime; Chris@400: } Chris@400: if (m_duration != t.m_duration) { Chris@400: return m_duration < t.m_duration; Chris@400: } Chris@400: if (m_sampleRate != t.m_sampleRate) { Chris@400: return m_sampleRate < t.m_sampleRate; Chris@400: } Chris@400: return false; Chris@400: } Chris@400: Chris@350: void Chris@350: Transform::setIdentifier(TransformId id) Chris@350: { Chris@350: m_id = id; Chris@350: } Chris@350: Chris@350: TransformId Chris@350: Transform::getIdentifier() const Chris@350: { Chris@350: return m_id; Chris@350: } Chris@350: Chris@328: QString Chris@328: Transform::createIdentifier(QString type, QString soName, QString label, Chris@328: QString output) Chris@328: { Chris@328: QString pluginId = PluginIdentifier::createIdentifier(type, soName, label); Chris@328: return pluginId + ":" + output; Chris@328: } Chris@328: Chris@328: void Chris@328: Transform::parseIdentifier(QString identifier, Chris@328: QString &type, QString &soName, Chris@328: QString &label, QString &output) Chris@328: { Chris@328: output = identifier.section(':', 3); Chris@328: PluginIdentifier::parseIdentifier(identifier.section(':', 0, 2), Chris@328: type, soName, label); Chris@328: } Chris@328: Chris@328: Transform::Type Chris@328: Transform::getType() const Chris@328: { Chris@1225: if (RealTimePluginFactory::instanceFor(getPluginIdentifier())) { Chris@1138: return RealTimeEffect; Chris@332: } else { Chris@1225: return FeatureExtraction; Chris@332: } Chris@328: } Chris@328: Chris@328: QString Chris@328: Transform::getPluginIdentifier() const Chris@328: { Chris@328: return m_id.section(':', 0, 2); Chris@328: } Chris@328: Chris@328: QString Chris@328: Transform::getOutput() const Chris@328: { Chris@328: return m_id.section(':', 3); Chris@328: } Chris@328: Chris@353: void Chris@353: Transform::setPluginIdentifier(QString pluginIdentifier) Chris@353: { Chris@353: m_id = pluginIdentifier + ':' + getOutput(); Chris@353: } Chris@353: Chris@353: void Chris@353: Transform::setOutput(QString output) Chris@353: { Chris@353: m_id = getPluginIdentifier() + ':' + output; Chris@353: } Chris@353: Chris@353: TransformId Chris@353: Transform::getIdentifierForPluginOutput(QString pluginIdentifier, Chris@353: QString output) Chris@353: { Chris@353: return pluginIdentifier + ':' + output; Chris@353: } Chris@353: Chris@350: const Transform::ParameterMap & Chris@350: Transform::getParameters() const Chris@350: { Chris@350: return m_parameters; Chris@350: } Chris@350: Chris@328: void Chris@350: Transform::setParameters(const ParameterMap &pm) Chris@328: { Chris@350: m_parameters = pm; Chris@350: } Chris@350: Chris@350: void Chris@350: Transform::setParameter(QString name, float value) Chris@350: { Chris@690: // SVDEBUG << "Transform::setParameter(" << name// << ") -> " << value << endl; Chris@350: m_parameters[name] = value; Chris@350: } Chris@350: Chris@350: const Transform::ConfigurationMap & Chris@350: Transform::getConfiguration() const Chris@350: { Chris@350: return m_configuration; Chris@350: } Chris@350: Chris@350: void Chris@350: Transform::setConfiguration(const ConfigurationMap &cm) Chris@350: { Chris@350: m_configuration = cm; Chris@350: } Chris@350: Chris@350: void Chris@350: Transform::setConfigurationValue(QString name, QString value) Chris@350: { Chris@690: SVDEBUG << "Transform::setConfigurationValue(" << name << ") -> " << value << endl; Chris@350: m_configuration[name] = value; Chris@350: } Chris@350: Chris@350: QString Chris@366: Transform::getPluginVersion() const Chris@366: { Chris@366: return m_pluginVersion; Chris@366: } Chris@366: Chris@366: void Chris@366: Transform::setPluginVersion(QString version) Chris@366: { Chris@366: m_pluginVersion = version; Chris@366: } Chris@366: Chris@366: QString Chris@350: Transform::getProgram() const Chris@350: { Chris@350: return m_program; Chris@350: } Chris@350: Chris@350: void Chris@350: Transform::setProgram(QString program) Chris@350: { Chris@350: m_program = program; Chris@350: } Chris@350: Chris@508: Transform::SummaryType Chris@508: Transform::getSummaryType() const Chris@508: { Chris@508: return m_summaryType; Chris@508: } Chris@508: Chris@508: void Chris@508: Transform::setSummaryType(SummaryType type) Chris@508: { Chris@508: m_summaryType = type; Chris@508: } Chris@328: Chris@930: int Chris@350: Transform::getStepSize() const Chris@350: { Chris@350: return m_stepSize; Chris@328: } Chris@350: Chris@350: void Chris@930: Transform::setStepSize(int s) Chris@350: { Chris@350: m_stepSize = s; Chris@350: } Chris@350: Chris@930: int Chris@350: Transform::getBlockSize() const Chris@350: { Chris@350: return m_blockSize; Chris@350: } Chris@350: Chris@350: void Chris@930: Transform::setBlockSize(int s) Chris@350: { Chris@350: m_blockSize = s; Chris@350: } Chris@350: Chris@350: WindowType Chris@350: Transform::getWindowType() const Chris@350: { Chris@350: return m_windowType; Chris@350: } Chris@350: Chris@350: void Chris@350: Transform::setWindowType(WindowType type) Chris@350: { Chris@350: m_windowType = type; Chris@350: } Chris@350: Chris@350: RealTime Chris@350: Transform::getStartTime() const Chris@350: { Chris@350: return m_startTime; Chris@350: } Chris@350: Chris@350: void Chris@350: Transform::setStartTime(RealTime t) Chris@350: { Chris@350: m_startTime = t; Chris@350: } Chris@350: Chris@350: RealTime Chris@350: Transform::getDuration() const Chris@350: { Chris@350: return m_duration; Chris@350: } Chris@350: Chris@350: void Chris@350: Transform::setDuration(RealTime d) Chris@350: { Chris@350: m_duration = d; Chris@350: } Chris@350: Chris@1047: sv_samplerate_t Chris@350: Transform::getSampleRate() const Chris@350: { Chris@350: return m_sampleRate; Chris@350: } Chris@350: Chris@350: void Chris@1047: Transform::setSampleRate(sv_samplerate_t rate) Chris@350: { Chris@350: m_sampleRate = rate; Chris@350: } Chris@350: Chris@350: void Chris@350: Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const Chris@350: { Chris@350: out << indent; Chris@350: Chris@350: bool haveContent = true; Chris@350: if (m_parameters.empty() && m_configuration.empty()) haveContent = false; Chris@350: Chris@396: out << QString("::getNameForType(m_windowType).c_str())) Chris@350: .arg(encodeEntities(m_startTime.toString().c_str())) Chris@350: .arg(encodeEntities(m_duration.toString().c_str())) Chris@366: .arg(m_sampleRate); Chris@366: Chris@508: if (m_summaryType != NoSummary) { Chris@508: out << QString("\n summaryType=\"%1\"").arg(summaryTypeToString(m_summaryType)); Chris@508: } Chris@508: Chris@366: if (extraAttributes != "") { Chris@366: out << " " << extraAttributes; Chris@366: } Chris@350: Chris@350: if (haveContent) { Chris@350: Chris@350: out << ">\n"; Chris@350: Chris@350: for (ParameterMap::const_iterator i = m_parameters.begin(); Chris@350: i != m_parameters.end(); ++i) { Chris@350: out << indent << " " Chris@350: << QString("\n") Chris@350: .arg(encodeEntities(i->first)) Chris@350: .arg(i->second); Chris@350: } Chris@350: Chris@350: for (ConfigurationMap::const_iterator i = m_configuration.begin(); Chris@350: i != m_configuration.end(); ++i) { Chris@350: out << indent << " " Chris@350: << QString("\n") Chris@350: .arg(encodeEntities(i->first)) Chris@350: .arg(encodeEntities(i->second)); Chris@350: } Chris@350: Chris@350: out << indent << "\n"; Chris@350: Chris@350: } else { Chris@350: Chris@350: out << "/>\n"; Chris@350: } Chris@350: } Chris@350: Chris@508: Transform::SummaryType Chris@508: Transform::stringToSummaryType(QString str) Chris@508: { Chris@508: str = str.toLower(); Chris@508: if (str == "minimum" || str == "min") return Minimum; Chris@508: if (str == "maximum" || str == "max") return Maximum; Chris@508: if (str == "mean") return Mean; Chris@508: if (str == "median") return Median; Chris@508: if (str == "mode") return Mode; Chris@508: if (str == "sum") return Sum; Chris@508: if (str == "variance") return Variance; Chris@508: if (str == "standard-deviation" || str == "standardDeviation" || Chris@508: str == "standard deviation" || str == "sd") return StandardDeviation; Chris@508: if (str == "count") return Count; Chris@508: if (str == "") return NoSummary; Chris@690: SVDEBUG << "Transform::stringToSummaryType: unknown summary type \"" Chris@687: << str << "\"" << endl; Chris@508: return NoSummary; Chris@508: } Chris@508: Chris@508: QString Chris@508: Transform::summaryTypeToString(SummaryType type) Chris@508: { Chris@508: switch (type) { Chris@508: case Minimum: return "min"; Chris@508: case Maximum: return "max"; Chris@508: case Mean: return "mean"; Chris@508: case Median: return "median"; Chris@508: case Mode: return "mode"; Chris@508: case Sum: return "sum"; Chris@508: case Variance: return "variance"; Chris@508: case StandardDeviation: return "sd"; Chris@508: case Count: return "count"; Chris@508: case NoSummary: return ""; Chris@508: default: Chris@690: SVDEBUG << "Transform::summaryTypeToString: unexpected summary type " Chris@687: << int(type) << endl; Chris@508: return ""; Chris@508: } Chris@508: } Chris@508: Chris@350: void Chris@350: Transform::setFromXmlAttributes(const QXmlAttributes &attrs) Chris@350: { Chris@350: if (attrs.value("id") != "") { Chris@350: setIdentifier(attrs.value("id")); Chris@350: } Chris@350: Chris@366: if (attrs.value("pluginVersion") != "") { Chris@366: setPluginVersion(attrs.value("pluginVersion")); Chris@366: } Chris@366: Chris@350: if (attrs.value("program") != "") { Chris@350: setProgram(attrs.value("program")); Chris@350: } Chris@350: Chris@350: if (attrs.value("stepSize") != "") { Chris@350: setStepSize(attrs.value("stepSize").toInt()); Chris@350: } Chris@350: Chris@350: if (attrs.value("blockSize") != "") { Chris@350: setBlockSize(attrs.value("blockSize").toInt()); Chris@350: } Chris@350: Chris@350: if (attrs.value("windowType") != "") { Chris@350: setWindowType(Window::getTypeForName Chris@350: (attrs.value("windowType").toStdString())); Chris@350: } Chris@350: Chris@350: if (attrs.value("startTime") != "") { Chris@350: setStartTime(RealTime::fromString(attrs.value("startTime").toStdString())); Chris@350: } Chris@350: Chris@350: if (attrs.value("duration") != "") { Chris@988: setDuration(RealTime::fromString(attrs.value("duration").toStdString())); Chris@350: } Chris@350: Chris@350: if (attrs.value("sampleRate") != "") { Chris@350: setSampleRate(attrs.value("sampleRate").toFloat()); Chris@350: } Chris@508: Chris@508: if (attrs.value("summaryType") != "") { Chris@508: setSummaryType(stringToSummaryType(attrs.value("summaryType"))); Chris@508: } Chris@350: } Chris@350: