Look Ahead / Delay Compensation best practice?

Hi,
So I’ve implemented lookAhead in my plugin, and so far it works pretty well! But my method of doing so feels… very basic and dangerous.

Basically, first thing in processBlock is reading the buffer into a FIFO. I have a value that iterates, and once it reaches a certain value, my processing starts.

if (lookAheadReached == false)
    lookAheadPosition += bufferLength;//This determines delay time before pushing FIFO buffers to output.

//Push buffer to FIFO
FIFO->addToFifo(buffer, bufferLength);

if (lookAheadPosition > delayCompensationSamps) //if enough delay has passed to push FIFO buffer to output
{
    lookAheadReached == true;
    FIFO->readFromFifo(lookAheadBuf, bufferLength);
    //...Start the processing

Does anyone have a better method of doing this? It does the job, but I’m trying to make my code more efficient and it feels like this is my main area of improvement.

Also, I hope this code also helps someone trying to do the same thing, I couldn’t find too much on lookAhead on here so I just figured it out on my own.

Thanks in advance!

If I understand it correctly, the problem you’re trying to solve there is that some data must be present in the FIFO so you have something to read, right?

The easiest way when using a FIFO logic for the delay is to push delayCompensationSamps zeros into the FIFO upon initialization. Then you can skip all those ifs and tracking the amount of written samples. Just write and read to/from the FIFO and the behavior will be basically as if the thing has been running forever.

3 Likes

Did you see this? SimpleCompressor: JUCE processor with article of how to implement look-ahead

2 Likes

I have no idea how I missed this, gotta work on my forum searching props. Thanks for this, saved!

I did exactly what you said and it worked! God bless.

Quick question though, upon initialization, do you mean in the constructor? Currently I push these samples in prepareToPlay and it’s working fine, but perhaps there will be unforeseen issues with this.

Thanks so much, JUCE forums always seem to deliver!

I didn’t fully read the code but ‘prepareToPlay’ is the right place to allocate / zero buffers.
Keep in mind look a head might be sample agnostic so each sample rate change would mean different buffer size.

2 Likes

Yeah, prepareToPlay is the right place. And don’t forget to clear the buffer before pushing zeros. Otherwise, if prepareToPlay is called multiple times during lifetime, the lookahead will add up each time.