This post is here so that we have something we can link to when this same issue comes up, because the JUCE team is getting very bored of spending time replying again and again to the same damned problem!
This isn’t a JUCE bug - there’s nothing we can do in our codebase that would stop people making it, which makes it painful for us to watch beginner after beginner come along and fall headfirst into the same trap!
It’s also understandable that people will post a new topic when they hit it, because it’s not the kind of problem you can find an answer to with a search. The forum probably contains hundreds of posts about the same thing, but the code is always different, and there’s no keyword you could look for to find them.
But there’s always a process method, and it always contains a loop that looks something like this:
for (int channel = 0; channel < 2; ++channel)
{
float* thisChannel = data[channel];
for (int sample = 0; sample < numSamples; ++sample)
{
thisChannel[sample] = someFunctionOf (lastSample); // where lastSample is a member variable.
lastSample = thisChannel[sample];
}
}
…and the poster will complain of “noise” or “artefacts” or “clicking”.
Usually there’s a variable holding a previous sample value. Or there’s a single IIR or FIR that they’re applying to all channels, but it’s basically the same mistake.
To anyone who can’t see the bug, it’s because you need to keep separate state for each channel. Otherwise, that last sample value from the end of channel 0 will be used at the the start of channel 1 when you go round the outer loop.
If anyone has any ideas about how we could somehow pre-warn newbies and stop them doing this, please let us know, as it’d save us a lot of time explaining the same thing over and over again!