diff --git a/src/finer/PhaseAdvance.h b/src/finer/PhaseAdvance.h index f5a6496..1c1384f 100644 --- a/src/finer/PhaseAdvance.h +++ b/src/finer/PhaseAdvance.h @@ -94,6 +94,7 @@ public: const process_t *const *prevMag, const Guide::Configuration &configuration, const Guide::Guidance *const *guidance, + bool usingMidSide, int inhop, int outhop) { @@ -197,6 +198,9 @@ public: process_t ph = 0.0; if (inRange(f, g->phaseReset) || inRange(f, g->kick)) { ph = phase[c][i]; + } else if (usingMidSide && channels == 2 && + c == 0 && inRange(f, guidance[1]->phaseReset)) { + ph = phase[c][i]; } else if (inhop == outhop) { ph = m_unlocked[c][i]; } else if (inRange (f, g->highUnlocked)) { diff --git a/src/finer/R3Stretcher.cpp b/src/finer/R3Stretcher.cpp index 3e1b9c8..bfbbbde 100644 --- a/src/finer/R3Stretcher.cpp +++ b/src/finer/R3Stretcher.cpp @@ -757,11 +757,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); @@ -781,8 +783,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; } @@ -819,9 +824,43 @@ R3Stretcher::retrieve(float *const *output, size_t samples) const } } + 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) +{ + 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() { @@ -933,6 +972,7 @@ R3Stretcher::consume() m_channelAssembly.prevMag.data(), m_guideConfiguration, m_channelAssembly.guidance.data(), + useMidSide(), m_prevInhop, m_prevOuthop); } diff --git a/src/finer/R3Stretcher.h b/src/finer/R3Stretcher.h index d1b8308..88660f1 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(); @@ -469,6 +472,12 @@ protected: } } + bool useMidSide() const { + return m_parameters.channels == 2 && + (m_parameters.options & + RubberBandStretcher::OptionChannelsTogether); + } + bool isSingleWindowed() const { return m_parameters.options & RubberBandStretcher::OptionWindowShort;