Working with IIRFilter and circular buffers


#1

Hi,

i’m trying to implement a Filterbank in a feedback delay network.

The delay buffers are all of different sizes and naturally the samples are not strictly in chronological order inside each buffer, so when i simply invoke the processSamples method of IIRFilter on each delay buffer, the output sounds rather weird, which is to be expected because at some point samples are being filtered as if they were chronologically adjacent when really they are at opposing ends of the buffer.

Is there a way so one can still use the IIRFilter class with such a buffer or would i have to “unwrap” the buffer so the samples are strictly chronological before passing them to the filter?


#2

naturally the samples are not strictly in chronological order inside each buffer

That doesn’t sound natural at all… how do you implement a delay line when the samples in the buffer aren’t stored chronologically? If the delay lines are of different lengths in your FDN, that just means you’re going to wind up summing different taps at the output.


#3

The majority is chronological, but at the read/write pointer adress, the newest and oldest sample are adjacent to each other, that is what i mean when i say the buffer is “wrapped”.

Maybe this picture will explain better what i mean, 9 would be the most recently written sample and 0 would be the oldest. Next step would be to read out 0 and write 10 at that adress asf. Basically i copied the delay buffer implementation of the audio plugin demo.

buffer

I hope it is more intuitive to see what happens when i call

IIRFilter[channel].processSamples(delayBuffer[channel].getWritePointer(0), delayBufferLength[channel]).

Since the filter is stateful, it leads to wrong results because the filter “assumes” the oldest sample is left and the newest is to the far right in the buffer, at least that is my understanding of what is happening.

My question is, is there an easy solution to make it work with such a buffer without having to shift the buffer? I know there is a method that processes single samples in the filter, would handling the pointer arithmetic myself and passing only single values to the filter be my only choice?


#4

Ok, so since i already have two cascaded loops with which i iterate over each sample of each channel (for the feedback matrix multiplication), i tried using processSingleSampleRaw in there and feeding the filter single samples, which works alright and has far less performance overhead.

So basically i’m set now, but out of academic curiosity i’d still be interested to know if there is a way to work with the entire buffer, if someone has a better solution.


#5

You can process it in one or two blocks, depending if you have enough space:

int pos;
int numToProcess;

const int overflow = delayBuffer.getNumSamples() - (pos + numToProcess);
if (overflow < 0) {
    processBuffer (delayBuffer.getWritePointer (channel, pos), numToProcess);
    pos += numToProcess;
}
else {
    processBuffer (delayBuffer.getWritePointer (channel, pos), numToProcess - overflow);
    processBuffer (delayBuffer.getWritePointer (channel), overflow);
    pos = overflow;
}

There is also class to handle similar things, called AbstractFifo.
You can get inspiration from that:

HTH