diff --git a/modules/juce_dsp/processors/juce_DryWetMixer.cpp b/modules/juce_dsp/processors/juce_DryWetMixer.cpp index b25cc84eeb..a6f7c964c4 100644 --- a/modules/juce_dsp/processors/juce_DryWetMixer.cpp +++ b/modules/juce_dsp/processors/juce_DryWetMixer.cpp @@ -93,62 +93,36 @@ void DryWetMixer::reset() dryDelayLine.reset(); - offsetInBuffer = 0; - numUsedSamples = 0; -} - -template -struct FirstAndSecondPartBlocks -{ - AudioBlock first, second; -}; - -template -static FirstAndSecondPartBlocks getFirstAndSecondPartBlocks (AudioBuffer& bufferDry, - size_t firstPartStart, - size_t channelsToCopy, - size_t samplesToCopy) -{ - const auto actualChannelsToCopy = jmin (channelsToCopy, (size_t) bufferDry.getNumChannels()); - const auto firstPartLength = jmin ((size_t) bufferDry.getNumSamples() - firstPartStart, samplesToCopy); - const auto secondPartLength = samplesToCopy - firstPartLength; - - const auto channelBlock = AudioBlock (bufferDry).getSubsetChannelBlock (0, actualChannelsToCopy); - - return { channelBlock.getSubBlock (firstPartStart, firstPartLength), - secondPartLength != 0 ? channelBlock.getSubBlock (0, samplesToCopy - firstPartLength) : AudioBlock() }; + fifo = SingleThreadedAbstractFifo (nextPowerOfTwo (bufferDry.getNumSamples())); + bufferDry.setSize (bufferDry.getNumChannels(), fifo.getSize(), false, false, true); } //============================================================================== template void DryWetMixer::pushDrySamples (const AudioBlock drySamples) { - const auto remainingSpace = (size_t) bufferDry.getNumSamples() - numUsedSamples; - jassert (drySamples.getNumChannels() <= (size_t) bufferDry.getNumChannels()); - jassert (drySamples.getNumSamples() <= remainingSpace); + jassert (drySamples.getNumSamples() <= (size_t) fifo.getRemainingSpace()); - auto blocks = getFirstAndSecondPartBlocks (bufferDry, - (offsetInBuffer + numUsedSamples) % (size_t) bufferDry.getNumSamples(), - drySamples.getNumChannels(), - jmin (drySamples.getNumSamples(), remainingSpace)); + auto offset = 0; - const auto processSubBlock = [this, &drySamples] (AudioBlock block, size_t startOffset) + for (const auto& range : fifo.write ((int) drySamples.getNumSamples())) { - auto inputBlock = drySamples.getSubBlock (startOffset, block.getNumSamples()); + if (range.getLength() == 0) + continue; + + auto block = AudioBlock (bufferDry).getSubsetChannelBlock (0, drySamples.getNumChannels()) + .getSubBlock ((size_t) range.getStart(), (size_t) range.getLength()); + + auto inputBlock = drySamples.getSubBlock ((size_t) offset, (size_t) range.getLength()); if (maximumWetLatencyInSamples == 0) block.copyFrom (inputBlock); else dryDelayLine.process (ProcessContextNonReplacing (inputBlock, block)); - }; - processSubBlock (blocks.first, 0); - - if (blocks.second.getNumSamples() > 0) - processSubBlock (blocks.second, blocks.first.getNumSamples()); - - numUsedSamples += blocks.first.getNumSamples() + blocks.second.getNumSamples(); + offset += range.getLength(); + } } template @@ -156,24 +130,22 @@ void DryWetMixer::mixWetSamples (AudioBlock inOutBlock) { inOutBlock.multiplyBy (wetVolume); - jassert (inOutBlock.getNumSamples() <= numUsedSamples); + jassert (inOutBlock.getNumSamples() <= (size_t) fifo.getNumReadable()); - auto blocks = getFirstAndSecondPartBlocks (bufferDry, - offsetInBuffer, - inOutBlock.getNumChannels(), - jmin (inOutBlock.getNumSamples(), numUsedSamples)); - blocks.first.multiplyBy (dryVolume); - inOutBlock.add (blocks.first); + auto offset = 0; - if (blocks.second.getNumSamples() != 0) + for (const auto& range : fifo.read ((int) inOutBlock.getNumSamples())) { - blocks.second.multiplyBy (dryVolume); - inOutBlock.getSubBlock (blocks.first.getNumSamples()).add (blocks.second); - } + if (range.getLength() == 0) + continue; - const auto samplesToCopy = blocks.first.getNumSamples() + blocks.second.getNumSamples(); - offsetInBuffer = (offsetInBuffer + samplesToCopy) % (size_t) bufferDry.getNumSamples(); - numUsedSamples -= samplesToCopy; + auto block = AudioBlock (bufferDry).getSubsetChannelBlock (0, inOutBlock.getNumChannels()) + .getSubBlock ((size_t) range.getStart(), (size_t) range.getLength()); + block.multiplyBy (dryVolume); + inOutBlock.getSubBlock ((size_t) offset).add (block); + + offset += range.getLength(); + } } //============================================================================== @@ -271,7 +243,7 @@ struct DryWetMixerTests : public UnitTest const auto wetBuffer = getRampBuffer (spec, Kind::up); const auto dryBuffer = getRampBuffer (spec, Kind::down); - for (auto maxLatency : { 0, 512 }) + for (auto maxLatency : { 0, 100, 200, 512 }) { beginTest ("Mixer can push multiple small buffers"); { diff --git a/modules/juce_dsp/processors/juce_DryWetMixer.h b/modules/juce_dsp/processors/juce_DryWetMixer.h index 0c243f49dc..ec760abc26 100644 --- a/modules/juce_dsp/processors/juce_DryWetMixer.h +++ b/modules/juce_dsp/processors/juce_DryWetMixer.h @@ -109,10 +109,10 @@ private: DelayLine dryDelayLine; AudioBuffer bufferDry; + SingleThreadedAbstractFifo fifo; SampleType mix = 1.0; MixingRule currentMixingRule = MixingRule::linear; double sampleRate = 44100.0; - size_t offsetInBuffer = 0, numUsedSamples = 0; int maximumWetLatencyInSamples = 0; };