diff --git a/meson.build b/meson.build index 0a1dfae..506bf4a 100644 --- a/meson.build +++ b/meson.build @@ -5,7 +5,7 @@ project( version: '2.0.2', license: 'GPL-2.0-or-later', default_options: [ - 'cpp_std=c++14', + 'cpp_std=c++11', 'buildtype=release', 'default_library=both', 'b_ndebug=if-release', diff --git a/src/finer/BinClassifier.h b/src/finer/BinClassifier.h index 82456de..cf2655c 100644 --- a/src/finer/BinClassifier.h +++ b/src/finer/BinClassifier.h @@ -66,6 +66,7 @@ public: BinClassifier(Parameters parameters) : m_parameters(parameters), + m_vFilter(new MovingMedian(m_parameters.verticalFilterLength)), m_vfQueue(parameters.horizontalFilterLag) { int n = m_parameters.binCount; @@ -75,9 +76,6 @@ public: (m_parameters.horizontalFilterLength)); } - m_vFilter = std::make_unique> - (m_parameters.verticalFilterLength); - m_hf = allocate_and_zero(n); m_vf = allocate_and_zero(n); diff --git a/src/finer/BinSegmenter.h b/src/finer/BinSegmenter.h index 6ae202c..a173ba0 100644 --- a/src/finer/BinSegmenter.h +++ b/src/finer/BinSegmenter.h @@ -37,6 +37,8 @@ public: double percussiveBelow; double percussiveAbove; double residualAbove; + explicit Segmentation() : + percussiveBelow(0.0), percussiveAbove(0.0), residualAbove(0.0) { } Segmentation(double _pb, double _pa, double _ra) : percussiveBelow(_pb), percussiveAbove(_pa), residualAbove(_ra) { } }; diff --git a/src/finer/Guide.h b/src/finer/Guide.h index 6d5da67..a1d6fac 100644 --- a/src/finer/Guide.h +++ b/src/finer/Guide.h @@ -87,9 +87,11 @@ public: struct Configuration { int classificationFftSize; + int longestFftSize; BandLimits fftBandLimits[3]; - Configuration(int _classificationFftSize) : - classificationFftSize(_classificationFftSize) { } + Configuration(int _classificationFftSize, int _longestFftSize) : + classificationFftSize(_classificationFftSize), + longestFftSize(_longestFftSize) { } }; struct Parameters { @@ -100,7 +102,8 @@ public: Guide(Parameters parameters) : m_parameters(parameters), - m_configuration(roundUp(int(ceil(parameters.sampleRate / 32.0)))), + m_configuration(roundUp(int(ceil(parameters.sampleRate / 32.0))), + roundUp(int(ceil(parameters.sampleRate / 16.0)))), m_defaultLower(700.0), m_defaultHigher(4800.0), m_maxLower(1100.0), m_maxHigher(7000.0) { diff --git a/src/finer/PhaseAdvance.h b/src/finer/PhaseAdvance.h index fb466d1..3015ab9 100644 --- a/src/finer/PhaseAdvance.h +++ b/src/finer/PhaseAdvance.h @@ -26,6 +26,9 @@ #include "Guide.h" +#include +#include + namespace RubberBand { @@ -36,14 +39,18 @@ public: int fftSize; double sampleRate; int channels; - Parameters(int _fftSize, double _sampleRate, int _channels) : - fftSize(_fftSize), sampleRate(_sampleRate), channels(_channels) { } + std::function logger; + Parameters(int _fftSize, double _sampleRate, int _channels, + std::function _log) : + fftSize(_fftSize), sampleRate(_sampleRate), + channels(_channels), logger(_log) { } }; GuidedPhaseAdvance(Parameters parameters) : m_parameters(parameters), m_blockSize(parameters.fftSize / 2 + 1), - m_peakPicker(m_blockSize) { + m_peakPicker(m_blockSize), + m_reported(false) { size_t ch = m_parameters.channels; m_currentPeaks = allocate_and_zero_channels(ch, m_blockSize); m_prevPeaks = allocate_and_zero_channels(ch, m_blockSize); @@ -89,6 +96,18 @@ public: (configuration.fftBandLimits[myFftBand].f0min); int highest = binForFrequency (configuration.fftBandLimits[myFftBand].f1max); + + if (!m_reported) { + std::ostringstream ostr; + ostr << "PhaseAdvance: fftSize = " << m_parameters.fftSize + << ": bins = " << bs << ", channels = " << channels + << ", inhop = "<< inhop << ", outhop = " << outhop + << ", ratio = " << ratio << std::endl; + ostr << "PhaseAdvance: lowest possible = " << lowest + << "Hz, highest = " << highest << "Hz" << std::endl; + m_parameters.logger(ostr.str()); + m_reported = true; + } for (int c = 0; c < channels; ++c) { for (int i = lowest; i <= highest; ++i) { @@ -184,9 +203,13 @@ public: } } + //!!! NB in the original we use a different value of p for + //!!! peak-picking the prior magnitudes - this isn't carried + //!!! over here + int **tmp = m_prevPeaks; m_prevPeaks = m_currentPeaks; - m_currentPeaks = m_prevPeaks; + m_currentPeaks = tmp; } protected: @@ -199,6 +222,7 @@ protected: float **m_prevInPhase; double **m_prevOutPhase; double **m_unlocked; + bool m_reported; int binForFrequency(double f) const { return int(round(f * double(m_parameters.fftSize) / diff --git a/src/finer/R3StretcherImpl.h b/src/finer/R3StretcherImpl.h index d917242..5a26cb1 100644 --- a/src/finer/R3StretcherImpl.h +++ b/src/finer/R3StretcherImpl.h @@ -24,9 +24,6 @@ #ifndef RUBBERBAND_R3_STRETCHERIMPL_H #define RUBBERBAND_R3_STRETCHERIMPL_H -#include -#include - #include "BinSegmenter.h" #include "Guide.h" #include "Peak.h" @@ -37,18 +34,52 @@ #include "../common/Allocators.h" #include "../common/Window.h" +#include +#include +#include + namespace RubberBand { class R3StretcherImpl { public: - R3StretcherImpl(double sampleRate, int channels) : - m_sampleRate(sampleRate), m_channels(channels), - m_guide(Guide::Parameters(sampleRate)), + struct Parameters { + double sampleRate; + int channels; + std::function logger; + Parameters(double _sampleRate, int _channels, + std::function _log = &logCerr) : + sampleRate(_sampleRate), channels(_channels), logger(_log) { } + }; + + R3StretcherImpl(Parameters parameters) : + m_parameters(parameters), + m_guide(Guide::Parameters(m_parameters.sampleRate)), m_guideConfiguration(m_guide.getConfiguration()) - { } - ~R3StretcherImpl(); + { + BinSegmenter::Parameters segmenterParameters + (m_guideConfiguration.classificationFftSize, + m_parameters.sampleRate); + BinClassifier::Parameters classifierParameters + (m_guideConfiguration.classificationFftSize / 2 + 1, + 9, 1, 10, 2.0, 2.0, 1.0e-7); + int ringBufferSize = m_guideConfiguration.longestFftSize * 2; + for (int c = 0; c < m_parameters.channels; ++c) { + m_channelData.push_back(std::make_shared + (segmenterParameters, + classifierParameters, + ringBufferSize)); + for (auto band: m_guideConfiguration.fftBandLimits) { + int fftSize = band.fftSize; + m_ffts[fftSize] = std::make_shared(fftSize); + m_channelData[c]->scales[fftSize] = + std::make_shared(fftSize); + } + } + } + + ~R3StretcherImpl() { } void reset(); @@ -97,18 +128,29 @@ protected: Guide::Guidance guidance; RingBuffer inbuf; RingBuffer outbuf; + ChannelData(BinSegmenter::Parameters segmenterParameters, + BinClassifier::Parameters classifierParameters, + int ringBufferSize) : + scales(), + segmenter(new BinSegmenter(segmenterParameters, + classifierParameters)), + segmentation(), prevSegmentation(), nextSegmentation(), + inbuf(ringBufferSize), outbuf(ringBufferSize) { } }; - double m_sampleRate; - int m_channels; + Parameters m_parameters; double m_timeRatio; double m_pitchScale; - std::vector m_channelData; + std::vector> m_channelData; std::map> m_ffts; Guide m_guide; Guide::Configuration m_guideConfiguration; + + static void logCerr(const std::string &message) { + std::cerr << "RubberBandStretcher: " << message << std::endl; + } }; } diff --git a/src/temporary.cpp b/src/temporary.cpp index 39d8493..9d21171 100644 --- a/src/temporary.cpp +++ b/src/temporary.cpp @@ -1 +1,8 @@ #include "finer/R3StretcherImpl.h" + +int main(int argc, char **argv) +{ + RubberBand::R3StretcherImpl::Parameters parameters(44100.0, 2); + RubberBand::R3StretcherImpl impl(parameters); +} +