This sound contains both mono and stereo implementations. Right now I have just a standard peaking/dipping EQ filter installed. But you can substitute any IIR filter you like. Even a whole chain of them...
This sound makes any IIR filter into a phase linear filter = constant delay, just like a symmetric FIR filter. It does this by sending the signal through the filter, then time reversing the signal and sending it through the filter again, and then finally re-time-reversing to get the final output.
However, just like for FFT processing, this chunks the input signal into blocks (in this case 4096 samples) and that chunking will cause temporal artifacts unless care is taken to smooth them over. We do that here, just like you do for FFT processing -- combining windowed versions of the signal with delayed versions of itself.
So for mono processing, it takes a total of 4 copies of your filter (chain). Two each in the two halves of the windowed processing in parallel. And those two are needed for the forward and reverse time filtering.
It can be shown that, in theory, this should work to remove any phase shift in the resulting filtered signal. But that is only true if you could time reverse the entire signal. We don't do that here. Instead we chunk the signal into blocks, and so the result is not exactly phase linear -- in the mathematical sense.
However, if these blocks are long enough, then the filter ringing dies away into the noise floor before reaching the end of the block. So for all practical purposes, we have accomplished what we need to do without serious artifacts.
But since the signal blocks are sent through the filter(s) twice, what you get is the square of the amplitude response of any one of them. I take care of that (sort of...) by using a script at the head of the processing to divide your desired dB gain/atten by 2 and passing that to each filter. Dividing dB by 2 is the same as taking the square root of the amplitude.
What that fails to account for, however, is the detailed bandwidth characteristics of the filter. It is well known that, e.g., sending a signal through two identical Butterworth (or any kind) filters is not the same as sending it through a single filter of that kind with double the filter order. The -3 dB frequency will be shifted, whereas the double-order filter will leave that point where you specify it to be.
I think the error will be relatively benign in practice. And perhaps later I can develop a formula to help compensate for this squaring effect.
The data window used here is the one used by the Vorbis encoder. That window is such that applying it twice and adding to shifted versions of itself produces a unity gain result. We apply the window to the input signal, and again to the output signal. In the absence of filtering the output should ideally equal the input and without any IMD products being generated by the windowing. In practice, once you modify the signal inside the processing chain with any kind of filtering, that no longer holds. But by using the overlap-add in two parallel processing chains, we sort of smooth over the resulting incongruities. The only way to improve on this is to use a shorter stride = greater overlap = much higher complexity. A four-fold temporal overlap would require twice as much processing as we are already doing.
The overall throughput delay of this filter is 10240 samples, but the result, just like for symmetric FIR filters is absolutely phase flat. This means two things (or more) to us:
1. We can create arbitrary phase flat IIR filters which can be used at any frequency and with any bandwidth and gain/atten. This is not so easy to do with FFT processing because of the finite width of each FFT cell, and it is next to impossible to do with FIR filtering if you need to be able to modify the filter on the fly the way you typically do with parametric equalization.
2. There will be no net phase cancellation effects when combining filters. All you get is their product amplitude response. That makes the combination of filtering very deterministic and produces no surprises (like unwanted phase cancellation or reinforcement as happens normally with IIR filters.)
Just in case you don't have a copy of that Vorbis window, here it is:
-- DavidMcClain - 16 Oct 2005
In retrospect, the retrograde solution provided here is not correct. And perhaps we won't need to do the windowing trick either. I'm working on a correction that will alternate chunk buffers so that the reader and writer will never be operating at the same time in the same buffer. I thought that by delaying the starting times of various branches that would do the trick, but I was wrong...
Be back with a correction shortly...
DavidMcClain - 16 Oct 2005
Okay, here is the corrected Sound set. I was partly wrong about being wrong... However, we still need the windowed overlap-add because of the gross discontinuity between successive blocks. What we don't need are the sound start-time offsets.
And it is okay for both the reader and writer pointers to be working in the same block. They will cross paths at the mid-point but that's fine. It means that the reader branch will be working a half-buffer ahead of the writer branch. As it reads from the tail end of the buffer while the writer is filling from the front of the buffer, the reader is seeing the last half buffer from the prior writing cycle, and the first half buffer from the current cycle.
So the result, while still a bit complicated, has been simplified. The delay has been significantly shortened too. I measure 127.67ms at 48 kHz SR.
It sounds great on my system. I'm sitting here notching out the bass line on some recordings and moving the frequency up and down, looking for phase artifacts. There are none. We should A/B against a standard IIR filter and see if we can notice the difference. I suspect that the differences will show up most strongly with very narrow, high-Q, filters, at frequencies very near the tuning cutoff or center of the filters, and the effect is most likely going to be to smear out some transient events with conventional IIR filtering. That smearing ought to disappear with this phase linear IIR implementation.
One artifact I do see, even in the absence of any filtering, is that the high-frequency response up around the Nyquist frequency is slightly depressed relative to the input signal. Not sure why that should be? perhaps a result of those temporal artifacts I was referring to above? But anyway, we can't hear up that high so it makes no difference in practice.
-- DavidMcClain - 16 Oct 2005