From d3830870c03aa8340c337d2e0f208d174105184c Mon Sep 17 00:00:00 2001 From: Chris Cannam Date: Wed, 15 Mar 2023 18:01:21 +0000 Subject: [PATCH] Experiments with mid-side in R3 - in this code always used when channels=2 --- src/finer/R3Stretcher.cpp | 47 +++++++++++++++++++++++++++++++++++++-- src/finer/R3Stretcher.h | 5 ++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/finer/R3Stretcher.cpp b/src/finer/R3Stretcher.cpp index 6cb6ae9..a4e0945 100644 --- a/src/finer/R3Stretcher.cpp +++ b/src/finer/R3Stretcher.cpp @@ -752,11 +752,13 @@ R3Stretcher::process(const float *const *input, size_t samples, bool final) int maxResampleInput = int(floor(maxResampleOutput * m_pitchScale)); int resampleInput = std::min(remaining, maxResampleInput); if (resampleInput == 0) resampleInput = 1; + + prepareInput(input, inputIx, resampleInput); int resampleOutput = m_resampler->resample (m_channelAssembly.resampled.data(), maxResampleOutput, - input, + m_channelAssembly.input.data(), resampleInput, 1.0 / m_pitchScale, final); @@ -776,8 +778,11 @@ R3Stretcher::process(const float *const *input, size_t samples, bool final) m_log.log(2, "process: resamplingBefore is false, writing to inbuf from supplied data, former read space and samples being added", m_channelData[0]->inbuf->getReadSpace(), toWrite); + prepareInput(input, inputIx, toWrite); + for (int c = 0; c < m_parameters.channels; ++c) { - m_channelData[c]->inbuf->write(input[c] + inputIx, toWrite); + m_channelData[c]->inbuf->write + (m_channelAssembly.input[c], toWrite); } inputIx += toWrite; } @@ -814,9 +819,47 @@ R3Stretcher::retrieve(float *const *output, size_t samples) const } } + bool useMidSide = (m_parameters.channels == 2); //!!! + + if (useMidSide) { + for (int i = 0; i < got; ++i) { + float m = output[0][i]; + float s = output[1][i]; + float l = m + s; + float r = m - s; + output[0][i] = l; + output[1][i] = r; + } + } + return got; } +void +R3Stretcher::prepareInput(const float *const *input, int ix, int n) +{ + bool useMidSide = (m_parameters.channels == 2); //!!! + + if (useMidSide) { + auto &c0 = m_channelData.at(0)->mixdown; + auto &c1 = m_channelData.at(1)->mixdown; + for (int i = 0; i < n; ++i) { + float l = input[0][i + ix]; + float r = input[1][i + ix]; + float m = (l + r) / 2.f; + float s = (l - r) / 2.f; + c0[i] = m; + c1[i] = s; + } + m_channelAssembly.input[0] = m_channelData.at(0)->mixdown.data(); + m_channelAssembly.input[1] = m_channelData.at(1)->mixdown.data(); + } else { + for (int c = 0; c < m_parameters.channels; ++c) { + m_channelAssembly.input[c] = input[c] + ix; + } + } +} + void R3Stretcher::consume() { diff --git a/src/finer/R3Stretcher.h b/src/finer/R3Stretcher.h index d1b8308..57a3187 100644 --- a/src/finer/R3Stretcher.h +++ b/src/finer/R3Stretcher.h @@ -241,7 +241,7 @@ protected: BinClassifier::Classification::Residual), segmenter(new BinSegmenter(segmenterParameters)), segmentation(), prevSegmentation(), nextSegmentation(), - mixdown(longestFftSize, 0.f), + mixdown(inRingBufferSize, 0.f), resampled(outRingBufferSize, 0.f), inbuf(new RingBuffer(inRingBufferSize)), outbuf(new RingBuffer(outRingBufferSize)), @@ -263,6 +263,7 @@ protected: struct ChannelAssembly { // Vectors of bare pointers, used to package container data // from different channels into arguments for PhaseAdvance + FixedVector input; FixedVector mag; FixedVector phase; FixedVector prevMag; @@ -271,6 +272,7 @@ protected: FixedVector mixdown; FixedVector resampled; ChannelAssembly(int channels) : + input(channels, nullptr), mag(channels, nullptr), phase(channels, nullptr), prevMag(channels, nullptr), guidance(channels, nullptr), outPhase(channels, nullptr), mixdown(channels, nullptr), @@ -350,6 +352,7 @@ protected: }; ProcessMode m_mode; + void prepareInput(const float *const *input, int ix, int n); void consume(); void createResampler(); void calculateHop();