diff --git a/rubberband/RubberBandStretcher.h b/rubberband/RubberBandStretcher.h index 789f523..af42174 100644 --- a/rubberband/RubberBandStretcher.h +++ b/rubberband/RubberBandStretcher.h @@ -89,7 +89,7 @@ public: virtual size_t getInputIncrement() const; virtual std::vector getOutputIncrements() const; //!!! document particular meaning in RT mode - virtual std::vector getLockCurve() const; //!!! document particular meaning in RT mode + virtual std::vector getPhaseResetCurve() const; //!!! document particular meaning in RT mode virtual std::vector getExactTimePoints() const; //!!! meaningless in RT mode virtual size_t getChannelCount() const; diff --git a/src/RubberBandStretcher.cpp b/src/RubberBandStretcher.cpp index 6258326..8d0922a 100644 --- a/src/RubberBandStretcher.cpp +++ b/src/RubberBandStretcher.cpp @@ -150,9 +150,9 @@ RubberBandStretcher::getOutputIncrements() const } std::vector -RubberBandStretcher::getLockCurve() const +RubberBandStretcher::getPhaseResetCurve() const { - return m_d->getLockCurve(); + return m_d->getPhaseResetCurve(); } std::vector diff --git a/src/StretchCalculator.cpp b/src/StretchCalculator.cpp index f2baf52..6499c16 100644 --- a/src/StretchCalculator.cpp +++ b/src/StretchCalculator.cpp @@ -44,7 +44,7 @@ StretchCalculator::~StretchCalculator() std::vector StretchCalculator::calculate(double ratio, size_t inputDuration, - const std::vector &lockDf, + const std::vector &phaseResetDf, const std::vector &stretchDf) { // 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 // 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 // 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 // start with a high sensitivity and reduce it). // 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 // short time frame (e.g. 30-50ms). @@ -79,11 +79,11 @@ StretchCalculator::calculate(double ratio, size_t inputDuration, // 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 &peaks = m_lastPeaks; - size_t totalCount = lockDf.size(); + size_t totalCount = phaseResetDf.size(); std::vector increments; @@ -96,11 +96,11 @@ StretchCalculator::calculate(double ratio, size_t inputDuration, } //!!! round down? - outputDuration = lrint((lockDf.size() * m_increment) * ratio); + outputDuration = lrint((phaseResetDf.size() * m_increment) * ratio); if (m_debugLevel > 0) { 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; @@ -329,10 +329,10 @@ StretchCalculator::findPeaks(const std::vector &rawDf) } //!!! 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 - //shortly after hard ones, otherwise either locking on them, or at - //least making sure they fall at the correct sample time + //shortly after hard ones, otherwise either resetting on them, or + //at least making sure they fall at the correct sample time // int mediansize = lrint(ceil(double(m_sampleRate) / // (4 * double(m_increment)))); // 0.25 sec ish @@ -444,11 +444,11 @@ StretchCalculator::findPeaks(const std::vector &rawDf) //a very rapid rise in detection function prior to the //peak (the first value after the rise is not necessarily //the peak itself, but it is probably where we should - //locate the lock). For hard peaks we need to lock in - //time to preserve the shape of the transient (unless some - //option is set to soft mode), for soft peaks we just want - //to avoid poor timing positioning so we build up to the - //lock at the exact peak moment. + //locate the phase reset). For hard peaks we need to + //reset in time to preserve the shape of the transient + //(unless some option is set to soft mode), for soft peaks + //we just want to avoid poor timing positioning so we + //build up to the reset at the exact peak moment. // size_t peak = i + maxindex - mediansize; size_t peak = i + maxindex - middle; @@ -563,7 +563,7 @@ StretchCalculator::smoothDF(const std::vector &df) std::vector StretchCalculator::distributeRegion(const std::vector &dfIn, - size_t duration, float ratio, bool lock) + size_t duration, float ratio, bool phaseReset) { std::vector df(dfIn); std::vector increments; @@ -706,7 +706,7 @@ StretchCalculator::distributeRegion(const std::vector &dfIn, if (displacement < 0) displacement -= adj; else displacement += adj; - if (i == 0 && lock) { + if (i == 0 && phaseReset) { if (df.size() == 1) { increments.push_back(duration); totalIncrement += duration; diff --git a/src/StretchCalculator.h b/src/StretchCalculator.h index 161ce2b..4641b74 100644 --- a/src/StretchCalculator.h +++ b/src/StretchCalculator.h @@ -66,7 +66,7 @@ protected: std::vector distributeRegion(const std::vector ®ionCurve, size_t outputDuration, float ratio, - bool lock); + bool phaseReset); void calculateDisplacements(const std::vector &df, float &maxDf, diff --git a/src/StretcherImpl.cpp b/src/StretcherImpl.cpp index b20c762..de538c0 100644 --- a/src/StretcherImpl.cpp +++ b/src/StretcherImpl.cpp @@ -62,8 +62,8 @@ RubberBandStretcher::Impl::Impl(RubberBandStretcher *stretcher, m_studyFFT(0), m_inputDuration(0), m_lastProcessOutputIncrements(16), - m_lastProcessLockDf(16), - m_lockAudioCurve(0), + m_lastProcessPhaseResetDf(16), + m_phaseResetAudioCurve(0), m_stretchAudioCurve(0), m_stretchCalculator(0), m_freq0(600), @@ -134,7 +134,7 @@ RubberBandStretcher::Impl::~Impl() delete m_channelData[c]; } - delete m_lockAudioCurve; + delete m_phaseResetAudioCurve; delete m_stretchAudioCurve; delete m_stretchCalculator; delete m_studyFFT; @@ -157,7 +157,7 @@ RubberBandStretcher::Impl::reset() m_channelData[c] = new ChannelData(m_windowSize, m_outbufSize); } m_mode = JustCreated; - if (m_lockAudioCurve) m_lockAudioCurve->reset(); + if (m_phaseResetAudioCurve) m_phaseResetAudioCurve->reset(); if (m_stretchAudioCurve) m_stretchAudioCurve->reset(); m_inputDuration = 0; @@ -478,11 +478,11 @@ RubberBandStretcher::Impl::configure() } } - delete m_lockAudioCurve; - m_lockAudioCurve = new PercussiveAudioCurve(m_stretcher->m_sampleRate, - m_windowSize); + delete m_phaseResetAudioCurve; + m_phaseResetAudioCurve = new PercussiveAudioCurve(m_stretcher->m_sampleRate, + m_windowSize); - // stretchAudioCurve unused in RT mode; lockAudioCurve and + // stretchAudioCurve unused in RT mode; phaseResetAudioCurve and // stretchCalculator however are used in all modes if (!m_realtime) { @@ -536,7 +536,7 @@ RubberBandStretcher::Impl::reconfigure() // stop and calculate the stretch curve so far, then reset // the df vectors calculateStretch(); - m_lockDf.clear(); + m_phaseResetDf.clear(); m_stretchDf.clear(); m_inputDuration = 0; } @@ -592,7 +592,7 @@ RubberBandStretcher::Impl::reconfigure() } 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); - float df = m_lockAudioCurve->process(cd.fltbuf, m_increment); - m_lockDf.push_back(df); + float df = m_phaseResetAudioCurve->process(cd.fltbuf, m_increment); + 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); m_stretchDf.push_back(df); @@ -756,14 +756,14 @@ RubberBandStretcher::Impl::getOutputIncrements() const } vector -RubberBandStretcher::Impl::getLockCurve() const +RubberBandStretcher::Impl::getPhaseResetCurve() const { if (!m_realtime) { - return m_lockDf; + return m_phaseResetDf; } else { vector df; - while (m_lastProcessLockDf.getReadSpace() > 0) { - df.push_back(m_lastProcessLockDf.readOne()); + while (m_lastProcessPhaseResetDf.getReadSpace() > 0) { + df.push_back(m_lastProcessPhaseResetDf.readOne()); } return df; } @@ -789,7 +789,7 @@ RubberBandStretcher::Impl::calculateStretch() std::vector increments = m_stretchCalculator->calculate (getEffectiveRatio(), m_inputDuration, - m_lockDf, + m_phaseResetDf, m_stretchDf); if (m_outputIncrements.empty()) m_outputIncrements = increments; diff --git a/src/StretcherImpl.h b/src/StretcherImpl.h index a95e9fd..c7ced29 100644 --- a/src/StretcherImpl.h +++ b/src/StretcherImpl.h @@ -70,7 +70,7 @@ public: } std::vector getOutputIncrements() const; - std::vector getLockCurve() const; + std::vector getPhaseResetCurve() const; std::vector getExactTimePoints() const; size_t getChannelCount() const { @@ -89,14 +89,14 @@ protected: bool processChunks(size_t channel); // returns "last" bool processOneChunk(); // across all channels, for real time use bool processChunkForChannel(size_t channel, size_t phaseIncrement, - size_t shiftIncrement, bool lock); + size_t shiftIncrement, bool phaseReset); bool testInbufReadSpace(size_t channel); void calculateIncrements(size_t &phaseIncrement, - size_t &shiftIncrement, bool &lock); + size_t &shiftIncrement, bool &phaseReset); bool getIncrements(size_t channel, size_t &phaseIncrement, - size_t &shiftIncrement, bool &lock); + size_t &shiftIncrement, bool &phaseReset); 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 writeChunk(size_t channel, size_t shiftIncrement, bool last); @@ -154,7 +154,7 @@ protected: size_t m_inputDuration; - std::vector m_lockDf; + std::vector m_phaseResetDf; std::vector m_stretchDf; class ChannelData; @@ -163,9 +163,9 @@ protected: std::vector m_outputIncrements; mutable RingBuffer m_lastProcessOutputIncrements; - mutable RingBuffer m_lastProcessLockDf; + mutable RingBuffer m_lastProcessPhaseResetDf; - AudioCurve *m_lockAudioCurve; + AudioCurve *m_phaseResetAudioCurve; AudioCurve *m_stretchAudioCurve; StretchCalculator *m_stretchCalculator; diff --git a/src/StretcherProcess.cpp b/src/StretcherProcess.cpp index 5543aa8..2afb9c0 100644 --- a/src/StretcherProcess.cpp +++ b/src/StretcherProcess.cpp @@ -89,11 +89,11 @@ RubberBandStretcher::Impl::processChunks(size_t c) analyseChunk(c); } - bool lock = false; + bool phaseReset = false; 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++; if (m_debugLevel > 2) { 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; - if (!getIncrements(0, phaseIncrement, shiftIncrement, lock)) { - calculateIncrements(phaseIncrement, shiftIncrement, lock); + if (!getIncrements(0, phaseIncrement, shiftIncrement, phaseReset)) { + calculateIncrements(phaseIncrement, shiftIncrement, phaseReset); } bool last = false; 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++; } @@ -187,15 +187,15 @@ bool RubberBandStretcher::Impl::processChunkForChannel(size_t c, size_t phaseIncrement, size_t shiftIncrement, - bool lock) + bool phaseReset) { // Process a single chunk on a single channel. This assumes // enough input data is available; caller must have tested this // using e.g. testInbufReadSpace first. Return true if this is // the last chunk on the channel. - if (lock && (m_debugLevel > 1)) { - cerr << "processChunkForChannel: lock found, incrs " + if (phaseReset && (m_debugLevel > 1)) { + cerr << "processChunkForChannel: phase reset found, incrs " << phaseIncrement << ":" << shiftIncrement << endl; } @@ -216,11 +216,11 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c, // We need to peek m_windowSize samples for processing, and // 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 if (m_debugLevel > 2) { - if (lock) { + if (phaseReset) { for (int i = 0; i < 10; ++i) { cd.accumulator[i] = ((drand48() * 2 - 1.0) > 0 ? 1 : -1); } @@ -277,7 +277,7 @@ RubberBandStretcher::Impl::processChunkForChannel(size_t c, void RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, size_t &shiftIncrementRtn, - bool &lock) + bool &phaseReset) { // cerr << "calculateIncrements" << endl; @@ -294,7 +294,7 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, phaseIncrementRtn = m_increment; shiftIncrementRtn = m_increment; - lock = false; + phaseReset = false; 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 (getEffectiveRatio(), m_inputDuration, //!!! no, totally wrong... fortunately it doesn't matter atm df); - m_lastProcessLockDf.write(&df, 1); + m_lastProcessPhaseResetDf.write(&df, 1); m_lastProcessOutputIncrements.write(&incr, 1); if (incr < 0) { - lock = true; + phaseReset = true; incr = -incr; } @@ -352,9 +352,9 @@ RubberBandStretcher::Impl::calculateIncrements(size_t &phaseIncrementRtn, // This implies we should use this increment for the shift // increment, and make the following phase increment the same as // 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 - // the broadband onset detector may mean that this isn't a problem - // -- test it and see. + // phase reset than we would be in non-RT mode. The sensitivity + // of the broadband onset detector may mean that this isn't a + // problem -- test it and see. shiftIncrementRtn = incr; @@ -371,12 +371,12 @@ bool RubberBandStretcher::Impl::getIncrements(size_t channel, size_t &phaseIncrementRtn, size_t &shiftIncrementRtn, - bool &lock) + bool &phaseReset) { if (channel >= m_channels) { phaseIncrementRtn = m_increment; shiftIncrementRtn = m_increment; - lock = false; + phaseReset = false; return false; } @@ -387,10 +387,10 @@ RubberBandStretcher::Impl::getIncrements(size_t channel, // writing the chunk. The shift increment for one chunk is the // 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. - // 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 // consistency. @@ -406,7 +406,7 @@ RubberBandStretcher::Impl::getIncrements(size_t channel, if (m_outputIncrements.size() == 0) { phaseIncrementRtn = m_increment; shiftIncrementRtn = m_increment; - lock = false; + phaseReset = false; return false; } else { cd.chunkCount = m_outputIncrements.size()-1; @@ -423,7 +423,7 @@ RubberBandStretcher::Impl::getIncrements(size_t channel, if (phaseIncrement < 0) { phaseIncrement = -phaseIncrement; - lock = true; + phaseReset = true; } if (shiftIncrement < 0) { @@ -437,7 +437,7 @@ RubberBandStretcher::Impl::getIncrements(size_t channel, phaseIncrementRtn = phaseIncrement; 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; } @@ -465,12 +465,12 @@ double princarg(double a) { return mod(a + M_PI, -2 * M_PI) + M_PI; } void RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, - bool lock) + bool phaseReset) { ChannelData &cd = *m_channelData[channel]; - if (lock && m_debugLevel > 1) { - cerr << "lock: leaving phases unmodified" << endl; + if (phaseReset && m_debugLevel > 1) { + cerr << "phase reset: leaving phases unmodified" << endl; } size_t count = m_windowSize/2; @@ -585,19 +585,19 @@ RubberBandStretcher::Impl::modifyChunk(size_t channel, size_t outputIncrement, pp = cd.freqPeak[i-1]; } - bool lockThis = lock; + bool resetThis = phaseReset; if (!(m_options & OptionTransientsSmooth) && !(m_options & OptionTransientsCrisp)) { // must be OptionTransientsMixed size_t low = lrint((150 * m_windowSize) / rate); size_t high = lrint((1000 * m_windowSize) / rate); - if (lockThis) { - if (i > low && i < high) lockThis = false; + if (resetThis) { + if (i > low && i < high) resetThis = false; } } - if (!lockThis) { + if (!resetThis) { if (i == 0 || p != pp) { diff --git a/src/vamp/RubberBandVampPlugin.cpp b/src/vamp/RubberBandVampPlugin.cpp index f30da89..b762a56 100644 --- a/src/vamp/RubberBandVampPlugin.cpp +++ b/src/vamp/RubberBandVampPlugin.cpp @@ -35,17 +35,20 @@ public: bool m_realtime; bool m_elasticTiming; - bool m_crispTransients; + int m_transientMode; + bool m_phaseIndependent; bool m_threadingAllowed; + int m_windowLength; RubberBand::RubberBandStretcher *m_stretcher; int m_incrementsOutput; int m_aggregateIncrementsOutput; int m_divergenceOutput; - int m_lockDfOutput; - int m_smoothedLockDfOutput; - int m_lockPointsOutput; + int m_phaseResetDfOutput; + int m_smoothedPhaseResetDfOutput; + int m_phaseResetPointsOutput; + int m_timeSyncPointsOutput; size_t m_counter; size_t m_accumulatedIncrement; @@ -62,9 +65,9 @@ public: FeatureSet createFeatures(size_t inputIncrement, std::vector &outputIncrements, - std::vector &lockDf, + std::vector &phaseResetDf, std::vector &exactPoints, - std::vector &smoothedDF, + std::vector &smoothedDf, size_t baseCount, bool includeFinal); }; @@ -75,12 +78,14 @@ RubberBandVampPlugin::RubberBandVampPlugin(float inputSampleRate) : { m_d = new Impl(); m_d->m_stepSize = 0; - m_d->m_timeRatio = 1.0; - m_d->m_pitchRatio = 1.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_crispTransients = true; + m_d->m_transientMode = 0; + m_d->m_phaseIndependent = false; m_d->m_threadingAllowed = true; + m_d->m_windowLength = 0; m_d->m_stretcher = 0; m_d->m_sampleRate = lrintf(m_inputSampleRate); } @@ -140,11 +145,11 @@ RubberBandVampPlugin::getOutputDescriptors() const OutputDescriptor d; d.identifier = "increments"; d.name = "Output Increments"; - d.description = ""; //!!! + d.description = "Output time increment for each input step"; d.unit = "samples"; d.hasFixedBinCount = true; d.binCount = 1; - d.hasKnownExtents = false; //!!! + d.hasKnownExtents = false; d.isQuantized = true; d.quantizeStep = 1.0; d.sampleType = OutputDescriptor::VariableSampleRate; @@ -154,44 +159,56 @@ RubberBandVampPlugin::getOutputDescriptors() const d.identifier = "aggregate_increments"; d.name = "Accumulated Output Increments"; - d.description = ""; //!!! + 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 = ""; //!!! + 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 = "lockdf"; - d.name = "Lock Point Detection Function"; - d.description = ""; //!!! + 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 = rate; - m_d->m_lockDfOutput = list.size(); + m_d->m_phaseResetDfOutput = list.size(); list.push_back(d); - d.identifier = "smoothedlockdf"; - d.name = "Smoothed Lock Point Detection Function"; - d.description = ""; //!!! + d.identifier = "smoothedphaseresetdf"; + d.name = "Smoothed Phase Reset Detection Function"; + d.description = "Phase reset curve smoothed for peak picking"; d.unit = ""; - m_d->m_smoothedLockDfOutput = list.size(); + m_d->m_smoothedPhaseResetDfOutput = list.size(); list.push_back(d); - d.identifier = "lockpoints"; - d.name = "Phase Lock Points"; - d.description = ""; //!!! + 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_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); return list; @@ -204,22 +221,22 @@ RubberBandVampPlugin::getParameterDescriptors() const ParameterDescriptor d; d.identifier = "timeratio"; - d.name = "Timestretch Ratio"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0.0000001; - d.maxValue = 1000; - d.defaultValue = 1.0; + 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 Scaling Ratio"; - d.description = ""; //!!! - d.unit = ""; - d.minValue = 0.0000001; - d.maxValue = 1000; - d.defaultValue = 1.0; + 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); @@ -256,13 +273,43 @@ RubberBandVampPlugin::getParameterDescriptors() const 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("Crisp"); - d.valueNames.push_back("Soft"); + 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); d.identifier = "threadingmode"; @@ -275,7 +322,7 @@ RubberBandVampPlugin::getParameterDescriptors() const d.isQuantized = true; d.quantizeStep = 1; d.valueNames.clear(); - d.valueNames.push_back("Enabled"); + d.valueNames.push_back("Automatic"); d.valueNames.push_back("Disabled"); list.push_back(d); @@ -285,12 +332,14 @@ RubberBandVampPlugin::getParameterDescriptors() const float RubberBandVampPlugin::getParameter(std::string id) const { - if (id == "timeratio") return m_d->m_timeRatio; - if (id == "pitchratio") return m_d->m_pitchRatio; + 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 : 0; 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 == "windowmode") return m_d->m_windowLength; return 0.f; } @@ -298,15 +347,17 @@ void RubberBandVampPlugin::setParameter(std::string id, float value) { if (id == "timeratio") { - m_d->m_timeRatio = value; + m_d->m_timeRatio = value / 100; } else if (id == "pitchratio") { - m_d->m_pitchRatio = value; + 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_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 == "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; else options |= RubberBand::RubberBandStretcher::OptionStretchPrecise; - if (m_d->m_crispTransients) - options |= RubberBand::RubberBandStretcher::OptionTransientsCrisp; - else options |= RubberBand::RubberBandStretcher::OptionTransientsSmooth; + 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::OptionPhasePeakLocked; if (m_d->m_threadingAllowed) options |= RubberBand::RubberBandStretcher::OptionThreadingAuto; 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; m_d->m_stretcher = new RubberBand::RubberBandStretcher (m_d->m_sampleRate, channels, options); @@ -409,12 +472,12 @@ RubberBandVampPlugin::Impl::getRemainingFeaturesOffline() size_t inputIncrement = m_stretcher->getInputIncrement(); std::vector outputIncrements = m_stretcher->getOutputIncrements(); - std::vector lockDf = m_stretcher->getLockCurve(); + std::vector phaseResetDf = m_stretcher->getPhaseResetCurve(); std::vector peaks = m_stretcher->getExactTimePoints(); - std::vector smoothedDf = sc.smoothDF(lockDf); + std::vector smoothedDf = sc.smoothDF(phaseResetDf); FeatureSet features = createFeatures - (inputIncrement, outputIncrements, lockDf, peaks, smoothedDf, + (inputIncrement, outputIncrements, phaseResetDf, peaks, smoothedDf, 0, true); return features; @@ -439,11 +502,11 @@ RubberBandVampPlugin::Impl::processRealTime(const float *const *inputBuffers, size_t inputIncrement = m_stretcher->getInputIncrement(); std::vector outputIncrements = m_stretcher->getOutputIncrements(); - std::vector lockDf = m_stretcher->getLockCurve(); + std::vector phaseResetDf = m_stretcher->getPhaseResetCurve(); std::vector smoothedDf; // not meaningful in RT mode std::vector dummyPoints; FeatureSet features = createFeatures - (inputIncrement, outputIncrements, lockDf, dummyPoints, smoothedDf, + (inputIncrement, outputIncrements, phaseResetDf, dummyPoints, smoothedDf, m_counter, false); m_counter += outputIncrements.size(); @@ -459,7 +522,7 @@ RubberBandVampPlugin::Impl::getRemainingFeaturesRealTime() RubberBandVampPlugin::FeatureSet RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement, std::vector &outputIncrements, - std::vector &lockDf, + std::vector &phaseResetDf, std::vector &exactPoints, std::vector &smoothedDf, size_t baseCount, @@ -482,16 +545,16 @@ RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement, size_t frame = (baseCount + i) * inputIncrement; int oi = outputIncrements[i]; - bool hardLock = false; - bool softLock = false; + bool hard = false; + bool soft = false; if (oi < 0) { oi = -oi; - hardLock = true; + hard = true; } if (epi < exactPoints.size() && int(i) == exactPoints[epi]) { - softLock = true; + soft = true; ++epi; } @@ -528,28 +591,30 @@ RubberBandVampPlugin::Impl::createFeatures(size_t inputIncrement, char buf[30]; - if (i < lockDf.size()) { + if (i < phaseResetDf.size()) { feature.values.clear(); - feature.values.push_back(lockDf[i]); + feature.values.push_back(phaseResetDf[i]); sprintf(buf, "%d", baseCount + i); feature.label = buf; - features[m_lockDfOutput].push_back(feature); + features[m_phaseResetDfOutput].push_back(feature); } if (i < smoothedDf.size()) { feature.values.clear(); 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.label = "Phase Reset"; - features[m_lockPointsOutput].push_back(feature); - } else if (softLock) { + features[m_phaseResetPointsOutput].push_back(feature); + } + + if (hard || soft) { feature.values.clear(); feature.label = "Time Sync"; - features[m_lockPointsOutput].push_back(feature); + features[m_timeSyncPointsOutput].push_back(feature); } }