diff options
Diffstat (limited to 'libs/rubberband/src/vamp/RubberBandVampPlugin.cpp')
-rw-r--r-- | libs/rubberband/src/vamp/RubberBandVampPlugin.cpp | 648 |
1 files changed, 0 insertions, 648 deletions
diff --git a/libs/rubberband/src/vamp/RubberBandVampPlugin.cpp b/libs/rubberband/src/vamp/RubberBandVampPlugin.cpp deleted file mode 100644 index feb5bfa6bb..0000000000 --- a/libs/rubberband/src/vamp/RubberBandVampPlugin.cpp +++ /dev/null @@ -1,648 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Rubber Band - An audio time-stretching and pitch-shifting library. - Copyright 2007-2008 Chris Cannam. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. See the file - COPYING included with this distribution for more information. -*/ - -#include "RubberBandVampPlugin.h" - -#include "StretchCalculator.h" -#include "sysutils.h" - -#include <cmath> - -using std::string; -using std::vector; -using std::cerr; -using std::endl; - -class RubberBandVampPlugin::Impl -{ -public: - size_t m_stepSize; - size_t m_blockSize; - size_t m_sampleRate; - - float m_timeRatio; - float m_pitchRatio; - - bool m_realtime; - bool m_elasticTiming; - int m_transientMode; - bool m_phaseIndependent; - int m_windowLength; - - RubberBand::RubberBandStretcher *m_stretcher; - - int m_incrementsOutput; - int m_aggregateIncrementsOutput; - int m_divergenceOutput; - int m_phaseResetDfOutput; - int m_smoothedPhaseResetDfOutput; - int m_phaseResetPointsOutput; - int m_timeSyncPointsOutput; - - size_t m_counter; - size_t m_accumulatedIncrement; - - float **m_outputDump; - - FeatureSet processOffline(const float *const *inputBuffers, - Vamp::RealTime timestamp); - - FeatureSet getRemainingFeaturesOffline(); - - FeatureSet processRealTime(const float *const *inputBuffers, - Vamp::RealTime timestamp); - - FeatureSet getRemainingFeaturesRealTime(); - - FeatureSet createFeatures(size_t inputIncrement, - std::vector<int> &outputIncrements, - std::vector<float> &phaseResetDf, - std::vector<int> &exactPoints, - std::vector<float> &smoothedDf, - size_t baseCount, - bool includeFinal); -}; - - -RubberBandVampPlugin::RubberBandVampPlugin(float inputSampleRate) : - Plugin(inputSampleRate) -{ - m_d = new Impl(); - m_d->m_stepSize = 0; - m_d->m_timeRatio = 1.f; - m_d->m_pitchRatio = 1.f; - m_d->m_realtime = false; - m_d->m_elasticTiming = true; - m_d->m_transientMode = 0; - m_d->m_phaseIndependent = false; - m_d->m_windowLength = 0; - m_d->m_stretcher = 0; - m_d->m_sampleRate = lrintf(m_inputSampleRate); -} - -RubberBandVampPlugin::~RubberBandVampPlugin() -{ - if (m_d->m_outputDump) { - for (size_t i = 0; i < m_d->m_stretcher->getChannelCount(); ++i) { - delete[] m_d->m_outputDump[i]; - } - delete[] m_d->m_outputDump; - } - delete m_d->m_stretcher; - delete m_d; -} - -string -RubberBandVampPlugin::getIdentifier() const -{ - return "rubberband"; -} - -string -RubberBandVampPlugin::getName() const -{ - return "Rubber Band Timestretch Analysis"; -} - -string -RubberBandVampPlugin::getDescription() const -{ - return "Carry out analysis phases of time stretcher process"; -} - -string -RubberBandVampPlugin::getMaker() const -{ - return "Breakfast Quay"; -} - -int -RubberBandVampPlugin::getPluginVersion() const -{ - return 1; -} - -string -RubberBandVampPlugin::getCopyright() const -{ - return "";//!!! -} - -RubberBandVampPlugin::OutputList -RubberBandVampPlugin::getOutputDescriptors() const -{ - OutputList list; - - size_t rate = 0; - if (m_d->m_stretcher) { - rate = lrintf(m_inputSampleRate / m_d->m_stretcher->getInputIncrement()); - } - - OutputDescriptor d; - d.identifier = "increments"; - d.name = "Output Increments"; - d.description = "Output time increment for each input step"; - d.unit = "samples"; - d.hasFixedBinCount = true; - d.binCount = 1; - d.hasKnownExtents = false; - d.isQuantized = true; - d.quantizeStep = 1.0; - d.sampleType = OutputDescriptor::VariableSampleRate; - d.sampleRate = float(rate); - m_d->m_incrementsOutput = list.size(); - list.push_back(d); - - d.identifier = "aggregate_increments"; - d.name = "Accumulated Output Increments"; - d.description = "Accumulated output time increments"; - d.sampleRate = 0; - m_d->m_aggregateIncrementsOutput = list.size(); - list.push_back(d); - - d.identifier = "divergence"; - d.name = "Divergence from Linear"; - d.description = "Difference between actual output time and the output time for a theoretical linear stretch"; - d.isQuantized = false; - d.sampleRate = 0; - m_d->m_divergenceOutput = list.size(); - list.push_back(d); - - d.identifier = "phaseresetdf"; - d.name = "Phase Reset Detection Function"; - d.description = "Curve whose peaks are used to identify transients for phase reset points"; - d.unit = ""; - d.sampleRate = float(rate); - m_d->m_phaseResetDfOutput = list.size(); - list.push_back(d); - - d.identifier = "smoothedphaseresetdf"; - d.name = "Smoothed Phase Reset Detection Function"; - d.description = "Phase reset curve smoothed for peak picking"; - d.unit = ""; - m_d->m_smoothedPhaseResetDfOutput = list.size(); - list.push_back(d); - - d.identifier = "phaseresetpoints"; - d.name = "Phase Reset Points"; - d.description = "Points estimated as transients at which phase reset occurs"; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = 0; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleRate = 0; - m_d->m_phaseResetPointsOutput = list.size(); - list.push_back(d); - - d.identifier = "timesyncpoints"; - d.name = "Time Sync Points"; - d.description = "Salient points which stretcher aims to place with strictly correct timing"; - d.unit = ""; - d.hasFixedBinCount = true; - d.binCount = 0; - d.hasKnownExtents = false; - d.isQuantized = false; - d.sampleRate = 0; - m_d->m_timeSyncPointsOutput = list.size(); - list.push_back(d); - - return list; -} - -RubberBandVampPlugin::ParameterList -RubberBandVampPlugin::getParameterDescriptors() const -{ - ParameterList list; - - ParameterDescriptor d; - d.identifier = "timeratio"; - d.name = "Time Ratio"; - d.description = "Ratio to modify overall duration by"; - d.unit = "%"; - d.minValue = 1; - d.maxValue = 500; - d.defaultValue = 100; - d.isQuantized = false; - list.push_back(d); - - d.identifier = "pitchratio"; - d.name = "Pitch Scale Ratio"; - d.description = "Frequency ratio to modify pitch by"; - d.unit = "%"; - d.minValue = 1; - d.maxValue = 500; - d.defaultValue = 100; - d.isQuantized = false; - list.push_back(d); - - d.identifier = "mode"; - d.name = "Processing Mode"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 1; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Offline"); - d.valueNames.push_back("Real Time"); - list.push_back(d); - - d.identifier = "stretchtype"; - d.name = "Stretch Flexibility"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 1; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Elastic"); - d.valueNames.push_back("Precise"); - list.push_back(d); - - d.identifier = "transientmode"; - d.name = "Transient Handling"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 2; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Mixed"); - d.valueNames.push_back("Smooth"); - d.valueNames.push_back("Crisp"); - list.push_back(d); - - d.identifier = "phasemode"; - d.name = "Phase Handling"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 1; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Peak Locked"); - d.valueNames.push_back("Independent"); - list.push_back(d); - - d.identifier = "windowmode"; - d.name = "Window Length"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0; - d.maxValue = 2; - d.defaultValue = 0; - d.isQuantized = true; - d.quantizeStep = 1; - d.valueNames.clear(); - d.valueNames.push_back("Standard"); - d.valueNames.push_back("Short"); - d.valueNames.push_back("Long"); - list.push_back(d); - - return list; -} - -float -RubberBandVampPlugin::getParameter(std::string id) const -{ - if (id == "timeratio") return m_d->m_timeRatio * 100.f; - if (id == "pitchratio") return m_d->m_pitchRatio * 100.f; - if (id == "mode") return m_d->m_realtime ? 1.f : 0.f; - if (id == "stretchtype") return m_d->m_elasticTiming ? 0.f : 1.f; - if (id == "transientmode") return float(m_d->m_transientMode); - if (id == "phasemode") return m_d->m_phaseIndependent ? 1.f : 0.f; - if (id == "windowmode") return float(m_d->m_windowLength); - return 0.f; -} - -void -RubberBandVampPlugin::setParameter(std::string id, float value) -{ - if (id == "timeratio") { - m_d->m_timeRatio = value / 100; - } else if (id == "pitchratio") { - m_d->m_pitchRatio = value / 100; - } else { - bool set = (value > 0.5); - if (id == "mode") m_d->m_realtime = set; - else if (id == "stretchtype") m_d->m_elasticTiming = !set; - else if (id == "transientmode") m_d->m_transientMode = int(value + 0.5); - else if (id == "phasemode") m_d->m_phaseIndependent = set; - else if (id == "windowmode") m_d->m_windowLength = int(value + 0.5); - } -} - -bool -RubberBandVampPlugin::initialise(size_t channels, size_t stepSize, size_t blockSize) -{ - if (channels < getMinChannelCount() || - channels > getMaxChannelCount()) return false; - - m_d->m_stepSize = std::min(stepSize, blockSize); - m_d->m_blockSize = stepSize; - - RubberBand::RubberBandStretcher::Options options = 0; - - if (m_d->m_realtime) - options |= RubberBand::RubberBandStretcher::OptionProcessRealTime; - else options |= RubberBand::RubberBandStretcher::OptionProcessOffline; - - if (m_d->m_elasticTiming) - options |= RubberBand::RubberBandStretcher::OptionStretchElastic; - else options |= RubberBand::RubberBandStretcher::OptionStretchPrecise; - - if (m_d->m_transientMode == 0) - options |= RubberBand::RubberBandStretcher::OptionTransientsMixed; - else if (m_d->m_transientMode == 1) - options |= RubberBand::RubberBandStretcher::OptionTransientsSmooth; - else options |= RubberBand::RubberBandStretcher::OptionTransientsCrisp; - - if (m_d->m_phaseIndependent) - options |= RubberBand::RubberBandStretcher::OptionPhaseIndependent; - else options |= RubberBand::RubberBandStretcher::OptionPhaseLaminar; - - if (m_d->m_windowLength == 0) - options |= RubberBand::RubberBandStretcher::OptionWindowStandard; - else if (m_d->m_windowLength == 1) - options |= RubberBand::RubberBandStretcher::OptionWindowShort; - else options |= RubberBand::RubberBandStretcher::OptionWindowLong; - - delete m_d->m_stretcher; - m_d->m_stretcher = new RubberBand::RubberBandStretcher - (m_d->m_sampleRate, channels, options); - m_d->m_stretcher->setDebugLevel(1); - m_d->m_stretcher->setTimeRatio(m_d->m_timeRatio); - m_d->m_stretcher->setPitchScale(m_d->m_pitchRatio); - - m_d->m_counter = 0; - m_d->m_accumulatedIncrement = 0; - - m_d->m_outputDump = 0; - - return true; -} - -void -RubberBandVampPlugin::reset() -{ -// delete m_stretcher; //!!! or just if (m_stretcher) m_stretcher->reset(); -// m_stretcher = new RubberBand::RubberBandStretcher(lrintf(m_inputSampleRate), channels); - if (m_d->m_stretcher) m_d->m_stretcher->reset(); -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::process(const float *const *inputBuffers, - Vamp::RealTime timestamp) -{ - if (m_d->m_realtime) { - return m_d->processRealTime(inputBuffers, timestamp); - } else { - return m_d->processOffline(inputBuffers, timestamp); - } -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::getRemainingFeatures() -{ - if (m_d->m_realtime) { - return m_d->getRemainingFeaturesRealTime(); - } else { - return m_d->getRemainingFeaturesOffline(); - } -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::processOffline(const float *const *inputBuffers, - Vamp::RealTime timestamp) -{ - if (!m_stretcher) { - cerr << "ERROR: RubberBandVampPlugin::processOffline: " - << "RubberBandVampPlugin has not been initialised" - << endl; - return FeatureSet(); - } - - m_stretcher->study(inputBuffers, m_blockSize, false); - return FeatureSet(); -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::getRemainingFeaturesOffline() -{ - m_stretcher->study(0, 0, true); - - m_stretcher->calculateStretch(); - - int rate = m_sampleRate; - - RubberBand::StretchCalculator sc(rate, - m_stretcher->getInputIncrement(), - true); - - size_t inputIncrement = m_stretcher->getInputIncrement(); - std::vector<int> outputIncrements = m_stretcher->getOutputIncrements(); - std::vector<float> phaseResetDf = m_stretcher->getPhaseResetCurve(); - std::vector<int> peaks = m_stretcher->getExactTimePoints(); - std::vector<float> smoothedDf = sc.smoothDF(phaseResetDf); - - FeatureSet features = createFeatures - (inputIncrement, outputIncrements, phaseResetDf, peaks, smoothedDf, - 0, true); - - return features; -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::processRealTime(const float *const *inputBuffers, - Vamp::RealTime timestamp) -{ - // This function is not in any way a real-time function (i.e. it - // has no requirement to be RT safe); it simply operates the - // stretcher in RT mode. - - if (!m_stretcher) { - cerr << "ERROR: RubberBandVampPlugin::processRealTime: " - << "RubberBandVampPlugin has not been initialised" - << endl; - return FeatureSet(); - } - - m_stretcher->process(inputBuffers, m_blockSize, false); - - size_t inputIncrement = m_stretcher->getInputIncrement(); - std::vector<int> outputIncrements = m_stretcher->getOutputIncrements(); - std::vector<float> phaseResetDf = m_stretcher->getPhaseResetCurve(); - std::vector<float> smoothedDf; // not meaningful in RT mode - std::vector<int> dummyPoints; - FeatureSet features = createFeatures - (inputIncrement, outputIncrements, phaseResetDf, dummyPoints, smoothedDf, - m_counter, false); - m_counter += outputIncrements.size(); - - int available = 0; - while ((available = m_stretcher->available()) > 0) { - if (!m_outputDump) { - m_outputDump = new float *[m_stretcher->getChannelCount()]; - for (size_t i = 0; i < m_stretcher->getChannelCount(); ++i) { - m_outputDump[i] = new float[m_blockSize]; - } - } - m_stretcher->retrieve(m_outputDump, - std::min(int(m_blockSize), available)); - } - - return features; -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::getRemainingFeaturesRealTime() -{ - return FeatureSet(); -} - -RubberBandVampPlugin::FeatureSet -RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement, - std::vector<int> &outputIncrements, - std::vector<float> &phaseResetDf, - std::vector<int> &exactPoints, - std::vector<float> &smoothedDf, - size_t baseCount, - bool includeFinal) -{ - size_t actual = m_accumulatedIncrement; - - double overallRatio = m_timeRatio * m_pitchRatio; - - char label[200]; - - FeatureSet features; - - int rate = m_sampleRate; - - size_t epi = 0; - - for (size_t i = 0; i < outputIncrements.size(); ++i) { - - size_t frame = (baseCount + i) * inputIncrement; - - int oi = outputIncrements[i]; - bool hard = false; - bool soft = false; - - if (oi < 0) { - oi = -oi; - hard = true; - } - - if (epi < exactPoints.size() && int(i) == exactPoints[epi]) { - soft = true; - ++epi; - } - - double linear = (frame * overallRatio); - - Vamp::RealTime t = Vamp::RealTime::frame2RealTime(frame, rate); - - Feature feature; - feature.hasTimestamp = true; - feature.timestamp = t; - feature.values.push_back(float(oi)); - feature.label = Vamp::RealTime::frame2RealTime(oi, rate).toText(); - features[m_incrementsOutput].push_back(feature); - - feature.values.clear(); - feature.values.push_back(float(actual)); - feature.label = Vamp::RealTime::frame2RealTime(actual, rate).toText(); - features[m_aggregateIncrementsOutput].push_back(feature); - - feature.values.clear(); - feature.values.push_back(actual - linear); - - sprintf(label, "expected %ld, actual %ld, difference %ld (%s ms)", - long(linear), long(actual), long(actual - linear), - // frame2RealTime expects an integer frame number, - // hence our multiplication factor - (Vamp::RealTime::frame2RealTime - (lrintf((actual - linear) * 1000), rate) / 1000) - .toText().c_str()); - feature.label = label; - - features[m_divergenceOutput].push_back(feature); - actual += oi; - - char buf[30]; - - if (i < phaseResetDf.size()) { - feature.values.clear(); - feature.values.push_back(phaseResetDf[i]); - sprintf(buf, "%d", int(baseCount + i)); - feature.label = buf; - features[m_phaseResetDfOutput].push_back(feature); - } - - if (i < smoothedDf.size()) { - feature.values.clear(); - feature.values.push_back(smoothedDf[i]); - features[m_smoothedPhaseResetDfOutput].push_back(feature); - } - - if (hard) { - feature.values.clear(); - feature.label = "Phase Reset"; - features[m_phaseResetPointsOutput].push_back(feature); - } - - if (hard || soft) { - feature.values.clear(); - feature.label = "Time Sync"; - features[m_timeSyncPointsOutput].push_back(feature); - } - } - - if (includeFinal) { - Vamp::RealTime t = Vamp::RealTime::frame2RealTime - (inputIncrement * (baseCount + outputIncrements.size()), rate); - Feature feature; - feature.hasTimestamp = true; - feature.timestamp = t; - feature.label = Vamp::RealTime::frame2RealTime(actual, rate).toText(); - feature.values.clear(); - feature.values.push_back(float(actual)); - features[m_aggregateIncrementsOutput].push_back(feature); - - float linear = ((baseCount + outputIncrements.size()) - * inputIncrement * overallRatio); - feature.values.clear(); - feature.values.push_back(actual - linear); - feature.label = // see earlier comment - (Vamp::RealTime::frame2RealTime //!!! update this as earlier label - (lrintf((actual - linear) * 1000), rate) / 1000) - .toText(); - features[m_divergenceOutput].push_back(feature); - } - - m_accumulatedIncrement = actual; - - return features; -} - |