Suggestions for removing dry signal from delay buffer

Hello!

I’m working on a Delay plugin based on the ffAudio ffTapeDelay, and wanted some help figuring out an issue with my dry and wet gain controls.

Currently my dry buffer is the buffer parameter from processBlock, which I then copy into wetBuffer, and set aside till the end. I use wetBuffer to perform the circular delay processing, and then finally copy it back into buffer.

Logically, because the wetBuffer starts as a complete copy of the dry buffer, it will ultimately contain the wet signal and the dry signal, instead of just the wet signal.

Does anyone have any ideas for how I could remove the dry signal from the wet buffer? I’ve attached my processBlock code below. Any advice would be greatly appreciated!

void BitDelayAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
    juce::ScopedNoDenormals noDenormals;
    auto totalNumInputChannels = getTotalNumInputChannels();
    auto totalNumOutputChannels = getTotalNumOutputChannels();

    juce::AudioBuffer<float> wetBuffer;
    wetBuffer.makeCopyOf(buffer);

    for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
        buffer.clear(i, 0, buffer.getNumSamples());

    const int bufferLength = buffer.getNumSamples();
    const int delayBufferLength = mDelayBuffer.getNumSamples();

    for (int channel = 0; channel < totalNumInputChannels; ++channel)
    {
        auto* bufferData = wetBuffer.getWritePointer(channel);

        wetBuffer.applyGainRamp(channel, 0, buffer.getNumSamples(), lastInputGain, volume->getValue());
        lastInputGain = volume->getValue();

        fillBuffer(channel, bufferLength, delayBufferLength, bufferData);

        readFromBuffer(channel, bufferLength, delayBufferLength, wetBuffer);

        fillBuffer(channel, bufferLength, delayBufferLength, bufferData);

        wetBuffer.applyGainRamp(channel, 0, bufferLength, lastWetGain, wet->getValue());
        lastWetGain = wet->getValue();

        buffer.applyGainRamp(channel, 0, bufferLength, lastDryGain, dry->getValue());
        lastDryGain = dry->getValue();

        buffer.addFrom(channel, 0, bufferData, bufferLength);
    }

    mWritePosition += bufferLength;
    mWritePosition %= delayBufferLength;
}

Could you use addFrom the other way first, adding buffer to wetBuffer, with the gain set to -1? I don’t see a subtractFrom.

I’ll try this! Thanks!

instead of adding to the ringbuffer, you could just replace what’s in there

The issue is that if I clear or replace the wetBuffer at any point after the first fillBuffer, it basically zeroes the wet output and breaks my feedback loop.

oh yeah, understandable. replacing parts of the buffer only works for feed forward delays. in that case what about just copying the dry signal into another buffer at the beginning, so at the end you can just subtract them from each other?

So I would copy my input buffer, then once the circular buffer processing is done subtract the dryCopyBuffer from wetBuffer?

Is there a function I could use for this, or would I have to iterate sample by sample and subtract manually?

Thanks!

the function would do just that. i guess you could use some FloatVectorOperations method for that

Using FloatVectorOperations::subtract worked. I had to fix an issue where I was hard-coding the gain on the buffers so the subtraction was producing weird results, but once that was fixed, it worked perfectly. My dry/wet controls are working as intended. Thanks!

1 Like