* Some code rearrangement
* Threading fixes (corrections to condition usage) * Avoid a potential hang when faced with some peculiar stretch factors * More modular calls out to vectorizable functions * Solaris build fixes * Bump version number
This commit is contained in:
648
vamp/RubberBandVampPlugin.cpp
Normal file
648
vamp/RubberBandVampPlugin.cpp
Normal file
@@ -0,0 +1,648 @@
|
||||
/* -*- 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-2009 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 "system/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;
|
||||
}
|
||||
|
||||
56
vamp/RubberBandVampPlugin.h
Normal file
56
vamp/RubberBandVampPlugin.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* -*- 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-2009 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.
|
||||
*/
|
||||
|
||||
#ifndef _RUBBERBAND_VAMP_PLUGIN_H_
|
||||
#define _RUBBERBAND_VAMP_PLUGIN_H_
|
||||
|
||||
#include <vamp-sdk/Plugin.h>
|
||||
|
||||
#include "RubberBandStretcher.h"
|
||||
|
||||
class RubberBandVampPlugin : public Vamp::Plugin
|
||||
{
|
||||
public:
|
||||
RubberBandVampPlugin(float inputSampleRate);
|
||||
virtual ~RubberBandVampPlugin();
|
||||
|
||||
bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
||||
void reset();
|
||||
|
||||
InputDomain getInputDomain() const { return TimeDomain; }
|
||||
|
||||
std::string getIdentifier() const;
|
||||
std::string getName() const;
|
||||
std::string getDescription() const;
|
||||
std::string getMaker() const;
|
||||
int getPluginVersion() const;
|
||||
std::string getCopyright() const;
|
||||
|
||||
ParameterList getParameterDescriptors() const;
|
||||
float getParameter(std::string id) const;
|
||||
void setParameter(std::string id, float value);
|
||||
|
||||
OutputList getOutputDescriptors() const;
|
||||
|
||||
FeatureSet process(const float *const *inputBuffers,
|
||||
Vamp::RealTime timestamp);
|
||||
|
||||
FeatureSet getRemainingFeatures();
|
||||
|
||||
protected:
|
||||
class Impl;
|
||||
Impl *m_d;
|
||||
};
|
||||
|
||||
#endif
|
||||
32
vamp/libmain.cpp
Normal file
32
vamp/libmain.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* -*- 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-2009 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 <vamp/vamp.h>
|
||||
#include <vamp-sdk/PluginAdapter.h>
|
||||
|
||||
#include "RubberBandVampPlugin.h"
|
||||
|
||||
static Vamp::PluginAdapter<RubberBandVampPlugin> rubberBandAdapter;
|
||||
|
||||
const VampPluginDescriptor *vampGetPluginDescriptor(unsigned int version,
|
||||
unsigned int index)
|
||||
{
|
||||
if (version < 1) return 0;
|
||||
|
||||
switch (index) {
|
||||
case 0: return rubberBandAdapter.getDescriptor();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
4
vamp/vamp-plugin.map
Normal file
4
vamp/vamp-plugin.map
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
global: vampGetPluginDescriptor;
|
||||
local: *;
|
||||
};
|
||||
1
vamp/vamp-rubberband.cat
Normal file
1
vamp/vamp-rubberband.cat
Normal file
@@ -0,0 +1 @@
|
||||
vamp:vamp-rubberband:rubberband::Time > Timestretch Analysis
|
||||
Reference in New Issue
Block a user