[Sv1-commits] SF.net SVN: sv1: [893] sonic-visualiser/branches/transforms
Brought to you by:
cannam
From: <ca...@us...> - 2007-12-07 16:45:29
|
Revision: 893 http://sv1.svn.sourceforge.net/sv1/?rev=893&view=rev Author: cannam Date: 2007-12-07 08:45:27 -0800 (Fri, 07 Dec 2007) Log Message: ----------- * Latest tranche of changes to make SV use the Transform to describe a transform, instead of an unholy mixture of plugin configuration XML, ExecutionContext object, etc. This time it compiles, runs, and appears to be backward compatible with old SV files. Modified Paths: -------------- sonic-visualiser/branches/transforms/base/RealTime.cpp sonic-visualiser/branches/transforms/base/RealTime.h sonic-visualiser/branches/transforms/base/Window.h sonic-visualiser/branches/transforms/framework/Document.cpp sonic-visualiser/branches/transforms/framework/Document.h sonic-visualiser/branches/transforms/framework/SVFileReader.cpp sonic-visualiser/branches/transforms/framework/SVFileReader.h sonic-visualiser/branches/transforms/plugin/transform/FeatureExtractionModelTransformer.cpp sonic-visualiser/branches/transforms/plugin/transform/FeatureExtractionModelTransformer.h sonic-visualiser/branches/transforms/plugin/transform/ModelTransformer.h sonic-visualiser/branches/transforms/plugin/transform/ModelTransformerFactory.cpp sonic-visualiser/branches/transforms/plugin/transform/ModelTransformerFactory.h sonic-visualiser/branches/transforms/plugin/transform/RealTimeEffectModelTransformer.cpp sonic-visualiser/branches/transforms/plugin/transform/RealTimeEffectModelTransformer.h sonic-visualiser/branches/transforms/plugin/transform/Transform.cpp sonic-visualiser/branches/transforms/plugin/transform/Transform.h sonic-visualiser/branches/transforms/plugin/transform/TransformDescription.h sonic-visualiser/branches/transforms/plugin/transform/TransformFactory.cpp sonic-visualiser/branches/transforms/plugin/transform/TransformFactory.h sonic-visualiser/branches/transforms/sv/main/MainWindow.cpp sonic-visualiser/branches/transforms/sv/main/OSCHandler.cpp Modified: sonic-visualiser/branches/transforms/base/RealTime.cpp =================================================================== --- sonic-visualiser/branches/transforms/base/RealTime.cpp 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/base/RealTime.cpp 2007-12-07 16:45:27 UTC (rev 893) @@ -122,6 +122,51 @@ return s.substr(0, s.length() - 1); } +RealTime +RealTime::fromString(std::string s) +{ + bool negative = false; + bool faulty = false; + bool section = 0; + std::string ssec, snsec; + + for (size_t i = 0; i < s.length(); ++i) { + + char c = s[i]; + if (isspace(c)) continue; + + if (section == 0) { + + if (c == '-') negative = true; + else if (isdigit(c)) { section = 1; ssec += c; } + else if (c == '.') section = 2; + else break; + + } else if (section == 1) { + + if (c == '.') section = 2; + else if (isdigit(c)) ssec += c; + else break; + + } else if (section == 2) { + + if (isdigit(c)) snsec += c; + else break; + } + } + + while (snsec.length() < 8) snsec += '0'; + + int sec = atoi(ssec.c_str()); + int nsec = atoi(snsec.c_str()); + if (negative) sec = -sec; + + std::cerr << "RealTime::fromString: string " << s << " -> " + << sec << " sec, " << nsec << " nsec" << std::endl; + + return RealTime(sec, nsec); +} + std::string RealTime::toText(bool fixedDp) const { Modified: sonic-visualiser/branches/transforms/base/RealTime.h =================================================================== --- sonic-visualiser/branches/transforms/base/RealTime.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/base/RealTime.h 2007-12-07 16:45:27 UTC (rev 893) @@ -95,30 +95,45 @@ RealTime operator*(int m) const; RealTime operator/(int d) const; - // Find the fractional difference between times - // + /** + * Return the ratio of two times. + */ double operator/(const RealTime &r) const; - // Return a human-readable debug-type string to full precision - // (probably not a format to show to a user directly). If align - // is true, prepend " " to the start of positive values so that - // they line up with negative ones (which start with "-"). - // + /** + * Return a human-readable debug-type string to full precision + * (probably not a format to show to a user directly). If align + * is true, prepend " " to the start of positive values so that + * they line up with negative ones (which start with "-"). + */ std::string toString(bool align = false) const; - // Return a user-readable string to the nearest millisecond - // in a form like HH:MM:SS.mmm - // + /** + * Convert a string as obtained from toString back to a RealTime + * object. + */ + static RealTime fromString(std::string); + + /** + * Return a user-readable string to the nearest millisecond, in a + * form like HH:MM:SS.mmm + */ std::string toText(bool fixedDp = false) const; - // Return a user-readable string to the nearest second in a form - // like "6s" (for less than a minute) or "2:21" (for more). - // + /** + * Return a user-readable string to the nearest second, in a form + * like "6s" (for less than a minute) or "2:21" (for more). + */ std::string toSecText() const; - // Convenience functions for handling sample frames - // + /** + * Convert a RealTime into a sample frame at the given sample rate. + */ static long realTime2Frame(const RealTime &r, unsigned int sampleRate); + + /** + * Convert a sample frame at the given sample rate into a RealTime. + */ static RealTime frame2RealTime(long frame, unsigned int sampleRate); static const RealTime zeroTime; Modified: sonic-visualiser/branches/transforms/base/Window.h =================================================================== --- sonic-visualiser/branches/transforms/base/Window.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/base/Window.h 2007-12-07 16:45:27 UTC (rev 893) @@ -18,6 +18,7 @@ #include <cmath> #include <iostream> +#include <string> #include <map> enum WindowType { @@ -61,6 +62,12 @@ WindowType getType() const { return m_type; } size_t getSize() const { return m_size; } + // The names used by these functions are un-translated, for use in + // e.g. XML I/O. Use Preferences::getPropertyValueLabel if you + // want translated names for use in the user interface. + static std::string getNameForType(WindowType type); + static WindowType getTypeForName(std::string name); + protected: WindowType m_type; size_t m_size; @@ -159,4 +166,46 @@ } } +template <typename T> +std::string +Window<T>::getNameForType(WindowType type) +{ + switch (type) { + case RectangularWindow: return "rectangular"; + case BartlettWindow: return "bartlett"; + case HammingWindow: return "hamming"; + case HanningWindow: return "hanning"; + case BlackmanWindow: return "blackman"; + case GaussianWindow: return "gaussian"; + case ParzenWindow: return "parzen"; + case NuttallWindow: return "nuttall"; + case BlackmanHarrisWindow: return "blackman-harris"; + } + + std::cerr << "WARNING: Window::getNameForType: unknown type " + << type << std::endl; + + return "unknown"; +} + +template <typename T> +WindowType +Window<T>::getTypeForName(std::string name) +{ + if (name == "rectangular") return RectangularWindow; + if (name == "bartlett") return BartlettWindow; + if (name == "hamming") return HammingWindow; + if (name == "hanning") return HanningWindow; + if (name == "blackman") return BlackmanWindow; + if (name == "gaussian") return GaussianWindow; + if (name == "parzen") return ParzenWindow; + if (name == "nuttall") return NuttallWindow; + if (name == "blackman-harris") return BlackmanHarrisWindow; + + std::cerr << "WARNING: Window::getTypeForName: unknown name \"" + << name << "\", defaulting to \"hanning\"" << std::endl; + + return HanningWindow; +} + #endif Modified: sonic-visualiser/branches/transforms/framework/Document.cpp =================================================================== --- sonic-visualiser/branches/transforms/framework/Document.cpp 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/framework/Document.cpp 2007-12-07 16:45:27 UTC (rev 893) @@ -659,7 +659,7 @@ } std::vector<Model *> -Document::getTransformerInputModels() +Document::getTransformInputModels() { std::vector<Model *> models; @@ -733,19 +733,24 @@ TransformId id = "vamp:match-vamp-plugin:match:path"; //!!! configure - ModelTransformerFactory *factory = ModelTransformerFactory::getInstance(); + TransformFactory *tf = TransformFactory::getInstance(); - PluginTransformer::ExecutionContext context = - factory->getDefaultContextForTransformer(id, aggregate); - context.stepSize = context.blockSize/2; + Transform transform = tf->getDefaultTransformFor + (id, aggregate->getSampleRate()); - QString args = "<plugin param-serialise=\"1\"/>"; + transform.setStepSize(transform.getBlockSize()/2); + transform.setParameter("serialise", 1); - Model *transformOutput = factory->transform(id, aggregate, context, args); +//!!! QString args = "<plugin param-serialise=\"1\"/>"; +// Model *transformOutput = factory->transform(id, aggregate, context, args); + ModelTransformerFactory *mtf = ModelTransformerFactory::getInstance(); + + Model *transformOutput = mtf->transform(transform, aggregate); + if (!transformOutput) { - context.stepSize = 0; - transformOutput = factory->transform(id, aggregate, context, args); + transform.setStepSize(0); + transformOutput = mtf->transform(transform, aggregate); } SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> @@ -920,7 +925,7 @@ bool writeModel = true; bool haveDerivation = false; - if (rec.source && rec.transform != "") { + if (rec.source && rec.transform.getIdentifier() != "") { haveDerivation = true; } @@ -937,33 +942,8 @@ } if (haveDerivation) { - - QString extentsAttributes; - if (rec.context.startFrame != 0 || - rec.context.duration != 0) { - extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ") - .arg(rec.context.startFrame) - .arg(rec.context.duration); - } - - out << indent; - out << QString(" <derivation source=\"%1\" model=\"%2\" channel=\"%3\" domain=\"%4\" stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" transform=\"%9\"") - .arg(XmlExportable::getObjectExportId(rec.source)) - .arg(XmlExportable::getObjectExportId(i->first)) - .arg(rec.context.channel) - .arg(rec.context.domain) - .arg(rec.context.stepSize) - .arg(rec.context.blockSize) - .arg(extentsAttributes) - .arg(int(rec.context.windowType)) - .arg(XmlExportable::encodeEntities(rec.transform)); - - if (rec.configurationXml != "") { - out << ">\n " + indent + rec.configurationXml - + "\n" + indent + " </derivation>\n"; - } else { - out << "/>\n"; - } + writeBackwardCompatibleDerivation(out, indent + " ", + i->first, rec); } //!!! We should probably own the PlayParameterRepository @@ -986,4 +966,82 @@ out << indent + "</data>\n"; } +void +Document::writeBackwardCompatibleDerivation(QTextStream &out, QString indent, + Model *targetModel, + const ModelRecord &rec) const +{ + // There is a lot of redundancy in the XML we output here, because + // we want it to work with older SV session file reading code as + // well. + // + // Formerly, a transform was described using a derivation element + // which set out the source and target models, execution context + // (step size, input channel etc) and transform id, containing a + // plugin element which set out the transform parameters and so + // on. (The plugin element came from a "configurationXml" string + // obtained from PluginXml.) + // + // This has been replaced by a derivation element setting out the + // source and target models and input channel, containing a + // transform element which sets out everything in the Transform. + // + // In order to retain compatibility with older SV code, however, + // we have to write out the same stuff into the derivation as + // before, and manufacture an appropriate plugin element as well + // as the transform element. In order that newer code knows it's + // dealing with a newer format, we will also write an attribute + // 'type="transform"' in the derivation element. + const Transform &transform = rec.transform; + + // Just for reference, this is what we would write if we didn't + // have to be backward compatible: + // + // out << indent + // << QString("<derivation type=\"transform\" source=\"%1\" " + // "model=\"%2\" channel=\"%3\">\n") + // .arg(XmlExportable::getObjectExportId(rec.source)) + // .arg(XmlExportable::getObjectExportId(targetModel)) + // .arg(rec.channel); + // + // transform.toXml(out, indent + " "); + // + // out << indent << "</derivation>\n"; + // + // Unfortunately, we can't just do that. So we do this... + + QString extentsAttributes; + if (transform.getStartTime() != RealTime::zeroTime || + transform.getDuration() != RealTime::zeroTime) { + extentsAttributes = QString("startFrame=\"%1\" duration=\"%2\" ") + .arg(RealTime::realTime2Frame(transform.getStartTime(), + targetModel->getSampleRate())) + .arg(RealTime::realTime2Frame(transform.getDuration(), + targetModel->getSampleRate())); + } + + out << indent; + out << QString("<derivation type=\"transform\" source=\"%1\" " + "model=\"%2\" channel=\"%3\" domain=\"%4\" " + "stepSize=\"%5\" blockSize=\"%6\" %7windowType=\"%8\" " + "transform=\"%9\">\n") + .arg(XmlExportable::getObjectExportId(rec.source)) + .arg(XmlExportable::getObjectExportId(targetModel)) + .arg(rec.channel) + .arg(TransformFactory::getInstance()->getTransformInputDomain + (transform.getIdentifier())) + .arg(transform.getStepSize()) + .arg(transform.getBlockSize()) + .arg(extentsAttributes) + .arg(int(transform.getWindowType())) + .arg(XmlExportable::encodeEntities(transform.getIdentifier())); + + transform.toXml(out, indent + " "); + + out << indent << " " + << TransformFactory::getInstance()->getPluginConfigurationXml(transform); + + out << indent << "</derivation>\n"; +} + Modified: sonic-visualiser/branches/transforms/framework/Document.h =================================================================== --- sonic-visualiser/branches/transforms/framework/Document.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/framework/Document.h 2007-12-07 16:45:27 UTC (rev 893) @@ -141,7 +141,7 @@ */ const WaveFileModel *getMainModel() const { return m_mainModel; } - std::vector<Model *> getTransformerInputModels(); + std::vector<Model *> getTransformInputModels(); /** * Add a derived model associated with the given transform, @@ -319,6 +319,8 @@ void removeFromLayerViewMap(Layer *, View *); QString getUniqueLayerName(QString candidate); + void writeBackwardCompatibleDerivation(QTextStream &, QString, Model *, + const ModelRecord &) const; /** * And these are the layers. We also control the lifespans of Modified: sonic-visualiser/branches/transforms/framework/SVFileReader.cpp =================================================================== --- sonic-visualiser/branches/transforms/framework/SVFileReader.cpp 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/framework/SVFileReader.cpp 2007-12-07 16:45:27 UTC (rev 893) @@ -32,6 +32,8 @@ #include "data/model/TextModel.h" #include "data/model/ImageModel.h" +#include "plugin/transform/TransformFactory.h" + #include "view/Pane.h" #include "Document.h" @@ -53,6 +55,7 @@ m_currentDerivedModel(0), m_currentDerivedModelId(-1), m_currentPlayParameters(0), + m_currentTransformSource(0), m_datasetSeparator(" "), m_inRow(false), m_inLayer(false), @@ -136,6 +139,11 @@ // row // view // window + // plugin + // transform + // selections + // selection + // measurement if (name == "sv") { @@ -212,6 +220,14 @@ ok = readMeasurement(attributes); + } else if (name == "transform") { + + ok = readTransform(attributes); + + } else if (name == "parameter") { + + ok = readParameter(attributes); + } else { std::cerr << "WARNING: SV-XML: Unexpected element \"" << name.toLocal8Bit().data() << "\"" << std::endl; @@ -286,24 +302,25 @@ << " as target, not regenerating" << std::endl; } else { m_currentDerivedModel = m_models[m_currentDerivedModelId] = - m_document->addDerivedModel(m_currentTransformer, - m_currentTransformerSource, - m_currentTransformerContext, - m_currentTransformerConfiguration); + m_document->addDerivedModel + (m_currentTransform, + ModelTransformer::Input(m_currentTransformSource, + m_currentTransformChannel)); } } else { - m_document->addDerivedModel(m_currentTransformer, - m_currentTransformerSource, - m_currentTransformerContext, - m_currentDerivedModel, - m_currentTransformerConfiguration); + m_document->addDerivedModel + (m_currentTransform, + ModelTransformer::Input(m_currentTransformSource, + m_currentTransformChannel), + m_currentDerivedModel); } m_addedModels.insert(m_currentDerivedModel); m_currentDerivedModel = 0; m_currentDerivedModelId = -1; - m_currentTransformer = ""; - m_currentTransformerConfiguration = ""; + m_currentTransformSource = 0; + m_currentTransform = Transform(); + m_currentTransformChannel = -1; } else if (name == "row") { m_inRow = false; @@ -993,8 +1010,6 @@ return false; } - QString transform = attributes.value("transform"); - if (haveModel(modelId)) { m_currentDerivedModel = m_models[modelId]; } else { @@ -1009,32 +1024,44 @@ sourceId = attributes.value("source").trimmed().toInt(&sourceOk); if (sourceOk && haveModel(sourceId)) { - m_currentTransformerSource = m_models[sourceId]; + m_currentTransformSource = m_models[sourceId]; } else { - m_currentTransformerSource = m_document->getMainModel(); + m_currentTransformSource = m_document->getMainModel(); } - m_currentTransformer = transform; - m_currentTransformerConfiguration = ""; + m_currentTransform = Transform(); - m_currentTransformerContext = PluginTransformer::ExecutionContext(); - bool ok = false; int channel = attributes.value("channel").trimmed().toInt(&ok); - if (ok) m_currentTransformerContext.channel = channel; + if (ok) m_currentTransformChannel = channel; + else m_currentTransformChannel = -1; - int domain = attributes.value("domain").trimmed().toInt(&ok); - if (ok) m_currentTransformerContext.domain = Vamp::Plugin::InputDomain(domain); + QString type = attributes.value("type"); + if (type == "transform") { + m_currentTransformIsNewStyle = true; + return true; + } else { + m_currentTransformIsNewStyle = false; + std::cerr << "NOTE: SV-XML: Reading old-style derivation element" + << std::endl; + } + + QString transformId = attributes.value("transform"); + + m_currentTransform.setIdentifier(transformId); + int stepSize = attributes.value("stepSize").trimmed().toInt(&ok); - if (ok) m_currentTransformerContext.stepSize = stepSize; + if (ok) m_currentTransform.setStepSize(stepSize); int blockSize = attributes.value("blockSize").trimmed().toInt(&ok); - if (ok) m_currentTransformerContext.blockSize = blockSize; + if (ok) m_currentTransform.setBlockSize(blockSize); int windowType = attributes.value("windowType").trimmed().toInt(&ok); - if (ok) m_currentTransformerContext.windowType = WindowType(windowType); + if (ok) m_currentTransform.setWindowType(WindowType(windowType)); + if (!m_currentTransformSource) return true; + QString startFrameStr = attributes.value("startFrame"); QString durationStr = attributes.value("duration"); @@ -1050,9 +1077,14 @@ if (!ok) duration = 0; } - m_currentTransformerContext.startFrame = startFrame; - m_currentTransformerContext.duration = duration; + m_currentTransform.setStartTime + (RealTime::frame2RealTime + (startFrame, m_currentTransformSource->getSampleRate())); + m_currentTransform.setDuration + (RealTime::frame2RealTime + (duration, m_currentTransformSource->getSampleRate())); + return true; } @@ -1119,6 +1151,10 @@ return false; } + if (!m_currentPlayParameters && m_currentTransformIsNewStyle) { + return true; + } + QString configurationXml = "<plugin"; for (int i = 0; i < attributes.length(); ++i) { @@ -1132,13 +1168,48 @@ if (m_currentPlayParameters) { m_currentPlayParameters->setPlayPluginConfiguration(configurationXml); } else { - m_currentTransformerConfiguration += configurationXml; + TransformFactory::getInstance()-> + setParametersFromPluginConfigurationXml(m_currentTransform, + configurationXml); } return true; } bool +SVFileReader::readTransform(const QXmlAttributes &attributes) +{ + if (m_currentDerivedModelId < 0) { + std::cerr << "WARNING: SV-XML: Transform found outside derivation" << std::endl; + return false; + } + + m_currentTransform.setFromXmlAttributes(attributes); + return true; +} + +bool +SVFileReader::readParameter(const QXmlAttributes &attributes) +{ + if (m_currentDerivedModelId < 0) { + std::cerr << "WARNING: SV-XML: Parameter found outside derivation" << std::endl; + return false; + } + + QString name = attributes.value("name"); + if (name == "") { + std::cerr << "WARNING: SV-XML: Ignoring nameless transform parameter" + << std::endl; + return false; + } + + float value = attributes.value("value").trimmed().toFloat(); + + m_currentTransform.setParameter(name, value); + return true; +} + +bool SVFileReader::readSelection(const QXmlAttributes &attributes) { bool ok; Modified: sonic-visualiser/branches/transforms/framework/SVFileReader.h =================================================================== --- sonic-visualiser/branches/transforms/framework/SVFileReader.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/framework/SVFileReader.h 2007-12-07 16:45:27 UTC (rev 893) @@ -18,7 +18,6 @@ #include "layer/LayerFactory.h" #include "plugin/transform/Transform.h" -#include "plugin/transform/PluginTransformer.h" #include <QXmlDefaultHandler> @@ -89,10 +88,21 @@ a derivation element, and no model element should appear for it at all. --> - <derivation source="0" model="2" transform="..." ...> - <plugin id="..." ... /> + <derivation type="transform" source="0" model="2" channel="-1"> + <transform id="vamp:soname:pluginid:output" ... /> </derivation> + <!-- Note that the derivation element just described replaces + this earlier formulation, which had more attributes in the + derivation element and a plugin element describing plugin + parameters and properties. What we actually read and + write these days is a horrid composite of the two formats, + for backward compatibility reasons. --> + + <derivation source="0" model="2" transform="vamp:soname:pluginid:output" ...> + <plugin id="pluginid" ... /> + </derivation> + <!-- The playparameters element lists playback settings for a model. --> @@ -195,6 +205,8 @@ bool readDerivation(const QXmlAttributes &); bool readPlayParameters(const QXmlAttributes &); bool readPlugin(const QXmlAttributes &); + bool readTransform(const QXmlAttributes &); + bool readParameter(const QXmlAttributes &); bool readSelection(const QXmlAttributes &); bool readMeasurement(const QXmlAttributes &); void addUnaddedModels(); @@ -216,10 +228,10 @@ Model *m_currentDerivedModel; int m_currentDerivedModelId; PlayParameters *m_currentPlayParameters; - QString m_currentTransformer; - Model *m_currentTransformerSource; - PluginTransformer::ExecutionContext m_currentTransformerContext; - QString m_currentTransformerConfiguration; + Transform m_currentTransform; + Model *m_currentTransformSource; + int m_currentTransformChannel; + bool m_currentTransformIsNewStyle; QString m_datasetSeparator; bool m_inRow; bool m_inLayer; Modified: sonic-visualiser/branches/transforms/plugin/transform/FeatureExtractionModelTransformer.cpp =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/FeatureExtractionModelTransformer.cpp 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/FeatureExtractionModelTransformer.cpp 2007-12-07 16:45:27 UTC (rev 893) @@ -29,18 +29,20 @@ #include "data/model/FFTModel.h" #include "data/model/WaveFileModel.h" +#include "TransformFactory.h" + #include <QMessageBox> #include <iostream> -FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input input, +FeatureExtractionModelTransformer::FeatureExtractionModelTransformer(Input in, const Transform &transform) : - ModelTransformer(input), + ModelTransformer(in, transform), m_plugin(0), m_descriptor(0), m_outputFeatureNo(0) { -// std::cerr << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << pluginId.toStdString() << ", outputName " << outputName.toStdString() << std::endl; +// std::cerr << "FeatureExtractionModelTransformer::FeatureExtractionModelTransformer: plugin " << pluginId.toStdString() << ", outputName " << m_transform.getOutput().toStdString() << std::endl; QString pluginId = transform.getPluginIdentifier(); @@ -106,7 +108,7 @@ } for (size_t i = 0; i < outputs.size(); ++i) { - if (outputName == "" || + if (m_transform.getOutput() == "" || outputs[i].identifier == m_transform.getOutput().toStdString()) { m_outputFeatureNo = i; m_descriptor = new Vamp::Plugin::OutputDescriptor @@ -118,7 +120,7 @@ if (!m_descriptor) { std::cerr << "FeatureExtractionModelTransformer: Plugin \"" << pluginId.toStdString() << "\" has no output named \"" - << outputName.toStdString() << "\"" << std::endl; + << m_transform.getOutput().toStdString() << "\"" << std::endl; return; } @@ -306,17 +308,17 @@ } } - long startFrame = m_input->getStartFrame(); - long endFrame = m_input->getEndFrame(); + long startFrame = m_input.getModel()->getStartFrame(); + long endFrame = m_input.getModel()->getEndFrame(); - Vamp::RealTime contextStartTime = m_transform.getStartTime(); - Vamp::RealTime contextDuration = m_transform.getDuration(); + RealTime contextStartRT = m_transform.getStartTime(); + RealTime contextDurationRT = m_transform.getDuration(); long contextStart = - Vamp::RealTime::realTime2Frame(contextStartTime, sampleRate); + RealTime::realTime2Frame(contextStartRT, sampleRate); long contextDuration = - Vamp::RealTime::realTime2Frame(contextDuration, sampleRate); + RealTime::realTime2Frame(contextDurationRT, sampleRate); if (contextStart == 0 || contextStart < startFrame) { contextStart = startFrame; @@ -353,7 +355,7 @@ (((blockFrame - contextStart) / stepSize) * 99) / (contextDuration / stepSize); - // channelCount is either m_input->channelCount or 1 + // channelCount is either m_input.getModel()->channelCount or 1 for (size_t ch = 0; ch < channelCount; ++ch) { if (frequencyDomain) { @@ -447,7 +449,7 @@ FeatureExtractionModelTransformer::addFeature(size_t blockFrame, const Vamp::Plugin::Feature &feature) { - size_t inputRate = m_input->getSampleRate(); + size_t inputRate = m_input.getModel()->getSampleRate(); // std::cerr << "FeatureExtractionModelTransformer::addFeature(" // << blockFrame << ")" << std::endl; Modified: sonic-visualiser/branches/transforms/plugin/transform/FeatureExtractionModelTransformer.h =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/FeatureExtractionModelTransformer.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/FeatureExtractionModelTransformer.h 2007-12-07 16:45:27 UTC (rev 893) @@ -18,6 +18,10 @@ #include "ModelTransformer.h" +#include <vamp-sdk/Plugin.h> + +#include <iostream> + class DenseTimeValueModel; class FeatureExtractionModelTransformer : public ModelTransformer Modified: sonic-visualiser/branches/transforms/plugin/transform/ModelTransformer.h =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/ModelTransformer.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/ModelTransformer.h 2007-12-07 16:45:27 UTC (rev 893) @@ -20,6 +20,8 @@ #include "data/model/Model.h" +#include "Transform.h" + /** * A ModelTransformer turns one data model into another. * @@ -42,8 +44,12 @@ public: Input(Model *m) : m_model(m), m_channel(-1) { } Input(Model *m, int c) : m_model(m), m_channel(c) { } + Model *getModel() const { return m_model; } + void setModel(Model *m) { m_model = m; } + int getChannel() const { return m_channel; } + void setChannel(int c) { m_channel = c; } protected: Model *m_model; Modified: sonic-visualiser/branches/transforms/plugin/transform/ModelTransformerFactory.cpp =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/ModelTransformerFactory.cpp 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/ModelTransformerFactory.cpp 2007-12-07 16:45:27 UTC (rev 893) @@ -51,7 +51,8 @@ } bool -ModelTransformerFactory::getChannelRange(TransformId identifier, Vamp::PluginBase *plugin, +ModelTransformerFactory::getChannelRange(TransformId identifier, + Vamp::PluginBase *plugin, int &minChannels, int &maxChannels) { Vamp::Plugin *vp = 0; @@ -66,7 +67,7 @@ } } -Model * +ModelTransformer::Input ModelTransformerFactory::getConfigurationForTransform(Transform &transform, const std::vector<Model *> &candidateInputModels, Model *defaultInputModel, @@ -74,8 +75,10 @@ size_t startFrame, size_t duration) { - if (candidateInputModels.empty()) return 0; + ModelTransformer::Input input(0); + if (candidateInputModels.empty()) return input; + //!!! This will need revision -- we'll have to have a callback //from the dialog for when the candidate input model is changed, //as we'll need to reinitialise the channel settings in the dialog @@ -103,7 +106,7 @@ QString outputDescription = ""; bool ok = false; - configurationXml = m_lastConfigurations[identifier]; + QString configurationXml = m_lastConfigurations[transform.getIdentifier()]; std::cerr << "last configuration: " << configurationXml.toStdString() << std::endl; @@ -183,11 +186,13 @@ if (plugin) { // Ensure block size etc are valid - TransformFactory::makeConsistentWithPlugin(transform, plugin); + TransformFactory::getInstance()-> + makeContextConsistentWithPlugin(transform, plugin); // Prepare the plugin with any existing parameters already // found in the transform - TransformFactory::setPluginParameters(transform, plugin); + TransformFactory::getInstance()-> + setPluginParameters(transform, plugin); // For this interactive usage, we want to override those with // whatever the user chose last time around @@ -200,7 +205,8 @@ } int minChannels = 1, maxChannels = sourceChannels; - getChannelRange(identifier, plugin, minChannels, maxChannels); + getChannelRange(transform.getIdentifier(), plugin, + minChannels, maxChannels); int targetChannels = sourceChannels; if (!effect) { @@ -208,7 +214,7 @@ if (sourceChannels > maxChannels) targetChannels = maxChannels; } - int defaultChannel = context.channel; + int defaultChannel = -1; //!!! no longer saved! [was context.channel] PluginParameterDialog *dialog = new PluginParameterDialog(plugin); @@ -247,30 +253,41 @@ } // Write parameters back to transform object - TransformFactory::setParametersFromPlugin(transform, plugin); + TransformFactory::getInstance()-> + setParametersFromPlugin(transform, plugin); - //!!! The channel really needs to be bundled up with the model - // as some sort of transform "input source" -- it isn't really - // part of the transform. -// context.channel = dialog->getChannel(); + input.setChannel(dialog->getChannel()); //!!! The dialog ought to be taking & returning transform - //objects rather than passing around all this misc stuff, but - //that's for tomorrow (whenever that may be) + //objects and input objects and stuff rather than passing + //around all this misc stuff, but that's for tomorrow + //(whenever that may be) if (startFrame != 0 || duration != 0) { if (dialog->getSelectionOnly()) { - context.startFrame = startFrame; - context.duration = duration; + transform.setStartTime(RealTime::frame2RealTime + (startFrame, inputModel->getSampleRate())); + transform.setDuration(RealTime::frame2RealTime + (duration, inputModel->getSampleRate())); } } - dialog->getProcessingParameters(context.stepSize, - context.blockSize, - context.windowType); + size_t stepSize = 0, blockSize = 0; + WindowType windowType = HanningWindow; - context.makeConsistentWithPlugin(plugin); + dialog->getProcessingParameters(stepSize, + blockSize, + windowType); + transform.setStepSize(stepSize); + transform.setBlockSize(blockSize); + transform.setWindowType(windowType); + + TransformFactory::getInstance()-> + makeContextConsistentWithPlugin(transform, plugin); + + configurationXml = PluginXml(plugin).toXmlString(); + delete dialog; if (effect && source) { @@ -280,9 +297,12 @@ } } - if (ok) m_lastConfigurations[identifier] = configurationXml; + if (ok) { + m_lastConfigurations[transform.getIdentifier()] = configurationXml; + input.setModel(inputModel); + } - return ok ? inputModel : 0; + return input; } /*!!! PluginTransformer::ExecutionContext @@ -354,7 +374,7 @@ QString imn = input.getModel()->objectName(); QString trn = TransformFactory::getInstance()->getTransformFriendlyName - (identifier); + (transform.getIdentifier()); if (imn != "") { if (trn != "") { model->setObjectName(tr("%1: %2").arg(imn).arg(trn)); Modified: sonic-visualiser/branches/transforms/plugin/transform/ModelTransformerFactory.h =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/ModelTransformerFactory.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/ModelTransformerFactory.h 2007-12-07 16:45:27 UTC (rev 893) @@ -39,18 +39,20 @@ /** * Fill out the configuration for the given transform (by asking - * the user, most likely). Returns the selected input model if - * the transform is acceptable, 0 if the operation should be - * cancelled. Audio callback play source may be used to audition - * effects plugins, if provided. + * the user, most likely). Returns the selected input model and + * channel if the transform is acceptable, or an input with a null + * model if the operation should be cancelled. Audio callback + * play source may be used to audition effects plugins, if + * provided. */ - Model *getConfigurationForTransform(Transform &transform, - const std::vector<Model *> &candidateInputModels, - Model *defaultInputModel, - AudioCallbackPlaySource *source = 0, - size_t startFrame = 0, - size_t duration = 0); - + ModelTransformer::Input + getConfigurationForTransform(Transform &transform, + const std::vector<Model *> &candidateInputModels, + Model *defaultInputModel, + AudioCallbackPlaySource *source = 0, + size_t startFrame = 0, + size_t duration = 0); + /** * Get the default execution context for the given transform * and input model (if known). Modified: sonic-visualiser/branches/transforms/plugin/transform/RealTimeEffectModelTransformer.cpp =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/RealTimeEffectModelTransformer.cpp 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/RealTimeEffectModelTransformer.cpp 2007-12-07 16:45:27 UTC (rev 893) @@ -25,14 +25,17 @@ #include "data/model/WritableWaveFileModel.h" #include "data/model/WaveFileModel.h" +#include "TransformFactory.h" + #include <iostream> -RealTimeEffectModelTransformer::RealTimeEffectModelTransformer(Input input, - const Transform &transform) - ModelTransformer(input, transform), +RealTimeEffectModelTransformer::RealTimeEffectModelTransformer(Input in, + const Transform &transform) : + ModelTransformer(in, transform), m_plugin(0) { - m_units = TransformFactory::getInstance()->getTransformUnits(transform); + m_units = TransformFactory::getInstance()->getTransformUnits + (transform.getIdentifier()); m_outputNo = (transform.getOutput() == "A") ? -1 : transform.getOutput().toInt(); @@ -65,7 +68,7 @@ return; } - TransformFactory::setPluginParameters(m_transform, m_plugin); + TransformFactory::getInstance()->setPluginParameters(m_transform, m_plugin); if (m_outputNo >= 0 && m_outputNo >= int(m_plugin->getControlOutputCount())) { @@ -90,7 +93,7 @@ SparseTimeValueModel *model = new SparseTimeValueModel (input->getSampleRate(), m_transform.getBlockSize(), 0.0, 0.0, false); - if (units != "") model->setScaleUnits(units); + if (m_units != "") model->setScaleUnits(m_units); m_output = model; } @@ -132,23 +135,23 @@ size_t sampleRate = input->getSampleRate(); size_t channelCount = input->getChannelCount(); - if (!wwfm && m_context.channel != -1) channelCount = 1; + if (!wwfm && m_input.getChannel() != -1) channelCount = 1; long blockSize = m_plugin->getBufferSize(); float **inbufs = m_plugin->getAudioInputBuffers(); - long startFrame = m_input->getStartFrame(); - long endFrame = m_input->getEndFrame(); + long startFrame = m_input.getModel()->getStartFrame(); + long endFrame = m_input.getModel()->getEndFrame(); - Vamp::RealTime contextStartTime = m_transform.getStartTime(); - Vamp::RealTime contextDuration = m_transform.getDuration(); + RealTime contextStartRT = m_transform.getStartTime(); + RealTime contextDurationRT = m_transform.getDuration(); long contextStart = - Vamp::RealTime::realTime2Frame(contextStartTime, sampleRate); + RealTime::realTime2Frame(contextStartRT, sampleRate); long contextDuration = - Vamp::RealTime::realTime2Frame(contextDuration, sampleRate); + RealTime::realTime2Frame(contextDurationRT, sampleRate); if (contextStart == 0 || contextStart < startFrame) { contextStart = startFrame; @@ -181,7 +184,7 @@ if (channelCount == 1) { if (inbufs && inbufs[0]) { got = input->getData - (m_context.channel, blockFrame, blockSize, inbufs[0]); + (m_input.getChannel(), blockFrame, blockSize, inbufs[0]); while (got < blockSize) { inbufs[0][got++] = 0.0; } Modified: sonic-visualiser/branches/transforms/plugin/transform/RealTimeEffectModelTransformer.h =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/RealTimeEffectModelTransformer.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/RealTimeEffectModelTransformer.h 2007-12-07 16:45:27 UTC (rev 893) @@ -16,12 +16,12 @@ #ifndef _REAL_TIME_PLUGIN_TRANSFORMER_H_ #define _REAL_TIME_PLUGIN_TRANSFORMER_H_ -#include "PluginTransformer.h" +#include "ModelTransformer.h" #include "plugin/RealTimePluginInstance.h" class DenseTimeValueModel; -class RealTimeEffectModelTransformer : public PluginTransformer +class RealTimeEffectModelTransformer : public ModelTransformer { public: RealTimeEffectModelTransformer(Input input, Modified: sonic-visualiser/branches/transforms/plugin/transform/Transform.cpp =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/Transform.cpp 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/Transform.cpp 2007-12-07 16:45:27 UTC (rev 893) @@ -19,6 +19,17 @@ #include "plugin/FeatureExtractionPluginFactory.h" +#include <QXmlAttributes> + +#include <QDomDocument> +#include <QDomElement> +#include <QDomNamedNodeMap> +#include <QDomAttr> + +#include <QTextStream> + +#include <iostream> + Transform::Transform() : m_stepSize(0), m_blockSize(0), @@ -27,6 +38,70 @@ { } +Transform::Transform(QString xml) : + m_stepSize(0), + m_blockSize(0), + m_windowType(HanningWindow), + m_sampleRate(0) +{ + QDomDocument doc; + + QString error; + int errorLine; + int errorColumn; + + if (!doc.setContent(xml, false, &error, &errorLine, &errorColumn)) { + std::cerr << "Transform::Transform: Error in parsing XML: " + << error.toStdString() << " at line " << errorLine + << ", column " << errorColumn << std::endl; + std::cerr << "Input follows:" << std::endl; + std::cerr << xml.toStdString() << std::endl; + std::cerr << "Input ends." << std::endl; + return; + } + + QDomElement transformElt = doc.firstChildElement("transform"); + QDomNamedNodeMap attrNodes = transformElt.attributes(); + QXmlAttributes attrs; + + for (unsigned int i = 0; i < attrNodes.length(); ++i) { + QDomAttr attr = attrNodes.item(i).toAttr(); + if (!attr.isNull()) attrs.append(attr.name(), "", "", attr.value()); + } + + setFromXmlAttributes(attrs); + + for (QDomElement paramElt = transformElt.firstChildElement("parameter"); + !paramElt.isNull(); + paramElt = paramElt.nextSiblingElement("parameter")) { + + QDomNamedNodeMap paramAttrs = paramElt.attributes(); + + QDomAttr nameAttr = paramAttrs.namedItem("name").toAttr(); + if (nameAttr.isNull() || nameAttr.value() == "") continue; + + QDomAttr valueAttr = paramAttrs.namedItem("value").toAttr(); + if (valueAttr.isNull() || valueAttr.value() == "") continue; + + setParameter(nameAttr.value(), valueAttr.value().toFloat()); + } + + for (QDomElement configElt = transformElt.firstChildElement("configuration"); + !configElt.isNull(); + configElt = configElt.nextSiblingElement("configuration")) { + + QDomNamedNodeMap configAttrs = configElt.attributes(); + + QDomAttr nameAttr = configAttrs.namedItem("name").toAttr(); + if (nameAttr.isNull() || nameAttr.value() == "") continue; + + QDomAttr valueAttr = configAttrs.namedItem("value").toAttr(); + if (valueAttr.isNull() || valueAttr.value() == "") continue; + + setConfigurationValue(nameAttr.value(), valueAttr.value()); + } +} + Transform::~Transform() { } @@ -47,6 +122,18 @@ m_sampleRate == t.m_sampleRate; } +void +Transform::setIdentifier(TransformId id) +{ + m_id = id; +} + +TransformId +Transform::getIdentifier() const +{ + return m_id; +} + QString Transform::createIdentifier(QString type, QString soName, QString label, QString output) @@ -89,8 +176,212 @@ return m_id.section(':', 3); } +const Transform::ParameterMap & +Transform::getParameters() const +{ + return m_parameters; +} + void -Transform::toXml(QTextStream &stream, QString indent, QString extraAttributes) const +Transform::setParameters(const ParameterMap &pm) { + m_parameters = pm; +} + +void +Transform::setParameter(QString name, float value) +{ + std::cerr << "Transform::setParameter(" << name.toStdString() + << ") -> " << value << std::endl; + m_parameters[name] = value; +} + +const Transform::ConfigurationMap & +Transform::getConfiguration() const +{ + return m_configuration; +} + +void +Transform::setConfiguration(const ConfigurationMap &cm) +{ + m_configuration = cm; +} + +void +Transform::setConfigurationValue(QString name, QString value) +{ + std::cerr << "Transform::setConfigurationValue(" << name.toStdString() + << ") -> " << value.toStdString() << std::endl; + m_configuration[name] = value; +} + +QString +Transform::getProgram() const +{ + return m_program; +} + +void +Transform::setProgram(QString program) +{ + m_program = program; +} + +size_t +Transform::getStepSize() const +{ + return m_stepSize; } + +void +Transform::setStepSize(size_t s) +{ + m_stepSize = s; +} + +size_t +Transform::getBlockSize() const +{ + return m_blockSize; +} + +void +Transform::setBlockSize(size_t s) +{ + m_blockSize = s; +} + +WindowType +Transform::getWindowType() const +{ + return m_windowType; +} + +void +Transform::setWindowType(WindowType type) +{ + m_windowType = type; +} + +RealTime +Transform::getStartTime() const +{ + return m_startTime; +} + +void +Transform::setStartTime(RealTime t) +{ + m_startTime = t; +} + +RealTime +Transform::getDuration() const +{ + return m_duration; +} + +void +Transform::setDuration(RealTime d) +{ + m_duration = d; +} + +float +Transform::getSampleRate() const +{ + return m_sampleRate; +} + +void +Transform::setSampleRate(float rate) +{ + m_sampleRate = rate; +} + +void +Transform::toXml(QTextStream &out, QString indent, QString extraAttributes) const +{ + out << indent; + + bool haveContent = true; + if (m_parameters.empty() && m_configuration.empty()) haveContent = false; + + out << QString("<transform id=\"%1\" program=\"%2\" stepSize=\"%3\" blockSize=\"%4\" windowType=\"%5\" startTime=\"%6\" duration=\"%7\" sampleRate=\"%8\" %9") + .arg(encodeEntities(m_id)) + .arg(encodeEntities(m_program)) + .arg(m_stepSize) + .arg(m_blockSize) + .arg(encodeEntities(Window<float>::getNameForType(m_windowType).c_str())) + .arg(encodeEntities(m_startTime.toString().c_str())) + .arg(encodeEntities(m_duration.toString().c_str())) + .arg(m_sampleRate) + .arg(extraAttributes); + + if (haveContent) { + + out << ">\n"; + + for (ParameterMap::const_iterator i = m_parameters.begin(); + i != m_parameters.end(); ++i) { + out << indent << " " + << QString("<parameter name=\"%1\" value=\"%2\"/>\n") + .arg(encodeEntities(i->first)) + .arg(i->second); + } + + for (ConfigurationMap::const_iterator i = m_configuration.begin(); + i != m_configuration.end(); ++i) { + out << indent << " " + << QString("<configuration name=\"%1\" value=\"%2\"/>\n") + .arg(encodeEntities(i->first)) + .arg(encodeEntities(i->second)); + } + + out << indent << "</transform>\n"; + + } else { + + out << "/>\n"; + } +} + +void +Transform::setFromXmlAttributes(const QXmlAttributes &attrs) +{ + if (attrs.value("id") != "") { + setIdentifier(attrs.value("id")); + } + + if (attrs.value("program") != "") { + setProgram(attrs.value("program")); + } + + if (attrs.value("stepSize") != "") { + setStepSize(attrs.value("stepSize").toInt()); + } + + if (attrs.value("blockSize") != "") { + setBlockSize(attrs.value("blockSize").toInt()); + } + + if (attrs.value("windowType") != "") { + setWindowType(Window<float>::getTypeForName + (attrs.value("windowType").toStdString())); + } + + if (attrs.value("startTime") != "") { + setStartTime(RealTime::fromString(attrs.value("startTime").toStdString())); + } + + if (attrs.value("duration") != "") { + setStartTime(RealTime::fromString(attrs.value("duration").toStdString())); + } + + if (attrs.value("sampleRate") != "") { + setSampleRate(attrs.value("sampleRate").toFloat()); + } +} + Modified: sonic-visualiser/branches/transforms/plugin/transform/Transform.h =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/Transform.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/Transform.h 2007-12-07 16:45:27 UTC (rev 893) @@ -18,13 +18,14 @@ #include "base/XmlExportable.h" #include "base/Window.h" +#include "base/RealTime.h" -#include <vamp-sdk/RealTime.h> - #include <QString> typedef QString TransformId; +class QXmlAttributes; + namespace Vamp { class PluginBase; } @@ -32,13 +33,32 @@ class Transform : public XmlExportable { public: + /** + * Construct a new Transform with default data and no identifier. + * The Transform object will be meaningless until some data and an + * identifier have been set on it. + * + * To construct a Transform for use with a particular transform + * identifier, use TransformFactory::getDefaultTransformFor. + */ Transform(); + + /** + * Construct a Transform by parsing the given XML data string. + * This is the inverse of toXml. + */ + Transform(QString xml); + virtual ~Transform(); - bool operator==(const Transform &); // only == if everything matches + /** + * Compare two Transforms. They only compare equal if every data + * element matches. + */ + bool operator==(const Transform &); - void setIdentifier(TransformId id) { m_id = id; } - TransformId getIdentifier() const { return m_id; } + void setIdentifier(TransformId id); + TransformId getIdentifier() const; void setPlugin(QString pluginIdentifier); void setOutput(QString output); @@ -51,39 +71,47 @@ typedef std::map<QString, float> ParameterMap; - const ParameterMap &getParameters() const { return m_parameters; } - void setParameters(const ParameterMap &pm) { m_parameters = pm; } + const ParameterMap &getParameters() const; + void setParameters(const ParameterMap &pm); + void setParameter(QString name, float value); typedef std::map<QString, QString> ConfigurationMap; - const ConfigurationMap &getConfiguration() const { return m_configuration; } - void setConfiguration(const ConfigurationMap &cm) { m_configuration = cm; } + const ConfigurationMap &getConfiguration() const; + void setConfiguration(const ConfigurationMap &cm); + void setConfigurationValue(QString name, QString value); - QString getProgram() const { return m_program; } - void setProgram(QString program) { m_program = program; } + QString getProgram() const; + void setProgram(QString program); - size_t getStepSize() const { return m_stepSize; } - void setStepSize(size_t s) { m_stepSize = s; } + size_t getStepSize() const; + void setStepSize(size_t s); - size_t getBlockSize() const { return m_blockSize; } - void setBlockSize(size_t s) { m_blockSize = s; } - - WindowType getWindowType() const { return m_windowType; } - void setWindowType(WindowType type) { m_windowType = type; } - - Vamp::RealTime getStartTime() const { return m_startTime; } - void setStartTime(Vamp::RealTime t) { m_startTime = t; } - - Vamp::RealTime getDuration() const { return m_duration; } // 0 -> all - void setDuration(Vamp::RealTime d) { m_duration = d; } + size_t getBlockSize() const; + void setBlockSize(size_t s); - float getSampleRate() const { return m_sampleRate; } // 0 -> as input - void setSampleRate(float rate) { m_sampleRate = rate; } + WindowType getWindowType() const; + void setWindowType(WindowType type); + + RealTime getStartTime() const; + void setStartTime(RealTime t); + + RealTime getDuration() const; // 0 -> all + void setDuration(RealTime d); + + float getSampleRate() const; // 0 -> as input + void setSampleRate(float rate); void toXml(QTextStream &stream, QString indent = "", QString extraAttributes = "") const; - static Transform fromXmlString(QString xml); + /** + * Set the main transform data from the given XML attributes. + * This does not set the parameters or configuration, which are + * exported to separate XML elements rather than attributes of the + * transform element. + */ + void setFromXmlAttributes(const QXmlAttributes &); protected: TransformId m_id; // pluginid:output, that is type:soname:label:output @@ -101,8 +129,8 @@ size_t m_stepSize; size_t m_blockSize; WindowType m_windowType; - Vamp::RealTime m_startTime; - Vamp::RealTime m_duration; + RealTime m_startTime; + RealTime m_duration; float m_sampleRate; }; Modified: sonic-visualiser/branches/transforms/plugin/transform/TransformDescription.h =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/TransformDescription.h 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/TransformDescription.h 2007-12-07 16:45:27 UTC (rev 893) @@ -37,6 +37,10 @@ * The friendly name is a shorter version of the name. * * The type is also intended to be user-readable, for use in menus. + * + * To obtain these objects, use + * TransformFactory::getAllTransformDescriptions and + * TransformFactory::getTransformDescription. */ struct TransformDescription Modified: sonic-visualiser/branches/transforms/plugin/transform/TransformFactory.cpp =================================================================== --- sonic-visualiser/branches/transforms/plugin/transform/TransformFactory.cpp 2007-12-07 16:26:58 UTC (rev 892) +++ sonic-visualiser/branches/transforms/plugin/transform/TransformFactory.cpp 2007-12-07 16:45:27 UTC (rev 893) @@ -28,6 +28,7 @@ #include <set> #include <QRegExp> +#include <QTextStream> TransformFactory * TransformFactory::m_instance = new TransformFactory; @@ -43,7 +44,7 @@ } TransformList -TransformFactory::getAllTransforms() +TransformFactory::getAllTransformDescriptions() { if (m_transforms.empty()) populateTransforms(); @@ -62,6 +63,18 @@ return list; } +TransformDescription +TransformFactory::getTransformDescription(TransformId id) +{ + if (m_transforms.empty()) populateTransforms(); + + if (m_transforms.find(id) == m_transforms.end()) { + return TransformDescription(); + } + + return m_transforms[id]; +} + std::vector<QString> TransformFactory::getAllTransformTypes() { @@ -217,7 +230,7 @@ } Vamp::Plugin *plugin = - factory->instantiatePlugin(pluginId, 48000); + factory->instantiatePlugin(pluginId, 44100); if (!plugin) { std::cerr << "WARNING: TransformFactory::populateTransforms: Failed to instantiate plugin " << pluginId.toLocal8Bit().data() << std::endl; @@ -423,6 +436,71 @@ } } + +Transform +TransformFactory::getDefaultTransformFor(TransformId id, size_t rate) +{ + Transform t; + t.setIdentifier(id); + if (rate != 0) t.setSampleRate(rate); + + Vamp::PluginBase *plugin = instantiatePluginFor(id, rate); + + if (plugin) { + setParametersFromPlugin(t, plugin); + makeContextConsistentWithPlugin(t, plugin); + delete plugin; + } + + return t; +} + +Vamp::PluginBase * +TransformFactory::instantiatePluginFor(TransformId identifier, size_t rate) +{ + Transform t; + t.setIdentifier(identifier); + if (rate == 0) rate = 44100; + QString pluginId = t.getPluginIdentifier(); + + Vamp::PluginBase *plugin = 0; + + if (t.getType() == Transform::FeatureExtraction) { + + FeatureExtractionPluginFactory *factory = + FeatureExtractionPluginFactory::instanceFor(pluginId); + + plugin = factory->instantiatePlugin(pluginId, rate); + + } else { + + ... [truncated message content] |