# HG changeset patch # User Chris Cannam # Date 1394559035 0 # Node ID 4cbf8c6a462dd25ef0e6b12f7d22dbf3fcbec1e9 # Parent 862fe7b20df76ec3e57d1110c5a064940ae5de35# Parent 0c8218b2d84a172049d966c82c2064f5aa59c503 Merge from branch tonioni diff -r 862fe7b20df7 -r 4cbf8c6a462d data/model/Model.h --- a/data/model/Model.h Tue Jan 28 15:01:54 2014 +0000 +++ b/data/model/Model.h Tue Mar 11 17:30:35 2014 +0000 @@ -216,7 +216,7 @@ virtual QString toDelimitedDataString(QString delimiter) const { return toDelimitedDataString(delimiter, getStartFrame(), getEndFrame()); } - virtual QString toDelimitedDataString(QString, size_t f0, size_t f1) const { + virtual QString toDelimitedDataString(QString, size_t /* f0 */, size_t /* f1 */) const { return ""; } diff -r 862fe7b20df7 -r 4cbf8c6a462d svcore.pro --- a/svcore.pro Tue Jan 28 15:01:54 2014 +0000 +++ b/svcore.pro Tue Mar 11 17:30:35 2014 +0000 @@ -5,6 +5,10 @@ include(config.pri) } !exists(config.pri) { + + CONFIG += release + DEFINES += NDEBUG BUILD_RELEASE NO_TIMING + win32-g++ { INCLUDEPATH += ../sv-dependency-builds/win32-mingw/include LIBS += -L../sv-dependency-builds/win32-mingw/lib diff -r 862fe7b20df7 -r 4cbf8c6a462d transform/FeatureExtractionModelTransformer.cpp --- a/transform/FeatureExtractionModelTransformer.cpp Tue Jan 28 15:01:54 2014 +0000 +++ b/transform/FeatureExtractionModelTransformer.cpp Tue Mar 11 17:30:35 2014 +0000 @@ -213,14 +213,14 @@ } for (int j = 0; j < (int)m_transforms.size(); ++j) { - createOutputModel(j); + createOutputModels(j); } return true; } void -FeatureExtractionModelTransformer::createOutputModel(int n) +FeatureExtractionModelTransformer::createOutputModels(int n) { DenseTimeValueModel *input = getConformingInput(); @@ -232,11 +232,14 @@ int binCount = 1; float minValue = 0.0, maxValue = 0.0; bool haveExtents = false; - - if (m_descriptors[n]->hasFixedBinCount) { + bool haveBinCount = m_descriptors[n]->hasFixedBinCount; + + if (haveBinCount) { binCount = m_descriptors[n]->binCount; } + m_needAdditionalModels[n] = false; + // cerr << "FeatureExtractionModelTransformer: output bin count " // << binCount << endl; @@ -401,10 +404,27 @@ // model. // Anything that is not a 1D, note, or interval model and that - // has a variable sample rate is also treated as a sparse time - // value model regardless of its bin count, because we lack a + // has a variable sample rate is treated as a set of sparse + // time value models, one per output bin, because we lack a // sparse 3D model. + // Anything that is not a 1D, note, or interval model and that + // has a fixed sample rate but an unknown number of values per + // result is also treated as a set of sparse time value models. + + // For sets of sparse time value models, we create a single + // model first as the "standard" output and then create models + // for bins 1+ in the additional model map (mapping the output + // descriptor to a list of models indexed by bin-1). But we + // don't create the additional models yet, as this case has to + // work even if the number of bins is unknown at this point -- + // we create an additional model (copying its parameters from + // the default one) each time a new bin is encountered. + + if (!haveBinCount || binCount > 1) { + m_needAdditionalModels[n] = true; + } + SparseTimeValueModel *model; if (haveExtents) { model = new SparseTimeValueModel @@ -463,6 +483,68 @@ } } +FeatureExtractionModelTransformer::Models +FeatureExtractionModelTransformer::getAdditionalOutputModels() +{ + Models mm; + for (AdditionalModelMap::iterator i = m_additionalModels.begin(); + i != m_additionalModels.end(); ++i) { + for (std::map::iterator j = + i->second.begin(); + j != i->second.end(); ++j) { + SparseTimeValueModel *m = j->second; + if (m) mm.push_back(m); + } + } + return mm; +} + +bool +FeatureExtractionModelTransformer::willHaveAdditionalOutputModels() +{ + for (std::map::const_iterator i = + m_needAdditionalModels.begin(); + i != m_needAdditionalModels.end(); ++i) { + if (i->second) return true; + } + return false; +} + +SparseTimeValueModel * +FeatureExtractionModelTransformer::getAdditionalModel(int n, int binNo) +{ + std::cerr << "getAdditionalModel(" << n << ", " << binNo << ")" << std::endl; + + if (binNo == 0) { + std::cerr << "Internal error: binNo == 0 in getAdditionalModel (should be using primary model)" << std::endl; + return 0; + } + + if (!m_needAdditionalModels[n]) return 0; + if (!isOutput(n)) return 0; + if (m_additionalModels[n][binNo]) return m_additionalModels[n][binNo]; + + std::cerr << "getAdditionalModel(" << n << ", " << binNo << "): creating" << std::endl; + + SparseTimeValueModel *baseModel = getConformingOutput(n); + if (!baseModel) return 0; + + std::cerr << "getAdditionalModel(" << n << ", " << binNo << "): (from " << baseModel << ")" << std::endl; + + SparseTimeValueModel *additional = + new SparseTimeValueModel(baseModel->getSampleRate(), + baseModel->getResolution(), + baseModel->getValueMinimum(), + baseModel->getValueMaximum(), + false); + + additional->setScaleUnits(baseModel->getScaleUnits()); + additional->setRDFTypeURI(baseModel->getRDFTypeURI()); + + m_additionalModels[n][binNo] = additional; + return additional; +} + DenseTimeValueModel * FeatureExtractionModelTransformer::getConformingInput() { @@ -487,7 +569,7 @@ Transform primaryTransform = m_transforms[0]; while (!input->isReady() && !m_abandoned) { - SVDEBUG << "FeatureExtractionModelTransformer::run: Waiting for input model to be ready..." << endl; + cerr << "FeatureExtractionModelTransformer::run: Waiting for input model to be ready..." << endl; usleep(500000); } if (m_abandoned) return; @@ -814,7 +896,17 @@ label = QString("[%1] %2").arg(i+1).arg(label); } - model->addPoint(SparseTimeValueModel::Point(frame, value, label)); + SparseTimeValueModel *targetModel = model; + + if (m_needAdditionalModels[n] && i > 0) { + targetModel = getAdditionalModel(n, i); + if (!targetModel) targetModel = model; + std::cerr << "adding point to model " << targetModel + << " for output " << n << " bin " << i << std::endl; + } + + targetModel->addPoint + (SparseTimeValueModel::Point(frame, value, label)); } } else if (isOutput(n) || isOutput(n) || isOutput(n)) { //GF: Added Note Model @@ -913,11 +1005,6 @@ void FeatureExtractionModelTransformer::setCompletion(int n, int completion) { - int binCount = 1; - if (m_descriptors[n]->hasFixedBinCount) { - binCount = m_descriptors[n]->binCount; - } - // SVDEBUG << "FeatureExtractionModelTransformer::setCompletion(" // << completion << ")" << endl; diff -r 862fe7b20df7 -r 4cbf8c6a462d transform/FeatureExtractionModelTransformer.h --- a/transform/FeatureExtractionModelTransformer.h Tue Jan 28 15:01:54 2014 +0000 +++ b/transform/FeatureExtractionModelTransformer.h Tue Mar 11 17:30:35 2014 +0000 @@ -23,8 +23,10 @@ #include #include +#include class DenseTimeValueModel; +class SparseTimeValueModel; class FeatureExtractionModelTransformer : public ModelTransformer { @@ -42,6 +44,10 @@ virtual ~FeatureExtractionModelTransformer(); + // ModelTransformer method, retrieve the additional models + Models getAdditionalOutputModels(); + bool willHaveAdditionalOutputModels(); + protected: bool initialise(); @@ -50,9 +56,14 @@ Vamp::Plugin *m_plugin; std::vector m_descriptors; // per transform std::vector m_fixedRateFeatureNos; // to assign times to FixedSampleRate features - std::vector m_outputNos; + std::vector m_outputNos; // list of plugin output indexes required for this group of transforms - void createOutputModel(int n); + void createOutputModels(int n); + + std::map m_needAdditionalModels; // transformNo -> necessity + typedef std::map > AdditionalModelMap; + AdditionalModelMap m_additionalModels; + SparseTimeValueModel *getAdditionalModel(int transformNo, int binNo); void addFeature(int n, size_t blockFrame, diff -r 862fe7b20df7 -r 4cbf8c6a462d transform/ModelTransformer.cpp --- a/transform/ModelTransformer.cpp Tue Jan 28 15:01:54 2014 +0000 +++ b/transform/ModelTransformer.cpp Tue Mar 11 17:30:35 2014 +0000 @@ -18,6 +18,7 @@ ModelTransformer::ModelTransformer(Input input, const Transform &transform) : m_input(input), m_detached(false), + m_detachedAdd(false), m_abandoned(false) { m_transforms.push_back(transform); @@ -27,6 +28,7 @@ m_transforms(transforms), m_input(input), m_detached(false), + m_detachedAdd(false), m_abandoned(false) { } @@ -36,9 +38,12 @@ m_abandoned = true; wait(); if (!m_detached) { - foreach (Model *m, m_outputs) { - delete m; - } + Models mine = getOutputModels(); + foreach (Model *m, mine) delete m; + } + if (!m_detachedAdd) { + Models mine = getAdditionalOutputModels(); + foreach (Model *m, mine) delete m; } } diff -r 862fe7b20df7 -r 4cbf8c6a462d transform/ModelTransformer.h --- a/transform/ModelTransformer.h Tue Jan 28 15:01:54 2014 +0000 +++ b/transform/ModelTransformer.h Tue Mar 11 17:30:35 2014 +0000 @@ -90,7 +90,35 @@ * transformer so that they will not be deleted when the * transformer is. The caller takes ownership of the models. */ - Models detachOutputModels() { m_detached = true; return m_outputs; } + Models detachOutputModels() { + m_detached = true; + return getOutputModels(); + } + + /** + * Return any additional models that were created during + * processing. This might happen if, for example, a transform was + * configured to split a multi-bin output into separate single-bin + * models as it processed. These should not be queried until after + * the transform has completed. + */ + virtual Models getAdditionalOutputModels() { return Models(); } + + /** + * Return true if the current transform is one that may produce + * additional models (to be retrieved through + * getAdditionalOutputModels above). + */ + virtual bool willHaveAdditionalOutputModels() { return false; } + + /** + * Return the set of additional models, also detaching them from + * the transformer. The caller takes ownership of the models. + */ + virtual Models detachAdditionalOutputModels() { + m_detachedAdd = true; + return getAdditionalOutputModels(); + } /** * Return a warning or error message. If getOutputModel returned @@ -108,6 +136,7 @@ Input m_input; // I don't own the model in this Models m_outputs; // I own this, unless... bool m_detached; // ... this is true. + bool m_detachedAdd; bool m_abandoned; QString m_message; }; diff -r 862fe7b20df7 -r 4cbf8c6a462d transform/ModelTransformerFactory.cpp --- a/transform/ModelTransformerFactory.cpp Tue Jan 28 15:01:54 2014 +0000 +++ b/transform/ModelTransformerFactory.cpp Tue Mar 11 17:30:35 2014 +0000 @@ -195,13 +195,14 @@ Model * ModelTransformerFactory::transform(const Transform &transform, const ModelTransformer::Input &input, - QString &message) + QString &message, + AdditionalModelHandler *handler) { SVDEBUG << "ModelTransformerFactory::transform: Constructing transformer with input model " << input.getModel() << endl; Transforms transforms; transforms.push_back(transform); - vector mm = transformMultiple(transforms, input, message); + vector mm = transformMultiple(transforms, input, message, handler); if (mm.empty()) return 0; else return mm[0]; } @@ -209,17 +210,22 @@ vector ModelTransformerFactory::transformMultiple(const Transforms &transforms, const ModelTransformer::Input &input, - QString &message) + QString &message, + AdditionalModelHandler *handler) { SVDEBUG << "ModelTransformerFactory::transformMultiple: Constructing transformer with input model " << input.getModel() << endl; ModelTransformer *t = createTransformer(transforms, input); if (!t) return vector(); - connect(t, SIGNAL(finished()), this, SLOT(transformerFinished())); + if (handler) { + m_handlers[t] = handler; + } m_runningTransformers.insert(t); + connect(t, SIGNAL(finished()), this, SLOT(transformerFinished())); + t->start(); vector models = t->detachOutputModels(); @@ -270,6 +276,16 @@ m_runningTransformers.erase(transformer); + if (m_handlers.find(transformer) != m_handlers.end()) { + if (transformer->willHaveAdditionalOutputModels()) { + vector mm = transformer->detachAdditionalOutputModels(); + m_handlers[transformer]->moreModelsAvailable(mm); + } else { + m_handlers[transformer]->noMoreModelsAvailable(); + } + m_handlers.erase(transformer); + } + transformer->wait(); // unnecessary but reassuring delete transformer; } diff -r 862fe7b20df7 -r 4cbf8c6a462d transform/ModelTransformerFactory.h --- a/transform/ModelTransformerFactory.h Tue Jan 28 15:01:54 2014 +0000 +++ b/transform/ModelTransformerFactory.h Tue Mar 11 17:30:35 2014 +0000 @@ -70,6 +70,15 @@ size_t startFrame = 0, size_t duration = 0, UserConfigurator *configurator = 0); + + class AdditionalModelHandler { + public: + virtual ~AdditionalModelHandler() { } + + // Exactly one of these functions will be called + virtual void moreModelsAvailable(std::vector models) = 0; + virtual void noMoreModelsAvailable() = 0; + }; /** * Return the output model resulting from applying the named @@ -82,12 +91,21 @@ * problem occurs, return 0. Set message if there is any error or * warning to report. * + * Some transforms may return additional models at the end of + * processing. (For example, a transform that splits an output + * into multiple one-per-bin models.) If an additionalModelHandler + * is provided here, its moreModelsAvailable method will be called + * when those models become available, and ownership of those + * models will be transferred to the handler. Otherwise (if the + * handler is null) any such models will be discarded. + * * The returned model is owned by the caller and must be deleted * when no longer needed. */ Model *transform(const Transform &transform, const ModelTransformer::Input &input, - QString &message); + QString &message, + AdditionalModelHandler *handler = 0); /** * Return the multiple output models resulting from applying the @@ -105,13 +123,22 @@ * for the given transform, or if some other problem occurs, * return 0. Set message if there is any error or warning to * report. - * + * + * Some transforms may return additional models at the end of + * processing. (For example, a transform that splits an output + * into multiple one-per-bin models.) If an additionalModelHandler + * is provided here, its moreModelsAvailable method will be called + * when those models become available, and ownership of those + * models will be transferred to the handler. Otherwise (if the + * handler is null) any such models will be discarded. + * * The returned models are owned by the caller and must be deleted * when no longer needed. */ std::vector transformMultiple(const Transforms &transform, const ModelTransformer::Input &input, - QString &message); + QString &message, + AdditionalModelHandler *handler = 0); protected slots: void transformerFinished(); @@ -128,6 +155,9 @@ typedef std::set TransformerSet; TransformerSet m_runningTransformers; + typedef std::map HandlerMap; + HandlerMap m_handlers; + static ModelTransformerFactory *m_instance; };