# HG changeset patch # User Chris Cannam # Date 1390987882 0 # Node ID 47aa3aeb687b0905956eb34800cde339f5fa11e5 # Parent 3e6ed8a8577b6cf4f08aad146953f222ac198a66 For outputs with unknown bin count or multiple bins with variable sample rate, create additional output models for bins beyond the first diff -r 3e6ed8a8577b -r 47aa3aeb687b transform/FeatureExtractionModelTransformer.cpp --- a/transform/FeatureExtractionModelTransformer.cpp Tue Jan 28 18:52:22 2014 +0000 +++ b/transform/FeatureExtractionModelTransformer.cpp Wed Jan 29 09:31:22 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; @@ -392,7 +395,7 @@ QString outputEventTypeURI = description.getOutputEventTypeURI(outputId); out->setRDFTypeURI(outputEventTypeURI); - } else if ((binCount == 1 && m_descriptors[n]->hasFixedBinCount) || + } else if (binCount == 1 || (m_descriptors[n]->sampleType == Vamp::Plugin::OutputDescriptor::VariableSampleRate)) { @@ -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 just 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,57 @@ } } +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; +} + +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() { @@ -799,7 +870,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 @@ -898,11 +979,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 3e6ed8a8577b -r 47aa3aeb687b transform/FeatureExtractionModelTransformer.h --- a/transform/FeatureExtractionModelTransformer.h Tue Jan 28 18:52:22 2014 +0000 +++ b/transform/FeatureExtractionModelTransformer.h Wed Jan 29 09:31:22 2014 +0000 @@ -23,8 +23,10 @@ #include #include +#include class DenseTimeValueModel; +class SparseTimeValueModel; class FeatureExtractionModelTransformer : public ModelTransformer { @@ -50,9 +52,17 @@ 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); + + // ModelTransformer method, retrieve the additional models + Models getAdditionalOutputModels(); void addFeature(int n, size_t blockFrame, diff -r 3e6ed8a8577b -r 47aa3aeb687b transform/ModelTransformer.cpp --- a/transform/ModelTransformer.cpp Tue Jan 28 18:52:22 2014 +0000 +++ b/transform/ModelTransformer.cpp Wed Jan 29 09:31:22 2014 +0000 @@ -36,9 +36,19 @@ m_abandoned = true; wait(); if (!m_detached) { - foreach (Model *m, m_outputs) { + Models mine = getOutputModels(); // including any additional ones + foreach (Model *m, mine) { delete m; } } } +ModelTransformer::Models +ModelTransformer::getOutputModels() +{ + Models out(m_outputs); + Models add(getAdditionalOutputModels()); + foreach (Model *m, add) out.push_back(m); + return out; +} + diff -r 3e6ed8a8577b -r 47aa3aeb687b transform/ModelTransformer.h --- a/transform/ModelTransformer.h Tue Jan 28 18:52:22 2014 +0000 +++ b/transform/ModelTransformer.h Wed Jan 29 09:31:22 2014 +0000 @@ -83,14 +83,14 @@ * be initialised; an error message may be available via * getMessage() in this situation. */ - Models getOutputModels() { return m_outputs; } + Models getOutputModels(); /** * Return the set of output models, also detaching them from the * 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 a warning or error message. If getOutputModel returned @@ -104,6 +104,14 @@ ModelTransformer(Input input, const Transform &transform); ModelTransformer(Input input, const Transforms &transforms); + /** + * 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. + */ + virtual Models getAdditionalOutputModels() { return Models(); } + Transforms m_transforms; Input m_input; // I don't own the model in this Models m_outputs; // I own this, unless...