lbajardsilogic@0: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ lbajardsilogic@0: lbajardsilogic@0: /* lbajardsilogic@0: Sonic Visualiser lbajardsilogic@0: An audio file viewer and annotation editor. lbajardsilogic@0: Centre for Digital Music, Queen Mary, University of London. lbajardsilogic@0: This file copyright 2006 Chris Cannam and QMUL. lbajardsilogic@0: lbajardsilogic@0: This program is free software; you can redistribute it and/or lbajardsilogic@0: modify it under the terms of the GNU General Public License as lbajardsilogic@0: published by the Free Software Foundation; either version 2 of the lbajardsilogic@0: License, or (at your option) any later version. See the file lbajardsilogic@0: COPYING included with this distribution for more information. lbajardsilogic@0: */ lbajardsilogic@0: lbajardsilogic@0: #include "FeatureExtractionPluginTransform.h" lbajardsilogic@0: lbajardsilogic@0: #include "plugin/FeatureExtractionPluginFactory.h" lbajardsilogic@0: #include "plugin/PluginXml.h" lbajardsilogic@0: #include "vamp-sdk/Plugin.h" lbajardsilogic@0: lbajardsilogic@0: #include "data/model/Model.h" lbajardsilogic@0: #include "base/Window.h" lbajardsilogic@0: #include "data/model/SparseOneDimensionalModel.h" lbajardsilogic@0: #include "data/model/SparseTimeValueModel.h" lbajardsilogic@0: #include "data/model/EditableDenseThreeDimensionalModel.h" lbajardsilogic@0: #include "data/model/DenseTimeValueModel.h" lbajardsilogic@0: #include "data/model/NoteModel.h" lbajardsilogic@0: #include "data/model/FFTModel.h" lbajardsilogic@0: #include "data/model/WaveFileModel.h" lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: #include lbajardsilogic@0: lbajardsilogic@0: FeatureExtractionPluginTransform::FeatureExtractionPluginTransform(Model *inputModel, lbajardsilogic@0: QString pluginId, lbajardsilogic@0: const ExecutionContext &context, lbajardsilogic@0: QString configurationXml, lbajardsilogic@0: QString outputName) : lbajardsilogic@0: PluginTransform(inputModel, context), lbajardsilogic@0: m_plugin(0), lbajardsilogic@0: m_descriptor(0), lbajardsilogic@0: m_outputFeatureNo(0) lbajardsilogic@0: { lbajardsilogic@0: // std::cerr << "FeatureExtractionPluginTransform::FeatureExtractionPluginTransform: plugin " << pluginId.toStdString() << ", outputName " << outputName.toStdString() << std::endl; lbajardsilogic@0: lbajardsilogic@0: FeatureExtractionPluginFactory *factory = lbajardsilogic@0: FeatureExtractionPluginFactory::instanceFor(pluginId); lbajardsilogic@0: lbajardsilogic@0: if (!factory) { lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform: No factory available for plugin id \"" lbajardsilogic@0: << pluginId.toStdString() << "\"" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_plugin = factory->instantiatePlugin(pluginId, m_input->getSampleRate()); lbajardsilogic@0: lbajardsilogic@0: if (!m_plugin) { lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform: Failed to instantiate plugin \"" lbajardsilogic@0: << pluginId.toStdString() << "\"" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (configurationXml != "") { lbajardsilogic@0: PluginXml(m_plugin).setParametersFromXml(configurationXml); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: DenseTimeValueModel *input = getInput(); lbajardsilogic@0: if (!input) return; lbajardsilogic@0: lbajardsilogic@0: size_t channelCount = input->getChannelCount(); lbajardsilogic@0: if (m_plugin->getMaxChannelCount() < channelCount) { lbajardsilogic@0: channelCount = 1; lbajardsilogic@0: } lbajardsilogic@0: if (m_plugin->getMinChannelCount() > channelCount) { lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform:: " lbajardsilogic@0: << "Can't provide enough channels to plugin (plugin min " lbajardsilogic@0: << m_plugin->getMinChannelCount() << ", max " lbajardsilogic@0: << m_plugin->getMaxChannelCount() << ", input model has " lbajardsilogic@0: << input->getChannelCount() << ")" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: std::cerr << "Initialising feature extraction plugin with channels = " lbajardsilogic@0: << channelCount << ", step = " << m_context.stepSize lbajardsilogic@0: << ", block = " << m_context.blockSize << std::endl; lbajardsilogic@0: lbajardsilogic@0: if (!m_plugin->initialise(channelCount, lbajardsilogic@0: m_context.stepSize, lbajardsilogic@0: m_context.blockSize)) { lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform: Plugin " lbajardsilogic@0: << m_plugin->getIdentifier() << " failed to initialise!" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Vamp::Plugin::OutputList outputs = m_plugin->getOutputDescriptors(); lbajardsilogic@0: lbajardsilogic@0: if (outputs.empty()) { lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform: Plugin \"" lbajardsilogic@0: << pluginId.toStdString() << "\" has no outputs" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: for (size_t i = 0; i < outputs.size(); ++i) { lbajardsilogic@0: if (outputName == "" || outputs[i].identifier == outputName.toStdString()) { lbajardsilogic@0: m_outputFeatureNo = i; lbajardsilogic@0: m_descriptor = new Vamp::Plugin::OutputDescriptor lbajardsilogic@0: (outputs[i]); lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!m_descriptor) { lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform: Plugin \"" lbajardsilogic@0: << pluginId.toStdString() << "\" has no output named \"" lbajardsilogic@0: << outputName.toStdString() << "\"" << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "FeatureExtractionPluginTransform: output sample type " lbajardsilogic@0: // << m_descriptor->sampleType << std::endl; lbajardsilogic@0: lbajardsilogic@0: int binCount = 1; lbajardsilogic@0: float minValue = 0.0, maxValue = 0.0; lbajardsilogic@0: bool haveExtents = false; lbajardsilogic@0: lbajardsilogic@0: if (m_descriptor->hasFixedBinCount) { lbajardsilogic@0: binCount = m_descriptor->binCount; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "FeatureExtractionPluginTransform: output bin count " lbajardsilogic@0: // << binCount << std::endl; lbajardsilogic@0: lbajardsilogic@0: if (binCount > 0 && m_descriptor->hasKnownExtents) { lbajardsilogic@0: minValue = m_descriptor->minValue; lbajardsilogic@0: maxValue = m_descriptor->maxValue; lbajardsilogic@0: haveExtents = true; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t modelRate = m_input->getSampleRate(); lbajardsilogic@0: size_t modelResolution = 1; lbajardsilogic@0: lbajardsilogic@0: switch (m_descriptor->sampleType) { lbajardsilogic@0: lbajardsilogic@0: case Vamp::Plugin::OutputDescriptor::VariableSampleRate: lbajardsilogic@0: if (m_descriptor->sampleRate != 0.0) { lbajardsilogic@0: modelResolution = size_t(modelRate / m_descriptor->sampleRate + 0.001); lbajardsilogic@0: } lbajardsilogic@0: break; lbajardsilogic@0: lbajardsilogic@0: case Vamp::Plugin::OutputDescriptor::OneSamplePerStep: lbajardsilogic@0: modelResolution = m_context.stepSize; lbajardsilogic@0: break; lbajardsilogic@0: lbajardsilogic@0: case Vamp::Plugin::OutputDescriptor::FixedSampleRate: lbajardsilogic@0: modelRate = size_t(m_descriptor->sampleRate + 0.001); lbajardsilogic@0: break; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (binCount == 0) { lbajardsilogic@0: lbajardsilogic@0: m_output = new SparseOneDimensionalModel(modelRate, modelResolution, lbajardsilogic@0: false); lbajardsilogic@0: lbajardsilogic@0: } else if (binCount == 1) { lbajardsilogic@0: lbajardsilogic@0: SparseTimeValueModel *model; lbajardsilogic@0: if (haveExtents) { lbajardsilogic@0: model = new SparseTimeValueModel lbajardsilogic@0: (modelRate, modelResolution, minValue, maxValue, false); lbajardsilogic@0: } else { lbajardsilogic@0: model = new SparseTimeValueModel lbajardsilogic@0: (modelRate, modelResolution, false); lbajardsilogic@0: } lbajardsilogic@0: model->setScaleUnits(outputs[m_outputFeatureNo].unit.c_str()); lbajardsilogic@0: lbajardsilogic@0: m_output = model; lbajardsilogic@0: lbajardsilogic@0: } else if (m_descriptor->sampleType == lbajardsilogic@0: Vamp::Plugin::OutputDescriptor::VariableSampleRate) { lbajardsilogic@0: lbajardsilogic@0: // We don't have a sparse 3D model, so interpret this as a lbajardsilogic@0: // note model. There's nothing to define which values to use lbajardsilogic@0: // as which parameters of the note -- for the moment let's lbajardsilogic@0: // treat the first as pitch, second as duration in frames, lbajardsilogic@0: // third (if present) as velocity. (Our note model doesn't lbajardsilogic@0: // yet store velocity.) lbajardsilogic@0: //!!! todo: ask the user! lbajardsilogic@0: lbajardsilogic@0: NoteModel *model; lbajardsilogic@0: if (haveExtents) { lbajardsilogic@0: model = new NoteModel lbajardsilogic@0: (modelRate, modelResolution, minValue, maxValue, false); lbajardsilogic@0: } else { lbajardsilogic@0: model = new NoteModel lbajardsilogic@0: (modelRate, modelResolution, false); lbajardsilogic@0: } lbajardsilogic@0: model->setScaleUnits(outputs[m_outputFeatureNo].unit.c_str()); lbajardsilogic@0: lbajardsilogic@0: m_output = model; lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: EditableDenseThreeDimensionalModel *model = lbajardsilogic@0: new EditableDenseThreeDimensionalModel lbajardsilogic@0: (modelRate, modelResolution, binCount, false); lbajardsilogic@0: lbajardsilogic@0: if (!m_descriptor->binNames.empty()) { lbajardsilogic@0: std::vector names; lbajardsilogic@0: for (size_t i = 0; i < m_descriptor->binNames.size(); ++i) { lbajardsilogic@0: names.push_back(m_descriptor->binNames[i].c_str()); lbajardsilogic@0: } lbajardsilogic@0: model->setBinNames(names); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: m_output = model; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: FeatureExtractionPluginTransform::~FeatureExtractionPluginTransform() lbajardsilogic@0: { lbajardsilogic@0: delete m_plugin; lbajardsilogic@0: delete m_descriptor; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: DenseTimeValueModel * lbajardsilogic@0: FeatureExtractionPluginTransform::getInput() lbajardsilogic@0: { lbajardsilogic@0: DenseTimeValueModel *dtvm = lbajardsilogic@0: dynamic_cast(getInputModel()); lbajardsilogic@0: if (!dtvm) { lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform::getInput: WARNING: Input model is not conformable to DenseTimeValueModel" << std::endl; lbajardsilogic@0: } lbajardsilogic@0: return dtvm; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: FeatureExtractionPluginTransform::run() lbajardsilogic@0: { lbajardsilogic@0: DenseTimeValueModel *input = getInput(); lbajardsilogic@0: if (!input) return; lbajardsilogic@0: lbajardsilogic@0: while (!input->isReady()) { lbajardsilogic@0: if (dynamic_cast(input)) break; // no need to wait lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform::run: Waiting for input model to be ready..." << std::endl; lbajardsilogic@0: sleep(1); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (!m_output) return; lbajardsilogic@0: lbajardsilogic@0: size_t sampleRate = m_input->getSampleRate(); lbajardsilogic@0: lbajardsilogic@0: size_t channelCount = input->getChannelCount(); lbajardsilogic@0: if (m_plugin->getMaxChannelCount() < channelCount) { lbajardsilogic@0: channelCount = 1; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: float **buffers = new float*[channelCount]; lbajardsilogic@0: for (size_t ch = 0; ch < channelCount; ++ch) { lbajardsilogic@0: buffers[ch] = new float[m_context.blockSize + 2]; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: bool frequencyDomain = (m_plugin->getInputDomain() == lbajardsilogic@0: Vamp::Plugin::FrequencyDomain); lbajardsilogic@0: std::vector fftModels; lbajardsilogic@0: lbajardsilogic@0: if (frequencyDomain) { lbajardsilogic@0: for (size_t ch = 0; ch < channelCount; ++ch) { lbajardsilogic@0: FFTModel *model = new FFTModel lbajardsilogic@0: (getInput(), lbajardsilogic@0: channelCount == 1 ? m_context.channel : ch, lbajardsilogic@0: m_context.windowType, lbajardsilogic@0: m_context.blockSize, lbajardsilogic@0: m_context.stepSize, lbajardsilogic@0: m_context.blockSize, lbajardsilogic@0: false); lbajardsilogic@0: if (!model->isOK()) { lbajardsilogic@0: QMessageBox::critical lbajardsilogic@0: (0, tr("FFT cache failed"), lbajardsilogic@0: tr("Failed to create the FFT model for this transform.\n" lbajardsilogic@0: "There may be insufficient memory or disc space to continue.")); lbajardsilogic@0: delete model; lbajardsilogic@0: setCompletion(100); lbajardsilogic@0: return; lbajardsilogic@0: } lbajardsilogic@0: model->resume(); lbajardsilogic@0: fftModels.push_back(model); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: long startFrame = m_input->getStartFrame(); lbajardsilogic@0: long endFrame = m_input->getEndFrame(); lbajardsilogic@0: long blockFrame = startFrame; lbajardsilogic@0: lbajardsilogic@0: long prevCompletion = 0; lbajardsilogic@0: lbajardsilogic@0: while (!m_abandoned) { lbajardsilogic@0: lbajardsilogic@0: if (frequencyDomain) { lbajardsilogic@0: if (blockFrame - int(m_context.blockSize)/2 > endFrame) break; lbajardsilogic@0: } else { lbajardsilogic@0: if (blockFrame >= endFrame) break; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "FeatureExtractionPluginTransform::run: blockFrame " lbajardsilogic@0: // << blockFrame << std::endl; lbajardsilogic@0: lbajardsilogic@0: long completion = lbajardsilogic@0: (((blockFrame - startFrame) / m_context.stepSize) * 99) / lbajardsilogic@0: ( (endFrame - startFrame) / m_context.stepSize); lbajardsilogic@0: lbajardsilogic@0: // channelCount is either m_input->channelCount or 1 lbajardsilogic@0: lbajardsilogic@0: for (size_t ch = 0; ch < channelCount; ++ch) { lbajardsilogic@0: if (frequencyDomain) { lbajardsilogic@0: int column = (blockFrame - startFrame) / m_context.stepSize; lbajardsilogic@0: for (size_t i = 0; i <= m_context.blockSize/2; ++i) { lbajardsilogic@0: fftModels[ch]->getValuesAt lbajardsilogic@0: (column, i, buffers[ch][i*2], buffers[ch][i*2+1]); lbajardsilogic@0: } lbajardsilogic@0: } else { lbajardsilogic@0: getFrames(ch, channelCount, lbajardsilogic@0: blockFrame, m_context.blockSize, buffers[ch]); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: Vamp::Plugin::FeatureSet features = m_plugin->process lbajardsilogic@0: (buffers, Vamp::RealTime::frame2RealTime(blockFrame, sampleRate)); lbajardsilogic@0: lbajardsilogic@0: for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) { lbajardsilogic@0: Vamp::Plugin::Feature feature = lbajardsilogic@0: features[m_outputFeatureNo][fi]; lbajardsilogic@0: addFeature(blockFrame, feature); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (blockFrame == startFrame || completion > prevCompletion) { lbajardsilogic@0: setCompletion(completion); lbajardsilogic@0: prevCompletion = completion; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: blockFrame += m_context.stepSize; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (m_abandoned) return; lbajardsilogic@0: lbajardsilogic@0: Vamp::Plugin::FeatureSet features = m_plugin->getRemainingFeatures(); lbajardsilogic@0: lbajardsilogic@0: for (size_t fi = 0; fi < features[m_outputFeatureNo].size(); ++fi) { lbajardsilogic@0: Vamp::Plugin::Feature feature = lbajardsilogic@0: features[m_outputFeatureNo][fi]; lbajardsilogic@0: addFeature(blockFrame, feature); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (frequencyDomain) { lbajardsilogic@0: for (size_t ch = 0; ch < channelCount; ++ch) { lbajardsilogic@0: delete fftModels[ch]; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: setCompletion(100); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: FeatureExtractionPluginTransform::getFrames(int channel, int channelCount, lbajardsilogic@0: long startFrame, long size, lbajardsilogic@0: float *buffer) lbajardsilogic@0: { lbajardsilogic@0: long offset = 0; lbajardsilogic@0: lbajardsilogic@0: if (startFrame < 0) { lbajardsilogic@0: for (int i = 0; i < size && startFrame + i < 0; ++i) { lbajardsilogic@0: buffer[i] = 0.0f; lbajardsilogic@0: } lbajardsilogic@0: offset = -startFrame; lbajardsilogic@0: size -= offset; lbajardsilogic@0: if (size <= 0) return; lbajardsilogic@0: startFrame = 0; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: long got = getInput()->getValues lbajardsilogic@0: ((channelCount == 1 ? m_context.channel : channel), lbajardsilogic@0: startFrame, startFrame + size, buffer + offset); lbajardsilogic@0: lbajardsilogic@0: while (got < size) { lbajardsilogic@0: buffer[offset + got] = 0.0; lbajardsilogic@0: ++got; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (m_context.channel == -1 && channelCount == 1 && lbajardsilogic@0: getInput()->getChannelCount() > 1) { lbajardsilogic@0: // use mean instead of sum, as plugin input lbajardsilogic@0: int cc = getInput()->getChannelCount(); lbajardsilogic@0: for (long i = 0; i < size; ++i) { lbajardsilogic@0: buffer[i] /= cc; lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: FeatureExtractionPluginTransform::addFeature(size_t blockFrame, lbajardsilogic@0: const Vamp::Plugin::Feature &feature) lbajardsilogic@0: { lbajardsilogic@0: size_t inputRate = m_input->getSampleRate(); lbajardsilogic@0: lbajardsilogic@0: // std::cerr << "FeatureExtractionPluginTransform::addFeature(" lbajardsilogic@0: // << blockFrame << ")" << std::endl; lbajardsilogic@0: lbajardsilogic@0: int binCount = 1; lbajardsilogic@0: if (m_descriptor->hasFixedBinCount) { lbajardsilogic@0: binCount = m_descriptor->binCount; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: size_t frame = blockFrame; lbajardsilogic@0: lbajardsilogic@0: if (m_descriptor->sampleType == lbajardsilogic@0: Vamp::Plugin::OutputDescriptor::VariableSampleRate) { lbajardsilogic@0: lbajardsilogic@0: if (!feature.hasTimestamp) { lbajardsilogic@0: std::cerr lbajardsilogic@0: << "WARNING: FeatureExtractionPluginTransform::addFeature: " lbajardsilogic@0: << "Feature has variable sample rate but no timestamp!" lbajardsilogic@0: << std::endl; lbajardsilogic@0: return; lbajardsilogic@0: } else { lbajardsilogic@0: frame = Vamp::RealTime::realTime2Frame(feature.timestamp, inputRate); lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: } else if (m_descriptor->sampleType == lbajardsilogic@0: Vamp::Plugin::OutputDescriptor::FixedSampleRate) { lbajardsilogic@0: lbajardsilogic@0: if (feature.hasTimestamp) { lbajardsilogic@0: //!!! warning: sampleRate may be non-integral lbajardsilogic@0: frame = Vamp::RealTime::realTime2Frame(feature.timestamp, lbajardsilogic@0: lrintf(m_descriptor->sampleRate)); lbajardsilogic@0: } else { lbajardsilogic@0: frame = m_output->getEndFrame(); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: if (binCount == 0) { lbajardsilogic@0: lbajardsilogic@0: SparseOneDimensionalModel *model = getOutput(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: model->addPoint(SparseOneDimensionalModel::Point(frame, feature.label.c_str())); lbajardsilogic@0: lbajardsilogic@0: } else if (binCount == 1) { lbajardsilogic@0: lbajardsilogic@0: float value = 0.0; lbajardsilogic@0: if (feature.values.size() > 0) value = feature.values[0]; lbajardsilogic@0: lbajardsilogic@0: SparseTimeValueModel *model = getOutput(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: model->addPoint(SparseTimeValueModel::Point(frame, value, feature.label.c_str())); lbajardsilogic@0: lbajardsilogic@0: } else if (m_descriptor->sampleType == lbajardsilogic@0: Vamp::Plugin::OutputDescriptor::VariableSampleRate) { lbajardsilogic@0: lbajardsilogic@0: float pitch = 0.0; lbajardsilogic@0: if (feature.values.size() > 0) pitch = feature.values[0]; lbajardsilogic@0: lbajardsilogic@0: float duration = 1; lbajardsilogic@0: if (feature.values.size() > 1) duration = feature.values[1]; lbajardsilogic@0: lbajardsilogic@0: float velocity = 100; lbajardsilogic@0: if (feature.values.size() > 2) velocity = feature.values[2]; lbajardsilogic@0: lbajardsilogic@0: NoteModel *model = getOutput(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: lbajardsilogic@0: model->addPoint(NoteModel::Point(frame, pitch, lbajardsilogic@0: lrintf(duration), lbajardsilogic@0: feature.label.c_str())); lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: DenseThreeDimensionalModel::Column values = feature.values; lbajardsilogic@0: lbajardsilogic@0: EditableDenseThreeDimensionalModel *model = lbajardsilogic@0: getOutput(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: lbajardsilogic@0: model->setColumn(frame / model->getResolution(), values); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: void lbajardsilogic@0: FeatureExtractionPluginTransform::setCompletion(int completion) lbajardsilogic@0: { lbajardsilogic@0: int binCount = 1; lbajardsilogic@0: if (m_descriptor->hasFixedBinCount) { lbajardsilogic@0: binCount = m_descriptor->binCount; lbajardsilogic@0: } lbajardsilogic@0: lbajardsilogic@0: std::cerr << "FeatureExtractionPluginTransform::setCompletion(" lbajardsilogic@0: << completion << ")" << std::endl; lbajardsilogic@0: lbajardsilogic@0: if (binCount == 0) { lbajardsilogic@0: lbajardsilogic@0: SparseOneDimensionalModel *model = getOutput(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: model->setCompletion(completion); lbajardsilogic@0: lbajardsilogic@0: } else if (binCount == 1) { lbajardsilogic@0: lbajardsilogic@0: SparseTimeValueModel *model = getOutput(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: model->setCompletion(completion); lbajardsilogic@0: lbajardsilogic@0: } else if (m_descriptor->sampleType == lbajardsilogic@0: Vamp::Plugin::OutputDescriptor::VariableSampleRate) { lbajardsilogic@0: lbajardsilogic@0: NoteModel *model = getOutput(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: model->setCompletion(completion); lbajardsilogic@0: lbajardsilogic@0: } else { lbajardsilogic@0: lbajardsilogic@0: EditableDenseThreeDimensionalModel *model = lbajardsilogic@0: getOutput(); lbajardsilogic@0: if (!model) return; lbajardsilogic@0: model->setCompletion(completion); lbajardsilogic@0: } lbajardsilogic@0: } lbajardsilogic@0: