[Sv1-commits] SF.net SVN: sv1: [792] sonic-visualiser/trunk
Brought to you by:
cannam
From: <ca...@us...> - 2007-10-24 15:21:40
|
Revision: 792 http://sv1.svn.sourceforge.net/sv1/?rev=792&view=rev Author: cannam Date: 2007-10-24 08:21:38 -0700 (Wed, 24 Oct 2007) Log Message: ----------- * Hoist alignment model set/query up to Model, so any models can be aligned * Add Model::aboutToDelete and aboutToBeDeleted for management of models that are contained by or referred to by other models instead of only the document Modified Paths: -------------- sonic-visualiser/trunk/data/model/Model.cpp sonic-visualiser/trunk/data/model/Model.h sonic-visualiser/trunk/data/model/RangeSummarisableTimeValueModel.cpp sonic-visualiser/trunk/data/model/RangeSummarisableTimeValueModel.h sonic-visualiser/trunk/sv/document/Document.cpp sonic-visualiser/trunk/sv/document/Document.h Modified: sonic-visualiser/trunk/data/model/Model.cpp =================================================================== --- sonic-visualiser/trunk/data/model/Model.cpp 2007-10-22 14:24:31 UTC (rev 791) +++ sonic-visualiser/trunk/data/model/Model.cpp 2007-10-24 15:21:38 UTC (rev 792) @@ -14,6 +14,7 @@ */ #include "Model.h" +#include "AlignmentModel.h" #include "base/PlayParameterRepository.h" #include <QTextStream> @@ -26,6 +27,17 @@ { // std::cerr << "Model::~Model(" << this << ")" << std::endl; + if (!m_aboutToDelete) { + std::cerr << "NOTE: Model::~Model(" << this << ", \"" + << objectName().toStdString() << "\"): Model deleted " + << "with no aboutToDelete notification" << std::endl; + } + + if (m_alignment) { + m_alignment->aboutToDelete(); + delete m_alignment; + } + // Subclasses have to handle adding themselves to the repository, // if they want to be played. We can't do it from here because // the repository would be unable to tell whether we were playable @@ -34,6 +46,86 @@ } void +Model::setSourceModel(Model *model) +{ + if (m_sourceModel) { + disconnect(m_sourceModel, SIGNAL(aboutToBeDeleted()), + this, SLOT(sourceModelAboutToBeDeleted())); + } + + m_sourceModel = model; + + if (m_sourceModel) { + connect(m_sourceModel, SIGNAL(aboutToBeDeleted()), + this, SLOT(sourceModelAboutToBeDeleted())); + } +} + +void +Model::aboutToDelete() +{ + if (m_aboutToDelete) { + std::cerr << "WARNING: Model(" << this << ", \"" + << objectName().toStdString() << "\")::aboutToDelete: " + << "aboutToDelete called more than once for the same model" + << std::endl; + } + + emit aboutToBeDeleted(); + m_aboutToDelete = true; +} + +void +Model::sourceModelAboutToBeDeleted() +{ + m_sourceModel = 0; +} + +void +Model::setAlignment(AlignmentModel *alignment) +{ + if (m_alignment) { + m_alignment->aboutToDelete(); + delete m_alignment; + } + m_alignment = alignment; + connect(m_alignment, SIGNAL(completionChanged()), + this, SIGNAL(alignmentCompletionChanged())); +} + +const Model * +Model::getAlignmentReference() const +{ + if (!m_alignment) return 0; + return m_alignment->getReferenceModel(); +} + +size_t +Model::alignToReference(size_t frame) const +{ + if (!m_alignment) return frame; + return m_alignment->toReference(frame); +} + +size_t +Model::alignFromReference(size_t refFrame) const +{ + if (!m_alignment) return refFrame; + return m_alignment->fromReference(refFrame); +} + +int +Model::getAlignmentCompletion() const +{ + std::cerr << "Model::getAlignmentCompletion" << std::endl; + if (!m_alignment) return 100; + int completion = 0; + (void)m_alignment->isReady(&completion); + std::cerr << " -> " << completion << std::endl; + return completion; +} + +void Model::toXml(QTextStream &stream, QString indent, QString extraAttributes) const { Modified: sonic-visualiser/trunk/data/model/Model.h =================================================================== --- sonic-visualiser/trunk/data/model/Model.h 2007-10-22 14:24:31 UTC (rev 791) +++ sonic-visualiser/trunk/data/model/Model.h 2007-10-24 15:21:38 UTC (rev 792) @@ -24,6 +24,7 @@ typedef std::vector<float> SampleBlock; class ZoomConstraint; +class AlignmentModel; /** * Model is the base class for all data models that represent any sort @@ -114,7 +115,8 @@ * If this model was derived from another, return the model it was * derived from. The assumption is that the source model's * alignment will also apply to this model, unless some other - * property indicates otherwise. + * property (such as a specific alignment model set on this model) + * indicates otherwise. */ virtual Model *getSourceModel() const { return m_sourceModel; @@ -123,17 +125,51 @@ /** * Set the source model for this model. */ - //!!! No way to handle source model deletion &c yet - virtual void setSourceModel(Model *model) { - m_sourceModel = model; - } + virtual void setSourceModel(Model *model); + /** + * Specify an aligment between this model's timeline and that of a + * reference model. The alignment model records both the + * reference and the alignment. This model takes ownership of the + * alignment model. + */ + virtual void setAlignment(AlignmentModel *alignment); + + /** + * Return the reference model for the current alignment timeline, + * if any. + */ + virtual const Model *getAlignmentReference() const; + + /** + * Return the frame number of the reference model that corresponds + * to the given frame number in this model. + */ + virtual size_t alignToReference(size_t frame) const; + + /** + * Return the frame number in this model that corresponds to the + * given frame number of the reference model. + */ + virtual size_t alignFromReference(size_t referenceFrame) const; + + /** + * Return the completion percentage for the alignment model: 100 + * if there is no alignment model or it has been entirely + * calculated, or less than 100 if it is still being calculated. + */ + virtual int getAlignmentCompletion() const; + virtual void toXml(QTextStream &stream, QString indent = "", QString extraAttributes = "") const; virtual QString toDelimitedDataString(QString) const { return ""; } +public slots: + void aboutToDelete(); + void sourceModelAboutToBeDeleted(); + signals: /** * Emitted when a model has been edited (or more data retrieved @@ -155,14 +191,32 @@ */ void completionChanged(); + /** + * Emitted when the completion percentage changes for the + * calculation of this model's alignment model. + */ + void alignmentCompletionChanged(); + + /** + * Emitted when something notifies this model (through calling + * aboutToDelete() that it is about to delete it. Note that this + * depends on an external agent such as a Document object or + * owning model telling the model that it is about to delete it; + * there is nothing in the model to guarantee that this signal + * will be emitted before the actual deletion. + */ + void aboutToBeDeleted(); + protected: - Model() : m_sourceModel(0) { } + Model() : m_sourceModel(0), m_alignment(0), m_aboutToDelete(false) { } // Not provided. Model(const Model &); Model &operator=(const Model &); Model *m_sourceModel; + AlignmentModel *m_alignment; + bool m_aboutToDelete; }; #endif Modified: sonic-visualiser/trunk/data/model/RangeSummarisableTimeValueModel.cpp =================================================================== --- sonic-visualiser/trunk/data/model/RangeSummarisableTimeValueModel.cpp 2007-10-22 14:24:31 UTC (rev 791) +++ sonic-visualiser/trunk/data/model/RangeSummarisableTimeValueModel.cpp 2007-10-24 15:21:38 UTC (rev 792) @@ -15,48 +15,4 @@ #include "RangeSummarisableTimeValueModel.h" -#include "AlignmentModel.h" - #include <iostream> - -void -RangeSummarisableTimeValueModel::setAlignment(AlignmentModel *alignment) -{ - delete m_alignment; - m_alignment = alignment; - connect(m_alignment, SIGNAL(completionChanged()), - this, SIGNAL(alignmentCompletionChanged())); -} - -const Model * -RangeSummarisableTimeValueModel::getAlignmentReference() const -{ - if (!m_alignment) return 0; - return m_alignment->getReferenceModel(); -} - -size_t -RangeSummarisableTimeValueModel::alignToReference(size_t frame) const -{ - if (!m_alignment) return frame; - return m_alignment->toReference(frame); -} - -size_t -RangeSummarisableTimeValueModel::alignFromReference(size_t refFrame) const -{ - if (!m_alignment) return refFrame; - return m_alignment->fromReference(refFrame); -} - -int -RangeSummarisableTimeValueModel::getAlignmentCompletion() const -{ - std::cerr << "RangeSummarisableTimeValueModel::getAlignmentCompletion" << std::endl; - if (!m_alignment) return 100; - int completion = 0; - (void)m_alignment->isReady(&completion); - std::cerr << " -> " << completion << std::endl; - return completion; -} - Modified: sonic-visualiser/trunk/data/model/RangeSummarisableTimeValueModel.h =================================================================== --- sonic-visualiser/trunk/data/model/RangeSummarisableTimeValueModel.h 2007-10-22 14:24:31 UTC (rev 791) +++ sonic-visualiser/trunk/data/model/RangeSummarisableTimeValueModel.h 2007-10-24 15:21:38 UTC (rev 792) @@ -21,8 +21,6 @@ #include "DenseTimeValueModel.h" #include "base/ZoomConstraint.h" -class AlignmentModel; - /** * Base class for models containing dense two-dimensional data (value * against time) that may be meaningfully represented in a zoomed view @@ -35,7 +33,7 @@ Q_OBJECT public: - RangeSummarisableTimeValueModel() : m_alignment(0) { } + RangeSummarisableTimeValueModel() { } struct Range { @@ -73,18 +71,6 @@ * block size equal to the distance between start and end frames. */ virtual Range getSummary(size_t channel, size_t start, size_t count) const = 0; - - virtual void setAlignment(AlignmentModel *alignment); // I take ownership - virtual const Model *getAlignmentReference() const; - virtual size_t alignToReference(size_t frame) const; - virtual size_t alignFromReference(size_t referenceFrame) const; - virtual int getAlignmentCompletion() const; - -signals: - void alignmentCompletionChanged(); - -protected: - AlignmentModel *m_alignment; }; #endif Modified: sonic-visualiser/trunk/sv/document/Document.cpp =================================================================== --- sonic-visualiser/trunk/sv/document/Document.cpp 2007-10-22 14:24:31 UTC (rev 791) +++ sonic-visualiser/trunk/sv/document/Document.cpp 2007-10-24 15:21:38 UTC (rev 792) @@ -30,6 +30,11 @@ #include <QTextStream> #include <iostream> +// For alignment: +#include "data/model/AggregateWaveModel.h" +#include "data/model/SparseTimeValueModel.h" +#include "data/model/AlignmentModel.h" + //!!! still need to handle command history, documentRestored/documentModified Document::Document() : @@ -60,13 +65,15 @@ << "should have been garbage collected when deleting layers" << std::endl; while (!m_models.empty()) { - if (m_models.begin()->first == m_mainModel) { + Model *model = m_models.begin()->first; + if (model == m_mainModel) { // just in case! std::cerr << "Document::~Document: WARNING: Main model is also" << " in models list!" << std::endl; - } else { - emit modelAboutToBeDeleted(m_models.begin()->first); - delete m_models.begin()->first; + } else if (model) { + emit modelAboutToBeDeleted(model); + model->aboutToDelete(); + delete model; } m_models.erase(m_models.begin()); } @@ -74,7 +81,11 @@ // std::cerr << "Document::~Document: About to get rid of main model" // << std::endl; - emit modelAboutToBeDeleted(m_mainModel); + if (m_mainModel) { + emit modelAboutToBeDeleted(m_mainModel); + m_mainModel->aboutToDelete(); + } + emit mainModelChanged(0); delete m_mainModel; @@ -439,6 +450,7 @@ } emit modelAboutToBeDeleted(model); + model->aboutToDelete(); m_models.erase(model); delete model; } @@ -649,6 +661,77 @@ return models; } +void +Document::alignModel(Model *model) +{ + if (!m_mainModel || model == m_mainModel) return; + + RangeSummarisableTimeValueModel *rm = + dynamic_cast<RangeSummarisableTimeValueModel *>(model); + if (!rm) return; + + // This involves creating three new models: + + // 1. an AggregateWaveModel to provide the mixdowns of the main + // model and the new model in its two channels, as input to the + // MATCH plugin + + // 2. a SparseTimeValueModel, which is the model automatically + // created by FeatureExtractionPluginTransform when running the + // MATCH plugin (thus containing the alignment path) + + // 3. an AlignmentModel, which stores the path model and carries + // out alignment lookups on it. + + // The first two of these are provided as arguments to the + // constructor for the third, which takes responsibility for + // deleting them. The AlignmentModel, meanwhile, is passed to the + // new model we are aligning, which also takes responsibility for + // it. We should not have to delete any of these new models here. + + AggregateWaveModel::ChannelSpecList components; + + components.push_back(AggregateWaveModel::ModelChannelSpec + (m_mainModel, -1)); + + components.push_back(AggregateWaveModel::ModelChannelSpec + (rm, -1)); + + Model *aggregate = new AggregateWaveModel(components); + + TransformId id = "vamp:match-vamp-plugin:match:path"; + + TransformFactory *factory = TransformFactory::getInstance(); + + Model *transformOutput = factory->transform + (id, aggregate, + factory->getDefaultContextForTransform(id, aggregate), + "<plugin param-serialise=\"1\"/>"); + + SparseTimeValueModel *path = dynamic_cast<SparseTimeValueModel *> + (transformOutput); + + if (!path) { + std::cerr << "Document::alignModel: ERROR: Failed to create alignment path (no MATCH plugin?)" << std::endl; + delete transformOutput; + delete aggregate; + return; + } + + AlignmentModel *alignmentModel = new AlignmentModel + (m_mainModel, model, aggregate, path); + + rm->setAlignment(alignmentModel); +} + +void +Document::alignModels() +{ + for (ModelMap::iterator i = m_models.begin(); i != m_models.end(); ++i) { + alignModel(i->first); + } +} + Document::AddLayerCommand::AddLayerCommand(Document *d, View *view, Layer *layer) : Modified: sonic-visualiser/trunk/sv/document/Document.h =================================================================== --- sonic-visualiser/trunk/sv/document/Document.h 2007-10-22 14:24:31 UTC (rev 791) +++ sonic-visualiser/trunk/sv/document/Document.h 2007-10-24 15:21:38 UTC (rev 792) @@ -217,6 +217,17 @@ */ void deleteLayer(Layer *, bool force = false); + /** + * If model is suitable for alignment, align it against the main + * model and store the alignment in the model. + */ + void alignModel(Model *); + + /** + * Realign all models if the main model has changed. Is this wise? + */ + void alignModels(); + /* * Every model that is in use by a layer in the document must be * found in either m_mainModel or m_models. We own and control This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |