diff --git a/meson.build b/meson.build index e184a75..f4b05f8 100644 --- a/meson.build +++ b/meson.build @@ -38,7 +38,6 @@ library_sources = [ 'src/faster/HighFrequencyAudioCurve.cpp', 'src/faster/SilentAudioCurve.cpp', 'src/faster/PercussiveAudioCurve.cpp', - 'src/faster/StretchCalculator.cpp', 'src/faster/StretcherChannelData.cpp', 'src/faster/StretcherImpl.cpp', 'src/faster/StretcherProcess.cpp', @@ -46,9 +45,9 @@ library_sources = [ 'src/common/Resampler.cpp', 'src/common/FFT.cpp', 'src/common/Allocators.cpp', + 'src/common/StretchCalculator.cpp', 'src/common/sysutils.cpp', 'src/common/Thread.cpp', - 'src/temporary.cpp', 'src/finer/R3StretcherImpl.cpp', ] diff --git a/src/RubberBandStretcher.cpp b/src/RubberBandStretcher.cpp index e6a3b01..4a6d130 100644 --- a/src/RubberBandStretcher.cpp +++ b/src/RubberBandStretcher.cpp @@ -39,8 +39,9 @@ RubberBandStretcher::RubberBandStretcher(size_t sampleRate, */ m_d(nullptr), //!!! +logger - m_r3d(new R3StretcherImpl(R3StretcherImpl::Parameters - (sampleRate, channels))) + m_r3d(new R3StretcherImpl(R3StretcherImpl::Parameters(sampleRate, channels), + initialTimeRatio, + initialPitchScale)) { } diff --git a/src/faster/StretchCalculator.cpp b/src/common/StretchCalculator.cpp similarity index 99% rename from src/faster/StretchCalculator.cpp rename to src/common/StretchCalculator.cpp index 87580e8..071e56b 100644 --- a/src/faster/StretchCalculator.cpp +++ b/src/common/StretchCalculator.cpp @@ -30,7 +30,7 @@ #include #include -#include "../common/sysutils.h" +#include "sysutils.h" namespace RubberBand { diff --git a/src/faster/StretchCalculator.h b/src/common/StretchCalculator.h similarity index 100% rename from src/faster/StretchCalculator.h rename to src/common/StretchCalculator.h diff --git a/src/faster/StretcherImpl.cpp b/src/faster/StretcherImpl.cpp index a23ebbc..4cc760b 100644 --- a/src/faster/StretcherImpl.cpp +++ b/src/faster/StretcherImpl.cpp @@ -27,9 +27,9 @@ #include "HighFrequencyAudioCurve.h" #include "SilentAudioCurve.h" #include "CompoundAudioCurve.h" -#include "StretchCalculator.h" #include "StretcherChannelData.h" +#include "../common/StretchCalculator.h" #include "../common/Resampler.h" #include "../common/Profiler.h" #include "../common/sysutils.h" diff --git a/src/faster/StretcherProcess.cpp b/src/faster/StretcherProcess.cpp index cb79b2a..c5a8b60 100644 --- a/src/faster/StretcherProcess.cpp +++ b/src/faster/StretcherProcess.cpp @@ -22,9 +22,9 @@ */ #include "StretcherImpl.h" -#include "StretchCalculator.h" #include "StretcherChannelData.h" +#include "../common/StretchCalculator.h" #include "../common/Resampler.h" #include "../common/Profiler.h" #include "../common/VectorOps.h" diff --git a/src/finer/R3StretcherImpl.cpp b/src/finer/R3StretcherImpl.cpp index b7d1b2b..de9ff85 100644 --- a/src/finer/R3StretcherImpl.cpp +++ b/src/finer/R3StretcherImpl.cpp @@ -31,12 +31,39 @@ void R3StretcherImpl::setTimeRatio(double ratio) { m_timeRatio = ratio; + calculateHop(); } void R3StretcherImpl::setPitchScale(double scale) { m_pitchScale = scale; + calculateHop(); +} + +void +R3StretcherImpl::calculateHop() +{ + double ratio = getEffectiveRatio(); + double proposedOuthop = 256; + + if (ratio > 1.0) { + double inhop = proposedOuthop / ratio; + if (inhop < 1.0) { + m_parameters.logger("WARNING: Extreme ratio yields ideal inhop < 1, results may be suspect"); + m_inhop = 1; + } else { + m_inhop = int(round(inhop)); + } + } else { + double inhop = std::min(proposedOuthop / ratio, 340.0); + m_inhop = int(round(inhop)); + } + + std::ostringstream str; + str << "R3StretcherImpl::calculateHop: for effective ratio " << ratio + << " calculated (typical) inhop of " << m_inhop << std::endl; + m_parameters.logger(str.str()); } double @@ -144,16 +171,28 @@ R3StretcherImpl::retrieve(float *const *output, size_t samples) const void R3StretcherImpl::consume() { - int inhop = 171, outhop = 256; //!!! - double ratio = double(outhop) / double(inhop); + double ratio = getEffectiveRatio(); int longest = m_guideConfiguration.longestFftSize; int classify = m_guideConfiguration.classificationFftSize; + + int outhop = m_calculator->calculateSingle(ratio, + 1.0 / m_pitchScale, + 1.f, + m_inhop, + longest, + longest); + + double instantaneousRatio = double(outhop) / double(m_inhop); while ((m_draining || m_channelData[0]->inbuf->getReadSpace() >= longest) && m_channelData[0]->outbuf->getWriteSpace() >= outhop) { m_parameters.logger("consume looping"); + + if (m_draining && m_channelData[0]->inbuf->getReadSpace() == 0) { + break; + } for (int c = 0; c < m_parameters.channels; ++c) { @@ -200,7 +239,8 @@ R3StretcherImpl::consume() m_troughPicker.findNearestAndNextPeaks (classifyScale->mag.data(), 3, nullptr, classifyScale->nextTroughs.data()); - m_guide.calculate(ratio, classifyScale->mag.data(), + m_guide.calculate(instantaneousRatio, + classifyScale->mag.data(), classifyScale->nextTroughs.data(), classifyScale->prevMag.data(), cd->segmentation, @@ -225,7 +265,7 @@ R3StretcherImpl::consume() m_channelAssembly.phase.data(), m_guideConfiguration, m_channelAssembly.guidance.data(), - inhop, + m_inhop, outhop); } @@ -300,7 +340,7 @@ R3StretcherImpl::consume() v_zero(acc.data() + n, outhop); } cd->outbuf->write(cd->mixdown.data(), outhop); - cd->inbuf->skip(inhop); + cd->inbuf->skip(m_inhop); } } } diff --git a/src/finer/R3StretcherImpl.h b/src/finer/R3StretcherImpl.h index 707a0a7..afd47d8 100644 --- a/src/finer/R3StretcherImpl.h +++ b/src/finer/R3StretcherImpl.h @@ -29,6 +29,7 @@ #include "Peak.h" #include "PhaseAdvance.h" +#include "../common/StretchCalculator.h" #include "../common/FFT.h" #include "../common/FixedVector.h" #include "../common/Allocators.h" @@ -53,12 +54,17 @@ public: sampleRate(_sampleRate), channels(_channels), logger(_log) { } }; - R3StretcherImpl(Parameters parameters) : + R3StretcherImpl(Parameters parameters, + double initialTimeRatio, + double initialPitchScale) : m_parameters(parameters), + m_timeRatio(initialTimeRatio), + m_pitchScale(initialPitchScale), m_guide(Guide::Parameters(m_parameters.sampleRate)), m_guideConfiguration(m_guide.getConfiguration()), m_channelAssembly(m_parameters.channels), m_troughPicker(m_guideConfiguration.classificationFftSize / 2 + 1), + m_inhop(1), m_draining(false) { BinSegmenter::Parameters segmenterParameters @@ -89,6 +95,12 @@ public: m_parameters.logger); m_scaleData[fftSize] = std::make_shared(guidedParameters); } + + m_calculator = std::unique_ptr + (new StretchCalculator(int(round(m_parameters.sampleRate)), //!!! which is a double... + 1, false)); // no fixed inputIncrement + + calculateHop(); } ~R3StretcherImpl() { } @@ -191,16 +203,23 @@ protected: double m_timeRatio; double m_pitchScale; - + std::vector> m_channelData; std::map> m_scaleData; Guide m_guide; Guide::Configuration m_guideConfiguration; ChannelAssembly m_channelAssembly; Peak> m_troughPicker; + std::unique_ptr m_calculator; + int m_inhop; bool m_draining; void consume(); + void calculateHop(); + + double getEffectiveRatio() const { + return m_timeRatio * m_pitchScale; + } static void logCerr(const std::string &message) { std::cerr << "RubberBandStretcher: " << message << std::endl; diff --git a/vamp/RubberBandVampPlugin.cpp b/vamp/RubberBandVampPlugin.cpp index a3dbd6c..6a8ca3a 100644 --- a/vamp/RubberBandVampPlugin.cpp +++ b/vamp/RubberBandVampPlugin.cpp @@ -23,7 +23,7 @@ #include "RubberBandVampPlugin.h" -#include "faster/StretchCalculator.h" +#include "common/StretchCalculator.h" #include "common/sysutils.h" #include