* More rationalisation -- lock becomes phase reset in most cases
* Update Vamp plugin parameters and outputs
This commit is contained in:
@@ -89,7 +89,7 @@ public:
|
|||||||
|
|
||||||
virtual size_t getInputIncrement() const;
|
virtual size_t getInputIncrement() const;
|
||||||
virtual std::vector<int> getOutputIncrements() const; //!!! document particular meaning in RT mode
|
virtual std::vector<int> getOutputIncrements() const; //!!! document particular meaning in RT mode
|
||||||
virtual std::vector<float> getLockCurve() const; //!!! document particular meaning in RT mode
|
virtual std::vector<float> getPhaseResetCurve() const; //!!! document particular meaning in RT mode
|
||||||
virtual std::vector<int> getExactTimePoints() const; //!!! meaningless in RT mode
|
virtual std::vector<int> getExactTimePoints() const; //!!! meaningless in RT mode
|
||||||
|
|
||||||
virtual size_t getChannelCount() const;
|
virtual size_t getChannelCount() const;
|
||||||
|
|||||||
@@ -150,9 +150,9 @@ RubberBandStretcher::getOutputIncrements() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float>
|
std::vector<float>
|
||||||
RubberBandStretcher::getLockCurve() const
|
RubberBandStretcher::getPhaseResetCurve() const
|
||||||
{
|
{
|
||||||
return m_d->getLockCurve();
|
return m_d->getPhaseResetCurve();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int>
|
std::vector<int>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ StretchCalculator::~StretchCalculator()
|
|||||||
|
|
||||||
std::vector<int>
|
std::vector<int>
|
||||||
StretchCalculator::calculate(double ratio, size_t inputDuration,
|
StretchCalculator::calculate(double ratio, size_t inputDuration,
|
||||||
const std::vector<float> &lockDf,
|
const std::vector<float> &phaseResetDf,
|
||||||
const std::vector<float> &stretchDf)
|
const std::vector<float> &stretchDf)
|
||||||
{
|
{
|
||||||
// Method:
|
// Method:
|
||||||
@@ -53,14 +53,14 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
|
|
||||||
// 1. Pre-process the df array, and for each (say) one second's
|
// 1. Pre-process the df array, and for each (say) one second's
|
||||||
// worth of values, calculate the number of peaks that would
|
// worth of values, calculate the number of peaks that would
|
||||||
// qualify for phase locking given the default threshold. Then
|
// qualify for phase reset given the default threshold. Then
|
||||||
// reduce or increase the threshold by stages until that number is
|
// reduce or increase the threshold by stages until that number is
|
||||||
// in a sensible range (say 1-10 peaks per second -- the low end
|
// in a sensible range (say 1-10 peaks per second -- the low end
|
||||||
// is harder to estimate than the high end, so it may be better to
|
// is harder to estimate than the high end, so it may be better to
|
||||||
// start with a high sensitivity and reduce it).
|
// start with a high sensitivity and reduce it).
|
||||||
|
|
||||||
// 2. Record the positions of peaks, and separately the positions
|
// 2. Record the positions of peaks, and separately the positions
|
||||||
// of those peaks that qualify for locking using the sliding
|
// of those peaks that qualify for reset using the sliding
|
||||||
// threshold window. Don't permit two locked peaks within a very
|
// threshold window. Don't permit two locked peaks within a very
|
||||||
// short time frame (e.g. 30-50ms).
|
// short time frame (e.g. 30-50ms).
|
||||||
|
|
||||||
@@ -79,11 +79,11 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
// Then divvy them up... how exactly?
|
// Then divvy them up... how exactly?
|
||||||
|
|
||||||
|
|
||||||
assert(lockDf.size() == stretchDf.size());
|
assert(phaseResetDf.size() == stretchDf.size());
|
||||||
|
|
||||||
m_lastPeaks = findPeaks(lockDf);
|
m_lastPeaks = findPeaks(phaseResetDf);
|
||||||
std::vector<Peak> &peaks = m_lastPeaks;
|
std::vector<Peak> &peaks = m_lastPeaks;
|
||||||
size_t totalCount = lockDf.size();
|
size_t totalCount = phaseResetDf.size();
|
||||||
|
|
||||||
std::vector<int> increments;
|
std::vector<int> increments;
|
||||||
|
|
||||||
@@ -96,11 +96,11 @@ StretchCalculator::calculate(double ratio, size_t inputDuration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//!!! round down?
|
//!!! round down?
|
||||||
outputDuration = lrint((lockDf.size() * m_increment) * ratio);
|
outputDuration = lrint((phaseResetDf.size() * m_increment) * ratio);
|
||||||
|
|
||||||
if (m_debugLevel > 0) {
|
if (m_debugLevel > 0) {
|
||||||
std::cerr << " (rounded up to " << outputDuration << ")";
|
std::cerr << " (rounded up to " << outputDuration << ")";
|
||||||
std::cerr << ", df size " << lockDf.size() << std::endl;
|
std::cerr << ", df size " << phaseResetDf.size() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// size_t stretchable = outputDuration - lockCount * m_increment;
|
// size_t stretchable = outputDuration - lockCount * m_increment;
|
||||||
@@ -329,10 +329,10 @@ StretchCalculator::findPeaks(const std::vector<float> &rawDf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//!!! we don't yet do the right thing with soft peaks. if
|
//!!! we don't yet do the right thing with soft peaks. if
|
||||||
//!useHardPeaks, we should be locking on soft peaks; if
|
//!useHardPeaks, we should be resetting on soft peaks; if
|
||||||
//useHardPeaks, we should be ignoring soft peaks if they occur
|
//useHardPeaks, we should be ignoring soft peaks if they occur
|
||||||
//shortly after hard ones, otherwise either locking on them, or at
|
//shortly after hard ones, otherwise either resetting on them, or
|
||||||
//least making sure they fall at the correct sample time
|
//at least making sure they fall at the correct sample time
|
||||||
|
|
||||||
// int mediansize = lrint(ceil(double(m_sampleRate) /
|
// int mediansize = lrint(ceil(double(m_sampleRate) /
|
||||||
// (4 * double(m_increment)))); // 0.25 sec ish
|
// (4 * double(m_increment)))); // 0.25 sec ish
|
||||||
@@ -444,11 +444,11 @@ StretchCalculator::findPeaks(const std::vector<float> &rawDf)
|
|||||||
//a very rapid rise in detection function prior to the
|
//a very rapid rise in detection function prior to the
|
||||||
//peak (the first value after the rise is not necessarily
|
//peak (the first value after the rise is not necessarily
|
||||||
//the peak itself, but it is probably where we should
|
//the peak itself, but it is probably where we should
|
||||||
//locate the lock). For hard peaks we need to lock in
|
//locate the phase reset). For hard peaks we need to
|
||||||
//time to preserve the shape of the transient (unless some
|
//reset in time to preserve the shape of the transient
|
||||||
//option is set to soft mode), for soft peaks we just want
|
//(unless some option is set to soft mode), for soft peaks
|
||||||
//to avoid poor timing positioning so we build up to the
|
//we just want to avoid poor timing positioning so we
|
||||||
//lock at the exact peak moment.
|
//build up to the reset at the exact peak moment.
|
||||||
|
|
||||||
// size_t peak = i + maxindex - mediansize;
|
// size_t peak = i + maxindex - mediansize;
|
||||||
size_t peak = i + maxindex - middle;
|
size_t peak = i + maxindex - middle;
|
||||||
@@ -563,7 +563,7 @@ StretchCalculator::smoothDF(const std::vector<float> &df)
|
|||||||
|
|
||||||
std::vector<int>
|
std::vector<int>
|
||||||
StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
||||||
size_t duration, float ratio, bool lock)
|
size_t duration, float ratio, bool phaseReset)
|
||||||
{
|
{
|
||||||
std::vector<float> df(dfIn);
|
std::vector<float> df(dfIn);
|
||||||
std::vector<int> increments;
|
std::vector<int> increments;
|
||||||
@@ -706,7 +706,7 @@ StretchCalculator::distributeRegion(const std::vector<float> &dfIn,
|
|||||||
if (displacement < 0) displacement -= adj;
|
if (displacement < 0) displacement -= adj;
|
||||||
else displacement += adj;
|
else displacement += adj;
|
||||||
|
|
||||||
if (i == 0 && lock) {
|
if (i == 0 && phaseReset) {
|
||||||
if (df.size() == 1) {
|
if (df.size() == 1) {
|
||||||
increments.push_back(duration);
|
increments.push_back(duration);
|
||||||
totalIncrement += duration;
|
totalIncrement += duration;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ protected:
|
|||||||
|
|
||||||
std::vector<int> distributeRegion(const std::vector<float> ®ionCurve,
|
std::vector<int> distributeRegion(const std::vector<float> ®ionCurve,
|
||||||
size_t outputDuration, float ratio,
|
size_t outputDuration, float ratio,
|
||||||
bool lock);
|
bool phaseReset);
|
||||||
|
|
||||||
void calculateDisplacements(const std::vector<float> &df,
|
void calculateDisplacements(const std::vector<float> &df,
|
||||||
float &maxDf,
|
float &maxDf,
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher,
|
|||||||
m_studyFFT(0),
|
m_studyFFT(0),
|
||||||
m_inputDuration(0),
|
m_inputDuration(0),
|
||||||
m_lastProcessOutputIncrements(16),
|
m_lastProcessOutputIncrements(16),
|
||||||
m_lastProcessLockDf(16),
|
m_lastProcessPhaseResetDf(16),
|
||||||
m_lockAudioCurve(0),
|
m_phaseResetAudioCurve(0),
|
||||||
m_stretchAudioCurve(0),
|
m_stretchAudioCurve(0),
|
||||||
m_stretchCalculator(0),
|
m_stretchCalculator(0),
|
||||||
m_freq0(600),
|
m_freq0(600),
|
||||||
@@ -134,7 +134,7 @@ RubberBandStretcher::Impl::~Impl()
|
|||||||
delete m_channelData[c];
|
delete m_channelData[c];
|
||||||
}
|
}
|
||||||
|
|
||||||
delete m_lockAudioCurve;
|
delete m_phaseResetAudioCurve;
|
||||||
delete m_stretchAudioCurve;
|
delete m_stretchAudioCurve;
|
||||||
delete m_stretchCalculator;
|
delete m_stretchCalculator;
|
||||||
delete m_studyFFT;
|
delete m_studyFFT;
|
||||||
@@ -157,7 +157,7 @@ RubberBandStretcher::Impl::reset()
|
|||||||
m_channelData[c] = new ChannelData(m_windowSize, m_outbufSize);
|
m_channelData[c] = new ChannelData(m_windowSize, m_outbufSize);
|
||||||
}
|
}
|
||||||
m_mode = JustCreated;
|
m_mode = JustCreated;
|
||||||
if (m_lockAudioCurve) m_lockAudioCurve->reset();
|
if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset();
|
||||||
if (m_stretchAudioCurve) m_stretchAudioCurve->reset();
|
if (m_stretchAudioCurve) m_stretchAudioCurve->reset();
|
||||||
m_inputDuration = 0;
|
m_inputDuration = 0;
|
||||||
|
|
||||||
@@ -478,11 +478,11 @@ RubberBandStretcher::Impl::configure()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete m_lockAudioCurve;
|
delete m_phaseResetAudioCurve;
|
||||||
m_lockAudioCurve = new PercussiveAudioCurve(m_stretcher->m_sampleRate,
|
m_phaseResetAudioCurve = new PercussiveAudioCurve(m_stretcher->m_sampleRate,
|
||||||
m_windowSize);
|
m_windowSize);
|
||||||
|
|
||||||
// stretchAudioCurve unused in RT mode; lockAudioCurve and
|
// stretchAudioCurve unused in RT mode; phaseResetAudioCurve and
|
||||||
// stretchCalculator however are used in all modes
|
// stretchCalculator however are used in all modes
|
||||||
|
|
||||||
if (!m_realtime) {
|
if (!m_realtime) {
|
||||||
@@ -536,7 +536,7 @@ RubberBandStretcher::Impl::reconfigure()
|
|||||||
// stop and calculate the stretch curve so far, then reset
|
// stop and calculate the stretch curve so far, then reset
|
||||||
// the df vectors
|
// the df vectors
|
||||||
calculateStretch();
|
calculateStretch();
|
||||||
m_lockDf.clear();
|
m_phaseResetDf.clear();
|
||||||
m_stretchDf.clear();
|
m_stretchDf.clear();
|
||||||
m_inputDuration = 0;
|
m_inputDuration = 0;
|
||||||
}
|
}
|
||||||
@@ -592,7 +592,7 @@ RubberBandStretcher::Impl::reconfigure()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_windowSize != prevWindowSize) {
|
if (m_windowSize != prevWindowSize) {
|
||||||
m_lockAudioCurve->setWindowSize(m_windowSize);
|
m_phaseResetAudioCurve->setWindowSize(m_windowSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,10 +705,10 @@ RubberBandStretcher::Impl::study(const float *const *input, size_t samples, bool
|
|||||||
|
|
||||||
m_studyFFT->forwardMagnitude(cd.accumulator, cd.fltbuf);
|
m_studyFFT->forwardMagnitude(cd.accumulator, cd.fltbuf);
|
||||||
|
|
||||||
float df = m_lockAudioCurve->process(cd.fltbuf, m_increment);
|
float df = m_phaseResetAudioCurve->process(cd.fltbuf, m_increment);
|
||||||
m_lockDf.push_back(df);
|
m_phaseResetDf.push_back(df);
|
||||||
|
|
||||||
// cout << m_lockDf.size() << " [" << final << "] -> " << df << " \t: ";
|
// cout << m_phaseResetDf.size() << " [" << final << "] -> " << df << " \t: ";
|
||||||
|
|
||||||
df = m_stretchAudioCurve->process(cd.fltbuf, m_increment);
|
df = m_stretchAudioCurve->process(cd.fltbuf, m_increment);
|
||||||
m_stretchDf.push_back(df);
|
m_stretchDf.push_back(df);
|
||||||
@@ -756,14 +756,14 @@ RubberBandStretcher::Impl::getOutputIncrements() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector<float>
|
vector<float>
|
||||||
RubberBandStretcher::Impl::getLockCurve() const
|
RubberBandStretcher::Impl::getPhaseResetCurve() const
|
||||||
{
|
{
|
||||||
if (!m_realtime) {
|
if (!m_realtime) {
|
||||||
return m_lockDf;
|
return m_phaseResetDf;
|
||||||
} else {
|
} else {
|
||||||
vector<float> df;
|
vector<float> df;
|
||||||
while (m_lastProcessLockDf.getReadSpace() > 0) {
|
while (m_lastProcessPhaseResetDf.getReadSpace() > 0) {
|
||||||
df.push_back(m_lastProcessLockDf.readOne());
|
df.push_back(m_lastProcessPhaseResetDf.readOne());
|
||||||
}
|
}
|
||||||
return df;
|
return df;
|
||||||
}
|
}
|
||||||
@@ -789,7 +789,7 @@ RubberBandStretcher::Impl::calculateStretch()
|
|||||||
std::vector<int> increments = m_stretchCalculator->calculate
|
std::vector<int> increments = m_stretchCalculator->calculate
|
||||||
(getEffectiveRatio(),
|
(getEffectiveRatio(),
|
||||||
m_inputDuration,
|
m_inputDuration,
|
||||||
m_lockDf,
|
m_phaseResetDf,
|
||||||
m_stretchDf);
|
m_stretchDf);
|
||||||
|
|
||||||
if (m_outputIncrements.empty()) m_outputIncrements = increments;
|
if (m_outputIncrements.empty()) m_outputIncrements = increments;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> getOutputIncrements() const;
|
std::vector<int> getOutputIncrements() const;
|
||||||
std::vector<float> getLockCurve() const;
|
std::vector<float> getPhaseResetCurve() const;
|
||||||
std::vector<int> getExactTimePoints() const;
|
std::vector<int> getExactTimePoints() const;
|
||||||
|
|
||||||
size_t getChannelCount() const {
|
size_t getChannelCount() const {
|
||||||
@@ -89,14 +89,14 @@ protected:
|
|||||||
bool processChunks(size_t channel); // returns "last"
|
bool processChunks(size_t channel); // returns "last"
|
||||||
bool processOneChunk(); // across all channels, for real time use
|
bool processOneChunk(); // across all channels, for real time use
|
||||||
bool processChunkForChannel(size_t channel, size_t phaseIncrement,
|
bool processChunkForChannel(size_t channel, size_t phaseIncrement,
|
||||||
size_t shiftIncrement, bool lock);
|
size_t shiftIncrement, bool phaseReset);
|
||||||
bool testInbufReadSpace(size_t channel);
|
bool testInbufReadSpace(size_t channel);
|
||||||
void calculateIncrements(size_t &phaseIncrement,
|
void calculateIncrements(size_t &phaseIncrement,
|
||||||
size_t &shiftIncrement, bool &lock);
|
size_t &shiftIncrement, bool &phaseReset);
|
||||||
bool getIncrements(size_t channel, size_t &phaseIncrement,
|
bool getIncrements(size_t channel, size_t &phaseIncrement,
|
||||||
size_t &shiftIncrement, bool &lock);
|
size_t &shiftIncrement, bool &phaseReset);
|
||||||
void analyseChunk(size_t channel);
|
void analyseChunk(size_t channel);
|
||||||
void modifyChunk(size_t channel, size_t outputIncrement, bool lock);
|
void modifyChunk(size_t channel, size_t outputIncrement, bool phaseReset);
|
||||||
void synthesiseChunk(size_t channel);
|
void synthesiseChunk(size_t channel);
|
||||||
void writeChunk(size_t channel, size_t shiftIncrement, bool last);
|
void writeChunk(size_t channel, size_t shiftIncrement, bool last);
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ protected:
|
|||||||
|
|
||||||
|
|
||||||
size_t m_inputDuration;
|
size_t m_inputDuration;
|
||||||
std::vector<float> m_lockDf;
|
std::vector<float> m_phaseResetDf;
|
||||||
std::vector<float> m_stretchDf;
|
std::vector<float> m_stretchDf;
|
||||||
|
|
||||||
class ChannelData;
|
class ChannelData;
|
||||||
@@ -163,9 +163,9 @@ protected:
|
|||||||
std::vector<int> m_outputIncrements;
|
std::vector<int> m_outputIncrements;
|
||||||
|
|
||||||
mutable RingBuffer<int> m_lastProcessOutputIncrements;
|
mutable RingBuffer<int> m_lastProcessOutputIncrements;
|
||||||
mutable RingBuffer<float> m_lastProcessLockDf;
|
mutable RingBuffer<float> m_lastProcessPhaseResetDf;
|
||||||
|
|
||||||
AudioCurve *m_lockAudioCurve;
|
AudioCurve *m_phaseResetAudioCurve;
|
||||||
AudioCurve *m_stretchAudioCurve;
|
AudioCurve *m_stretchAudioCurve;
|
||||||
StretchCalculator *m_stretchCalculator;
|
StretchCalculator *m_stretchCalculator;
|
||||||
|
|
||||||
|
|||||||
@@ -89,11 +89,11 @@ RubberBandStretcher::Impl::processChunks(size_t c)
|
|||||||
analyseChunk(c);
|
analyseChunk(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lock = false;
|
bool phaseReset = false;
|
||||||
size_t phaseIncrement, shiftIncrement;
|
size_t phaseIncrement, shiftIncrement;
|
||||||
getIncrements(c, phaseIncrement, shiftIncrement, lock);
|
getIncrements(c, phaseIncrement, shiftIncrement, phaseReset);
|
||||||
|
|
||||||
last = processChunkForChannel(c, phaseIncrement, shiftIncrement, lock);
|
last = processChunkForChannel(c, phaseIncrement, shiftIncrement, phaseReset);
|
||||||
cd.chunkCount++;
|
cd.chunkCount++;
|
||||||
if (m_debugLevel > 2) {
|
if (m_debugLevel > 2) {
|
||||||
cerr << "channel " << c << ": last = " << last << ", chunkCount = " << cd.chunkCount << endl;
|
cerr << "channel " << c << ": last = " << last << ", chunkCount = " << cd.chunkCount << endl;
|
||||||
@@ -121,15 +121,15 @@ RubberBandStretcher::Impl::processOneChunk()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lock = false;
|
bool phaseReset = false;
|
||||||
size_t phaseIncrement, shiftIncrement;
|
size_t phaseIncrement, shiftIncrement;
|
||||||
if (!getIncrements(0, phaseIncrement, shiftIncrement, lock)) {
|
if (!getIncrements(0, phaseIncrement, shiftIncrement, phaseReset)) {
|
||||||
calculateIncrements(phaseIncrement, shiftIncrement, lock);
|
calculateIncrements(phaseIncrement, shiftIncrement, phaseReset);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool last = false;
|
bool last = false;
|
||||||
for (size_t c = 0; c < m_channels; ++c) {
|
for (size_t c = 0; c < m_channels; ++c) {
|
||||||
last = processChunkForChannel(c, phaseIncrement, shiftIncrement, lock);
|
last = processChunkForChannel(c, phaseIncrement, shiftIncrement, phaseReset);
|
||||||
m_channelData[c]->chunkCount++;
|
m_channelData[c]->chunkCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,15 +187,15 @@ bool
|
|||||||
RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
||||||
size_t phaseIncrement,
|
size_t phaseIncrement,
|
||||||
size_t shiftIncrement,
|
size_t shiftIncrement,
|
||||||
bool lock)
|
bool phaseReset)
|
||||||
{
|
{
|
||||||
// Process a single chunk on a single channel. This assumes
|
// Process a single chunk on a single channel. This assumes
|
||||||
// enough input data is available; caller must have tested this
|
// enough input data is available; caller must have tested this
|
||||||
// using e.g. testInbufReadSpace first. Return true if this is
|
// using e.g. testInbufReadSpace first. Return true if this is
|
||||||
// the last chunk on the channel.
|
// the last chunk on the channel.
|
||||||
|
|
||||||
if (lock && (m_debugLevel > 1)) {
|
if (phaseReset && (m_debugLevel > 1)) {
|
||||||
cerr << "processChunkForChannel: lock found, incrs "
|
cerr << "processChunkForChannel: phase reset found, incrs "
|
||||||
<< phaseIncrement << ":" << shiftIncrement << endl;
|
<< phaseIncrement << ":" << shiftIncrement << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,11 +216,11 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
|||||||
// We need to peek m_windowSize samples for processing, and
|
// We need to peek m_windowSize samples for processing, and
|
||||||
// then skip m_increment to advance the read pointer.
|
// then skip m_increment to advance the read pointer.
|
||||||
|
|
||||||
modifyChunk(c, phaseIncrement, lock);
|
modifyChunk(c, phaseIncrement, phaseReset);
|
||||||
synthesiseChunk(c); // reads from cd.mag, cd.phase
|
synthesiseChunk(c); // reads from cd.mag, cd.phase
|
||||||
|
|
||||||
if (m_debugLevel > 2) {
|
if (m_debugLevel > 2) {
|
||||||
if (lock) {
|
if (phaseReset) {
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
cd.accumulator[i] = ((drand48() * 2 - 1.0) > 0 ? 1 : -1);
|
cd.accumulator[i] = ((drand48() * 2 - 1.0) > 0 ? 1 : -1);
|
||||||
}
|
}
|
||||||
@@ -277,7 +277,7 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c,
|
|||||||
void
|
void
|
||||||
RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
||||||
size_t &shiftIncrementRtn,
|
size_t &shiftIncrementRtn,
|
||||||
bool &lock)
|
bool &phaseReset)
|
||||||
{
|
{
|
||||||
// cerr << "calculateIncrements" << endl;
|
// cerr << "calculateIncrements" << endl;
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
|||||||
|
|
||||||
phaseIncrementRtn = m_increment;
|
phaseIncrementRtn = m_increment;
|
||||||
shiftIncrementRtn = m_increment;
|
shiftIncrementRtn = m_increment;
|
||||||
lock = false;
|
phaseReset = false;
|
||||||
|
|
||||||
if (m_channels == 0) return;
|
if (m_channels == 0) return;
|
||||||
|
|
||||||
@@ -328,18 +328,18 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float df = m_lockAudioCurve->process(cd.fltbuf, m_increment);
|
float df = m_phaseResetAudioCurve->process(cd.fltbuf, m_increment);
|
||||||
|
|
||||||
int incr = m_stretchCalculator->calculateSingle
|
int incr = m_stretchCalculator->calculateSingle
|
||||||
(getEffectiveRatio(),
|
(getEffectiveRatio(),
|
||||||
m_inputDuration, //!!! no, totally wrong... fortunately it doesn't matter atm
|
m_inputDuration, //!!! no, totally wrong... fortunately it doesn't matter atm
|
||||||
df);
|
df);
|
||||||
|
|
||||||
m_lastProcessLockDf.write(&df, 1);
|
m_lastProcessPhaseResetDf.write(&df, 1);
|
||||||
m_lastProcessOutputIncrements.write(&incr, 1);
|
m_lastProcessOutputIncrements.write(&incr, 1);
|
||||||
|
|
||||||
if (incr < 0) {
|
if (incr < 0) {
|
||||||
lock = true;
|
phaseReset = true;
|
||||||
incr = -incr;
|
incr = -incr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,9 +352,9 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn,
|
|||||||
// This implies we should use this increment for the shift
|
// This implies we should use this increment for the shift
|
||||||
// increment, and make the following phase increment the same as
|
// increment, and make the following phase increment the same as
|
||||||
// it. This means in RT mode we'll be one chunk later with our
|
// it. This means in RT mode we'll be one chunk later with our
|
||||||
// phase lock than we would be in non-RT mode. The sensitivity of
|
// phase reset than we would be in non-RT mode. The sensitivity
|
||||||
// the broadband onset detector may mean that this isn't a problem
|
// of the broadband onset detector may mean that this isn't a
|
||||||
// -- test it and see.
|
// problem -- test it and see.
|
||||||
|
|
||||||
shiftIncrementRtn = incr;
|
shiftIncrementRtn = incr;
|
||||||
|
|
||||||
@@ -371,12 +371,12 @@ bool
|
|||||||
RubberBandStretcher::Impl::getIncrements(size_t channel,
|
RubberBandStretcher::Impl::getIncrements(size_t channel,
|
||||||
size_t &phaseIncrementRtn,
|
size_t &phaseIncrementRtn,
|
||||||
size_t &shiftIncrementRtn,
|
size_t &shiftIncrementRtn,
|
||||||
bool &lock)
|
bool &phaseReset)
|
||||||
{
|
{
|
||||||
if (channel >= m_channels) {
|
if (channel >= m_channels) {
|
||||||
phaseIncrementRtn = m_increment;
|
phaseIncrementRtn = m_increment;
|
||||||
shiftIncrementRtn = m_increment;
|
shiftIncrementRtn = m_increment;
|
||||||
lock = false;
|
phaseReset = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,10 +387,10 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
|||||||
// writing the chunk. The shift increment for one chunk is the
|
// writing the chunk. The shift increment for one chunk is the
|
||||||
// same as the phase increment for the following chunk.
|
// same as the phase increment for the following chunk.
|
||||||
|
|
||||||
// When an onset occurs for which we need to lock phases, the
|
// When an onset occurs for which we need to reset phases, the
|
||||||
// increment given will be negative.
|
// increment given will be negative.
|
||||||
|
|
||||||
// When we lock phases, the previous shift increment (and so
|
// When we reset phases, the previous shift increment (and so
|
||||||
// current phase increments) must have been m_increment to ensure
|
// current phase increments) must have been m_increment to ensure
|
||||||
// consistency.
|
// consistency.
|
||||||
|
|
||||||
@@ -406,7 +406,7 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
|||||||
if (m_outputIncrements.size() == 0) {
|
if (m_outputIncrements.size() == 0) {
|
||||||
phaseIncrementRtn = m_increment;
|
phaseIncrementRtn = m_increment;
|
||||||
shiftIncrementRtn = m_increment;
|
shiftIncrementRtn = m_increment;
|
||||||
lock = false;
|
phaseReset = false;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
cd.chunkCount = m_outputIncrements.size()-1;
|
cd.chunkCount = m_outputIncrements.size()-1;
|
||||||
@@ -423,7 +423,7 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
|||||||
|
|
||||||
if (phaseIncrement < 0) {
|
if (phaseIncrement < 0) {
|
||||||
phaseIncrement = -phaseIncrement;
|
phaseIncrement = -phaseIncrement;
|
||||||
lock = true;
|
phaseReset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shiftIncrement < 0) {
|
if (shiftIncrement < 0) {
|
||||||
@@ -437,7 +437,7 @@ RubberBandStretcher::Impl::getIncrements(size_t channel,
|
|||||||
|
|
||||||
phaseIncrementRtn = phaseIncrement;
|
phaseIncrementRtn = phaseIncrement;
|
||||||
shiftIncrementRtn = shiftIncrement;
|
shiftIncrementRtn = shiftIncrement;
|
||||||
if (cd.chunkCount == 0) lock = true; // don't mess with the first chunk
|
if (cd.chunkCount == 0) phaseReset = true; // don't mess with the first chunk
|
||||||
return gotData;
|
return gotData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,12 +465,12 @@ double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; }
|
|||||||
|
|
||||||
void
|
void
|
||||||
RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement,
|
RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement,
|
||||||
bool lock)
|
bool phaseReset)
|
||||||
{
|
{
|
||||||
ChannelData &cd = *m_channelData[channel];
|
ChannelData &cd = *m_channelData[channel];
|
||||||
|
|
||||||
if (lock && m_debugLevel > 1) {
|
if (phaseReset && m_debugLevel > 1) {
|
||||||
cerr << "lock: leaving phases unmodified" << endl;
|
cerr << "phase reset: leaving phases unmodified" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t count = m_windowSize/2;
|
size_t count = m_windowSize/2;
|
||||||
@@ -585,19 +585,19 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement,
|
|||||||
pp = cd.freqPeak[i-1];
|
pp = cd.freqPeak[i-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lockThis = lock;
|
bool resetThis = phaseReset;
|
||||||
|
|
||||||
if (!(m_options & OptionTransientsSmooth) &&
|
if (!(m_options & OptionTransientsSmooth) &&
|
||||||
!(m_options & OptionTransientsCrisp)) {
|
!(m_options & OptionTransientsCrisp)) {
|
||||||
// must be OptionTransientsMixed
|
// must be OptionTransientsMixed
|
||||||
size_t low = lrint((150 * m_windowSize) / rate);
|
size_t low = lrint((150 * m_windowSize) / rate);
|
||||||
size_t high = lrint((1000 * m_windowSize) / rate);
|
size_t high = lrint((1000 * m_windowSize) / rate);
|
||||||
if (lockThis) {
|
if (resetThis) {
|
||||||
if (i > low && i < high) lockThis = false;
|
if (i > low && i < high) resetThis = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lockThis) {
|
if (!resetThis) {
|
||||||
|
|
||||||
if (i == 0 || p != pp) {
|
if (i == 0 || p != pp) {
|
||||||
|
|
||||||
|
|||||||
@@ -35,17 +35,20 @@ public:
|
|||||||
|
|
||||||
bool m_realtime;
|
bool m_realtime;
|
||||||
bool m_elasticTiming;
|
bool m_elasticTiming;
|
||||||
bool m_crispTransients;
|
int m_transientMode;
|
||||||
|
bool m_phaseIndependent;
|
||||||
bool m_threadingAllowed;
|
bool m_threadingAllowed;
|
||||||
|
int m_windowLength;
|
||||||
|
|
||||||
RubberBand::RubberBandStretcher *m_stretcher;
|
RubberBand::RubberBandStretcher *m_stretcher;
|
||||||
|
|
||||||
int m_incrementsOutput;
|
int m_incrementsOutput;
|
||||||
int m_aggregateIncrementsOutput;
|
int m_aggregateIncrementsOutput;
|
||||||
int m_divergenceOutput;
|
int m_divergenceOutput;
|
||||||
int m_lockDfOutput;
|
int m_phaseResetDfOutput;
|
||||||
int m_smoothedLockDfOutput;
|
int m_smoothedPhaseResetDfOutput;
|
||||||
int m_lockPointsOutput;
|
int m_phaseResetPointsOutput;
|
||||||
|
int m_timeSyncPointsOutput;
|
||||||
|
|
||||||
size_t m_counter;
|
size_t m_counter;
|
||||||
size_t m_accumulatedIncrement;
|
size_t m_accumulatedIncrement;
|
||||||
@@ -62,9 +65,9 @@ public:
|
|||||||
|
|
||||||
FeatureSet createFeatures(size_t inputIncrement,
|
FeatureSet createFeatures(size_t inputIncrement,
|
||||||
std::vector<int> &outputIncrements,
|
std::vector<int> &outputIncrements,
|
||||||
std::vector<float> &lockDf,
|
std::vector<float> &phaseResetDf,
|
||||||
std::vector<int> &exactPoints,
|
std::vector<int> &exactPoints,
|
||||||
std::vector<float> &smoothedDF,
|
std::vector<float> &smoothedDf,
|
||||||
size_t baseCount,
|
size_t baseCount,
|
||||||
bool includeFinal);
|
bool includeFinal);
|
||||||
};
|
};
|
||||||
@@ -75,12 +78,14 @@ RubberBandVampPlugin::RubberBandVampPlugin(float inputSampleRate) :
|
|||||||
{
|
{
|
||||||
m_d = new Impl();
|
m_d = new Impl();
|
||||||
m_d->m_stepSize = 0;
|
m_d->m_stepSize = 0;
|
||||||
m_d->m_timeRatio = 1.0;
|
m_d->m_timeRatio = 1.f;
|
||||||
m_d->m_pitchRatio = 1.0;
|
m_d->m_pitchRatio = 1.f;
|
||||||
m_d->m_realtime = false;
|
m_d->m_realtime = false;
|
||||||
m_d->m_elasticTiming = true;
|
m_d->m_elasticTiming = true;
|
||||||
m_d->m_crispTransients = true;
|
m_d->m_transientMode = 0;
|
||||||
|
m_d->m_phaseIndependent = false;
|
||||||
m_d->m_threadingAllowed = true;
|
m_d->m_threadingAllowed = true;
|
||||||
|
m_d->m_windowLength = 0;
|
||||||
m_d->m_stretcher = 0;
|
m_d->m_stretcher = 0;
|
||||||
m_d->m_sampleRate = lrintf(m_inputSampleRate);
|
m_d->m_sampleRate = lrintf(m_inputSampleRate);
|
||||||
}
|
}
|
||||||
@@ -140,11 +145,11 @@ RubberBandVampPlugin::getOutputDescriptors() const
|
|||||||
OutputDescriptor d;
|
OutputDescriptor d;
|
||||||
d.identifier = "increments";
|
d.identifier = "increments";
|
||||||
d.name = "Output Increments";
|
d.name = "Output Increments";
|
||||||
d.description = ""; //!!!
|
d.description = "Output time increment for each input step";
|
||||||
d.unit = "samples";
|
d.unit = "samples";
|
||||||
d.hasFixedBinCount = true;
|
d.hasFixedBinCount = true;
|
||||||
d.binCount = 1;
|
d.binCount = 1;
|
||||||
d.hasKnownExtents = false; //!!!
|
d.hasKnownExtents = false;
|
||||||
d.isQuantized = true;
|
d.isQuantized = true;
|
||||||
d.quantizeStep = 1.0;
|
d.quantizeStep = 1.0;
|
||||||
d.sampleType = OutputDescriptor::VariableSampleRate;
|
d.sampleType = OutputDescriptor::VariableSampleRate;
|
||||||
@@ -154,44 +159,56 @@ RubberBandVampPlugin::getOutputDescriptors() const
|
|||||||
|
|
||||||
d.identifier = "aggregate_increments";
|
d.identifier = "aggregate_increments";
|
||||||
d.name = "Accumulated Output Increments";
|
d.name = "Accumulated Output Increments";
|
||||||
d.description = ""; //!!!
|
d.description = "Accumulated output time increments";
|
||||||
d.sampleRate = 0;
|
d.sampleRate = 0;
|
||||||
m_d->m_aggregateIncrementsOutput = list.size();
|
m_d->m_aggregateIncrementsOutput = list.size();
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
d.identifier = "divergence";
|
d.identifier = "divergence";
|
||||||
d.name = "Divergence from Linear";
|
d.name = "Divergence from Linear";
|
||||||
d.description = ""; //!!!
|
d.description = "Difference between actual output time and the output time for a theoretical linear stretch";
|
||||||
d.isQuantized = false;
|
d.isQuantized = false;
|
||||||
d.sampleRate = 0;
|
d.sampleRate = 0;
|
||||||
m_d->m_divergenceOutput = list.size();
|
m_d->m_divergenceOutput = list.size();
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
d.identifier = "lockdf";
|
d.identifier = "phaseresetdf";
|
||||||
d.name = "Lock Point Detection Function";
|
d.name = "Phase Reset Detection Function";
|
||||||
d.description = ""; //!!!
|
d.description = "Curve whose peaks are used to identify transients for phase reset points";
|
||||||
d.unit = "";
|
d.unit = "";
|
||||||
d.sampleRate = rate;
|
d.sampleRate = rate;
|
||||||
m_d->m_lockDfOutput = list.size();
|
m_d->m_phaseResetDfOutput = list.size();
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
d.identifier = "smoothedlockdf";
|
d.identifier = "smoothedphaseresetdf";
|
||||||
d.name = "Smoothed Lock Point Detection Function";
|
d.name = "Smoothed Phase Reset Detection Function";
|
||||||
d.description = ""; //!!!
|
d.description = "Phase reset curve smoothed for peak picking";
|
||||||
d.unit = "";
|
d.unit = "";
|
||||||
m_d->m_smoothedLockDfOutput = list.size();
|
m_d->m_smoothedPhaseResetDfOutput = list.size();
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
d.identifier = "lockpoints";
|
d.identifier = "phaseresetpoints";
|
||||||
d.name = "Phase Lock Points";
|
d.name = "Phase Reset Points";
|
||||||
d.description = ""; //!!!
|
d.description = "Points estimated as transients at which phase reset occurs";
|
||||||
d.unit = "";
|
d.unit = "";
|
||||||
d.hasFixedBinCount = true;
|
d.hasFixedBinCount = true;
|
||||||
d.binCount = 0;
|
d.binCount = 0;
|
||||||
d.hasKnownExtents = false;
|
d.hasKnownExtents = false;
|
||||||
d.isQuantized = false;
|
d.isQuantized = false;
|
||||||
d.sampleRate = 0;
|
d.sampleRate = 0;
|
||||||
m_d->m_lockPointsOutput = list.size();
|
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);
|
list.push_back(d);
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
@@ -204,22 +221,22 @@ RubberBandVampPlugin::getParameterDescriptors() const
|
|||||||
|
|
||||||
ParameterDescriptor d;
|
ParameterDescriptor d;
|
||||||
d.identifier = "timeratio";
|
d.identifier = "timeratio";
|
||||||
d.name = "Timestretch Ratio";
|
d.name = "Time Ratio";
|
||||||
d.description = ""; //!!!
|
d.description = "Ratio to modify overall duration by";
|
||||||
d.unit = "";
|
d.unit = "%";
|
||||||
d.minValue = 0.0000001;
|
d.minValue = 1;
|
||||||
d.maxValue = 1000;
|
d.maxValue = 500;
|
||||||
d.defaultValue = 1.0;
|
d.defaultValue = 100;
|
||||||
d.isQuantized = false;
|
d.isQuantized = false;
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
d.identifier = "pitchratio";
|
d.identifier = "pitchratio";
|
||||||
d.name = "Pitch Scaling Ratio";
|
d.name = "Pitch Scale Ratio";
|
||||||
d.description = ""; //!!!
|
d.description = "Frequency ratio to modify pitch by";
|
||||||
d.unit = "";
|
d.unit = "%";
|
||||||
d.minValue = 0.0000001;
|
d.minValue = 1;
|
||||||
d.maxValue = 1000;
|
d.maxValue = 500;
|
||||||
d.defaultValue = 1.0;
|
d.defaultValue = 100;
|
||||||
d.isQuantized = false;
|
d.isQuantized = false;
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
@@ -256,13 +273,43 @@ RubberBandVampPlugin::getParameterDescriptors() const
|
|||||||
d.description = ""; //!!!
|
d.description = ""; //!!!
|
||||||
d.unit = "";
|
d.unit = "";
|
||||||
d.minValue = 0;
|
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.maxValue = 1;
|
||||||
d.defaultValue = 0;
|
d.defaultValue = 0;
|
||||||
d.isQuantized = true;
|
d.isQuantized = true;
|
||||||
d.quantizeStep = 1;
|
d.quantizeStep = 1;
|
||||||
d.valueNames.clear();
|
d.valueNames.clear();
|
||||||
d.valueNames.push_back("Crisp");
|
d.valueNames.push_back("Peak Locked");
|
||||||
d.valueNames.push_back("Soft");
|
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);
|
list.push_back(d);
|
||||||
|
|
||||||
d.identifier = "threadingmode";
|
d.identifier = "threadingmode";
|
||||||
@@ -275,7 +322,7 @@ RubberBandVampPlugin::getParameterDescriptors() const
|
|||||||
d.isQuantized = true;
|
d.isQuantized = true;
|
||||||
d.quantizeStep = 1;
|
d.quantizeStep = 1;
|
||||||
d.valueNames.clear();
|
d.valueNames.clear();
|
||||||
d.valueNames.push_back("Enabled");
|
d.valueNames.push_back("Automatic");
|
||||||
d.valueNames.push_back("Disabled");
|
d.valueNames.push_back("Disabled");
|
||||||
list.push_back(d);
|
list.push_back(d);
|
||||||
|
|
||||||
@@ -285,12 +332,14 @@ RubberBandVampPlugin::getParameterDescriptors() const
|
|||||||
float
|
float
|
||||||
RubberBandVampPlugin::getParameter(std::string id) const
|
RubberBandVampPlugin::getParameter(std::string id) const
|
||||||
{
|
{
|
||||||
if (id == "timeratio") return m_d->m_timeRatio;
|
if (id == "timeratio") return m_d->m_timeRatio * 100.f;
|
||||||
if (id == "pitchratio") return m_d->m_pitchRatio;
|
if (id == "pitchratio") return m_d->m_pitchRatio * 100.f;
|
||||||
if (id == "mode") return m_d->m_realtime ? 1 : 0;
|
if (id == "mode") return m_d->m_realtime ? 1 : 0;
|
||||||
if (id == "stretchtype") return m_d->m_elasticTiming ? 0 : 1;
|
if (id == "stretchtype") return m_d->m_elasticTiming ? 0 : 1;
|
||||||
if (id == "transientmode") return m_d->m_crispTransients ? 0 : 1;
|
if (id == "transientmode") return m_d->m_transientMode;
|
||||||
|
if (id == "phasemode") return m_d->m_phaseIndependent ? 1 : 0;
|
||||||
if (id == "threadingmode") return m_d->m_threadingAllowed ? 0 : 1;
|
if (id == "threadingmode") return m_d->m_threadingAllowed ? 0 : 1;
|
||||||
|
if (id == "windowmode") return m_d->m_windowLength;
|
||||||
return 0.f;
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,15 +347,17 @@ void
|
|||||||
RubberBandVampPlugin::setParameter(std::string id, float value)
|
RubberBandVampPlugin::setParameter(std::string id, float value)
|
||||||
{
|
{
|
||||||
if (id == "timeratio") {
|
if (id == "timeratio") {
|
||||||
m_d->m_timeRatio = value;
|
m_d->m_timeRatio = value / 100;
|
||||||
} else if (id == "pitchratio") {
|
} else if (id == "pitchratio") {
|
||||||
m_d->m_pitchRatio = value;
|
m_d->m_pitchRatio = value / 100;
|
||||||
} else {
|
} else {
|
||||||
bool set = (value > 0.5);
|
bool set = (value > 0.5);
|
||||||
if (id == "mode") m_d->m_realtime = set;
|
if (id == "mode") m_d->m_realtime = set;
|
||||||
else if (id == "stretchtype") m_d->m_elasticTiming = !set;
|
else if (id == "stretchtype") m_d->m_elasticTiming = !set;
|
||||||
else if (id == "transientmode") m_d->m_crispTransients = !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 == "threadingmode") m_d->m_threadingAllowed = !set;
|
else if (id == "threadingmode") m_d->m_threadingAllowed = !set;
|
||||||
|
else if (id == "windowmode") m_d->m_windowLength = int(value + 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,14 +380,26 @@ RubberBandVampPlugin::initialise(size_t channels, size_t stepSize, size_t blockS
|
|||||||
options |= RubberBand::RubberBandStretcher::OptionStretchElastic;
|
options |= RubberBand::RubberBandStretcher::OptionStretchElastic;
|
||||||
else options |= RubberBand::RubberBandStretcher::OptionStretchPrecise;
|
else options |= RubberBand::RubberBandStretcher::OptionStretchPrecise;
|
||||||
|
|
||||||
if (m_d->m_crispTransients)
|
if (m_d->m_transientMode == 0)
|
||||||
options |= RubberBand::RubberBandStretcher::OptionTransientsCrisp;
|
options |= RubberBand::RubberBandStretcher::OptionTransientsMixed;
|
||||||
else options |= RubberBand::RubberBandStretcher::OptionTransientsSmooth;
|
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::OptionPhasePeakLocked;
|
||||||
|
|
||||||
if (m_d->m_threadingAllowed)
|
if (m_d->m_threadingAllowed)
|
||||||
options |= RubberBand::RubberBandStretcher::OptionThreadingAuto;
|
options |= RubberBand::RubberBandStretcher::OptionThreadingAuto;
|
||||||
else options |= RubberBand::RubberBandStretcher::OptionThreadingNone;
|
else options |= RubberBand::RubberBandStretcher::OptionThreadingNone;
|
||||||
|
|
||||||
|
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;
|
delete m_d->m_stretcher;
|
||||||
m_d->m_stretcher = new RubberBand::RubberBandStretcher
|
m_d->m_stretcher = new RubberBand::RubberBandStretcher
|
||||||
(m_d->m_sampleRate, channels, options);
|
(m_d->m_sampleRate, channels, options);
|
||||||
@@ -409,12 +472,12 @@ RubberBandVampPlugin::Impl::getRemainingFeaturesOffline()
|
|||||||
|
|
||||||
size_t inputIncrement = m_stretcher->getInputIncrement();
|
size_t inputIncrement = m_stretcher->getInputIncrement();
|
||||||
std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
|
std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
|
||||||
std::vector<float> lockDf = m_stretcher->getLockCurve();
|
std::vector<float> phaseResetDf = m_stretcher->getPhaseResetCurve();
|
||||||
std::vector<int> peaks = m_stretcher->getExactTimePoints();
|
std::vector<int> peaks = m_stretcher->getExactTimePoints();
|
||||||
std::vector<float> smoothedDf = sc.smoothDF(lockDf);
|
std::vector<float> smoothedDf = sc.smoothDF(phaseResetDf);
|
||||||
|
|
||||||
FeatureSet features = createFeatures
|
FeatureSet features = createFeatures
|
||||||
(inputIncrement, outputIncrements, lockDf, peaks, smoothedDf,
|
(inputIncrement, outputIncrements, phaseResetDf, peaks, smoothedDf,
|
||||||
0, true);
|
0, true);
|
||||||
|
|
||||||
return features;
|
return features;
|
||||||
@@ -439,11 +502,11 @@ RubberBandVampPlugin::Impl::processRealTime(const float *const *inputBuffers,
|
|||||||
|
|
||||||
size_t inputIncrement = m_stretcher->getInputIncrement();
|
size_t inputIncrement = m_stretcher->getInputIncrement();
|
||||||
std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
|
std::vector<int> outputIncrements = m_stretcher->getOutputIncrements();
|
||||||
std::vector<float> lockDf = m_stretcher->getLockCurve();
|
std::vector<float> phaseResetDf = m_stretcher->getPhaseResetCurve();
|
||||||
std::vector<float> smoothedDf; // not meaningful in RT mode
|
std::vector<float> smoothedDf; // not meaningful in RT mode
|
||||||
std::vector<int> dummyPoints;
|
std::vector<int> dummyPoints;
|
||||||
FeatureSet features = createFeatures
|
FeatureSet features = createFeatures
|
||||||
(inputIncrement, outputIncrements, lockDf, dummyPoints, smoothedDf,
|
(inputIncrement, outputIncrements, phaseResetDf, dummyPoints, smoothedDf,
|
||||||
m_counter, false);
|
m_counter, false);
|
||||||
m_counter += outputIncrements.size();
|
m_counter += outputIncrements.size();
|
||||||
|
|
||||||
@@ -459,7 +522,7 @@ RubberBandVampPlugin::Impl::getRemainingFeaturesRealTime()
|
|||||||
RubberBandVampPlugin::FeatureSet
|
RubberBandVampPlugin::FeatureSet
|
||||||
RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement,
|
RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement,
|
||||||
std::vector<int> &outputIncrements,
|
std::vector<int> &outputIncrements,
|
||||||
std::vector<float> &lockDf,
|
std::vector<float> &phaseResetDf,
|
||||||
std::vector<int> &exactPoints,
|
std::vector<int> &exactPoints,
|
||||||
std::vector<float> &smoothedDf,
|
std::vector<float> &smoothedDf,
|
||||||
size_t baseCount,
|
size_t baseCount,
|
||||||
@@ -482,16 +545,16 @@ RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement,
|
|||||||
size_t frame = (baseCount + i) * inputIncrement;
|
size_t frame = (baseCount + i) * inputIncrement;
|
||||||
|
|
||||||
int oi = outputIncrements[i];
|
int oi = outputIncrements[i];
|
||||||
bool hardLock = false;
|
bool hard = false;
|
||||||
bool softLock = false;
|
bool soft = false;
|
||||||
|
|
||||||
if (oi < 0) {
|
if (oi < 0) {
|
||||||
oi = -oi;
|
oi = -oi;
|
||||||
hardLock = true;
|
hard = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (epi < exactPoints.size() && int(i) == exactPoints[epi]) {
|
if (epi < exactPoints.size() && int(i) == exactPoints[epi]) {
|
||||||
softLock = true;
|
soft = true;
|
||||||
++epi;
|
++epi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,28 +591,30 @@ RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement,
|
|||||||
|
|
||||||
char buf[30];
|
char buf[30];
|
||||||
|
|
||||||
if (i < lockDf.size()) {
|
if (i < phaseResetDf.size()) {
|
||||||
feature.values.clear();
|
feature.values.clear();
|
||||||
feature.values.push_back(lockDf[i]);
|
feature.values.push_back(phaseResetDf[i]);
|
||||||
sprintf(buf, "%d", baseCount + i);
|
sprintf(buf, "%d", baseCount + i);
|
||||||
feature.label = buf;
|
feature.label = buf;
|
||||||
features[m_lockDfOutput].push_back(feature);
|
features[m_phaseResetDfOutput].push_back(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < smoothedDf.size()) {
|
if (i < smoothedDf.size()) {
|
||||||
feature.values.clear();
|
feature.values.clear();
|
||||||
feature.values.push_back(smoothedDf[i]);
|
feature.values.push_back(smoothedDf[i]);
|
||||||
features[m_smoothedLockDfOutput].push_back(feature);
|
features[m_smoothedPhaseResetDfOutput].push_back(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hardLock) {
|
if (hard) {
|
||||||
feature.values.clear();
|
feature.values.clear();
|
||||||
feature.label = "Phase Reset";
|
feature.label = "Phase Reset";
|
||||||
features[m_lockPointsOutput].push_back(feature);
|
features[m_phaseResetPointsOutput].push_back(feature);
|
||||||
} else if (softLock) {
|
}
|
||||||
|
|
||||||
|
if (hard || soft) {
|
||||||
feature.values.clear();
|
feature.values.clear();
|
||||||
feature.label = "Time Sync";
|
feature.label = "Time Sync";
|
||||||
features[m_lockPointsOutput].push_back(feature);
|
features[m_timeSyncPointsOutput].push_back(feature);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user