I’ve been researching this subject for multiple days now and I’ve found a lot of good resources, but haven’t been able to implement it in practise. I’m trying to build a linear phase band splitter and my first thought was to just sample the corresponding Linkwitz-Riley impulse response to use as my coefficients. This, of course, works great to just copy the functionality of the IIR filter but the phase isn’t linear. I then tried to mirror the impulse response to make it symmetrical and cancel out the phase shift while doing so but this results in some weird frequency and phase response. I also read a lot about forward-backward filtering but I can’t seem to be able to implement it in my program.
I’d really appreciate if someone could point me to the right direction.
Forward-Backward is the efficient way to do it in terms of algorithmic complexity. You will need to buffer some history samples. How many depends on your minimum split frequency, because the lower the frequency, the longer the filter tail will be. This determines the latency of your algorithm. You can make quality tradeoffs here. You will also need to implement an overlap-add scheme with windowing, same as when doing phase vocoder based algorithms (you’ll find lots of how tos searching for explanations on how these work).
I’d recommend making lots of pen-and-paper sketches, OLA schemes can quickly become confusing, and small off by one errors have the potential of ruining your result, even if your algorithm is conceptually correct.
You will know that your algorithm performs correctly by null testing the sum of your split bands against the plain delayed original signal.
If you want to use FIR, you’re not limited by linkwitz-riley. You just need a good low pass. The other band is just original signal minus low passed signal. Filter theory can get involved, there are many properties to consider for a “good” band split, but a good starting point is finding out how to generate a windowed sinc-pulse, with cutoff at your split frequency.
You could also try building something FFT/IFFT based, adjusting the magnitudes (again with a solid overlap add scheme), this way getting lots of flexibility with your crossover curves - don’t make them too steep though!
Thanks for the detailed reply @jcomusic. I really appreciate it. I have no idea if this is a good way of doing this, but this is what I ended up doing:
Take impulse response of corresponding Linkwitz-Riley filter
Sample magnitude response of the impulse (maybe more efficient to get the magnitude response directly from the LR filter transfer function?)
Create symmetric FIR coefficients using the frequency sampling method
Process FIR with frequency domain multiplication
This might be way too much work to make the filters but at least it works great and I can keep the latency and CPU usage relatively low.
Hey!
I don’t think I understand exactly what you’re doing in steps 1…3.
Impulse Response and FIR coefficients are basically the same thing. If you push a diraq pulse through a filter and take the output (with tail), you get an impuse response (= FIR coeffs). Is that what you are doing in step 1?
By sampling the magnitude response, are you just measuring the effect of the filter on the magnitude at different frequencies?
It does sound a little like you’re more or less doing what I suggested as the third option, but with a lot of overhead If you just want to do magnitude transfer, you can just operate on FFT magnitudes directly - if we’re talking “linear phase”, there is no need for full convolution, since you expect the phase response to not change at all.
Just curious
Are you using the JUCE convolution classes for applying your filter? How long is your IR? Have you tested the results for correctness?
I did do testing and the results are good for my application. I wrote my own convolution since the JUCE one didn’t quite fit my needs. The impulse response is indeed the same thing as the FIR coefficients but I had a hard time making the phase linear with using the IIR impulse response directly. What I’m essentially doing is designing the FIR from the IIR filter’s magnitude response, which might be too much work as you said.