AudioBuffer pointers.. and how to move them?

Hey,
I’m trying to apply a simple echo effect using an “echo buffer” (circular), and not sure how to deal with the read/write pointers native to AudioBuffer.

void AudioPoocessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)
{
    auto totalNumInputChannels  = getTotalNumInputChannels();
    for (int channel = 0; channel < totalNumInputChannels; ++channel) {
        auto *channelData = buffer.getWritePointer(channel);

        for (int i = 0; i < buffer.getNumSamples(); ++i) {
            auto echoReadPtr = echoBuffer.getReadPointer(channel, i);
            auto echoWritePtr = echoBuffer.getWritePointer(channel, i);
            // Calculate echo value and return to new echo
            *echoWritePtr = channelData[i] += *echoReadPtr * *echoParameter;
            // How do I increment the pointers??
            
        }
    }
}

I’ve been attempting to increment the pointers manually, but then resetting them (upon clearing the buffer) is complicated and starts needing multiple global variables… I get a feeling I’m doing something wrong here. Any guidance?

If you are speaking of literal global variables, that would certainly be wrong. Those (or static variables) should almost never be used in a plugin. But if you actually mean member variables of your AudioProcessor, you must have some to implement a delay properly. Surely your “echoBuffer” is already one? What’s the problem in adding a couple more for the delay buffer indexing variables? (To keep things simpler and safer, you really want to be using just integer indexes, not pointers for the delay read and write positions…)

1 Like

Alright, fair enough. I was worried I was on the wrong track. And you’re right about the global variables, I did mean member variables. Thanks for the tip on the indexes too, that starts to feel safer indeed. :wink:

Thank you!

For anyone interested, it turned out to be a lot more convenient to use the AudioBuffer::addFrom(), AudioBuffer::copyFrom() and AudioBuffer::applyGain() methods. I have a single index value to keep track of the start read/write on the “echo buffer”, and move it at the end of the loop through the channels (so that the state stays the same during the loop / per channel).
This meant I didn’t need any loops inside, which I guess I could feel was kind of gross.
Best of luck to anyone debugging!

Here’s my final “echo effect” code:

for (int channel = 0; channel < totalNumInputChannels; ++channel) {
    auto *channelData = buffer.getWritePointer(channel);
    bool resetState = false;
    if (channel == totalNumInputChannels - 1) {
        resetState = true;
    }

    if (echoBufferPt + numSamples > echoBufferSize) {
        auto firstHalfSize = echoBufferSize - echoBufferPt;
        auto secondHalfSize = numSamples - firstHalfSize;
        // Split add to output
        buffer.addFrom(channel, 0, echoBuffer, channel, echoBufferPt, firstHalfSize);
        buffer.addFrom(channel, firstHalfSize, echoBuffer, channel, 0, secondHalfSize);
        // Copy over to echoBuffer
        echoBuffer.copyFrom(channel, echoBufferPt, buffer, channel, 0, firstHalfSize);
        echoBuffer.copyFrom(channel, 0, buffer, channel, firstHalfSize, secondHalfSize);
        // Apply gain to echo buffer
        echoBuffer.applyGain(echoBufferPt, firstHalfSize, *echoParameter);
        echoBuffer.applyGain(channel, 0, secondHalfSize, *echoParameter);
        // Set new echoBufferPt if this is the last channel
        if (resetState)
            echoBufferPt = numSamples - firstHalfSize;
    } else {
        // Add to output
        buffer.addFrom(channel, 0, echoBuffer, channel, echoBufferPt, numSamples);
        // Copy to echo buffer
        echoBuffer.copyFrom(channel, echoBufferPt, buffer, channel, 0, numSamples);
        // Apply gain to echo buffer
        echoBuffer.applyGain(channel, echoBufferPt, numSamples, *echoParameter);
        // Set new echoBufferPt if this is the last channel
        if (resetState)
            echoBufferPt += numSamples;
    }
}
2 Likes