Linear Phase,FIR Filter based EQ

kfir d's icon

hi I wont to create an eq based on Linear Phase FIR filters and i am really amateur in this I have read a lot and got just a little bit.
something with confections and math stuff :) i understood how fir low cut filter works but didn't get how to do in Linear phase.
I want to create a Low cut , Low Shelf , High Cut , High Shelf , Bell and Notch filters how can i make them Linear Phase with a max slope of 96dB/oct?
and can you explain to me were in the equation is the Q the Freq and the slope? how to make it changeable?
thank you for reading and sorry for my lack of knowledge.

Roman Thilenius's icon

i tend to ignore FIR, so i dont know much about it, but for a start...

- afaik (which usually does not mean much) it will be phase linear by definition - but it wont be very frequency linear. unless you are using a really big buffer.

- to make it 96 dB/A per ocatve, you´d simply put several of them in series, like you also would do with a biquad filter.

here is a very old implementation of a high pass with only 31 samples. it sounds terrible. you might want to try 511 for now, but in max 7 the size is no longer limited at all i think.

-110

fir-hp.jpg
jpg
woyteg's icon

For a linear Phase, the impulse response of the filter needs to be symmetrical.
A 96db/oct FIR will be very performance hungry.
Why do you need the filter to be linear phase? In many many applications this is not necessary and actually sounds bad/messes with transients..
(of course it sounds good if a company makes an EQ and say it's 'linear phase' but again, it really depends on the situation and most of the time they are not a good idea.)

woyteg's icon

some more detailed answers to romans comments:

I've been ignoring FIR

for a good reason.

– afaik (which usually does not mean much) it will be phase linear by definition – but it wont be very frequency linear. unless you are using a really big buffer.

FIR filters are not always phase linear. They can be.
IIR filters are always not phase linear.

The frequency response being 'linear', i guess you meant you can't get a nice linear passband. Yeah, I mean you can, but as you said, you need many coefficients=many delaytaps=a big buffer=poor performance to get a steep roll off.

– to make it 96 dB/A per ocatve, you´d simply put several of them in series, like you also would do with a biquad filter."

yes, you could do that, or you could do it all in one operation, which might be more efficient. Not sure, can't the filterdesign object design FIRs also? Otherwise, it's really easy in matlab...

woyteg's icon

ok one more:

nd can you explain to me were in the equation is the Q the Freq and the slope? how to make it changeable?
thank you for reading and sorry for my lack of knowledge.

so, Q is typically a feedback related parameter, wich you don't have in a FIR. But anyway, let's take slope/rolloff and frequency..
I really don't know how people do this. But you could easily do the following:
You just draw your desired frequency/amplitude response into a buffer, do the inverse fourier transform and you have the impulse response of the filter.
Or: you use a IIR, contriol the Freq/Q of this filter. Everytime the parameters change, you get the impulse response of that filter, window it (since it is potentially infinite) , make it symnmetrical and use that as your convolution kernel/FIR coeffs..

Roman Thilenius's icon

"needs to be symmetrical."

yeah, now that you remind me. well that at least saves from building the whole signal chain symetrical (as you need to do in analog hardware)

but that doubles the latency, right?

Roman Thilenius's icon

"I really don’t know how people do this."

i believe it makes the most sense to design such a filter parallel, i.e. you mix the FIR filter against the input to get a lower slope.

Timothy Place's icon

You might be able to glean a few insights from this, which just went up today:
https://cycling74.com/tutorials/crossover-filter-design-video-tutorial

The important part of the phase here is that the two signals produced have exactly the same phase as each-other. The fact that the phase is not linear only becomes a potential problem if you want to mix one of the filter output signals with the original input signal.

In this case it is quite common to linearize one of the signals using an allpass filter.

woyteg's icon

@Timothy, thats really a great video, once again!
And yes thats also my understanding, that linear phase is only important if you plan to mix with the original signal. I think in all other cases it only wastes cpu cycles. Especially if you build such a steep FIR.
Also I think its not a good idea to build the filter in parallel, dry/wet mixing with the original, as roman suggested, in order to get a variable filter steepness. Its just wasting performance if you imagine the case of a very slight filtering but having a 96db/oct filter only slightly mixed in.
"the filter kernel being symmetrical doubles the latency"
I don't think thats true. Or rather, doubles it in comparison to what? For a symmetrical kernel you get a latency of kernellength/2.
Timothy, do you mean it is possible to make a linear phase filter with an IIR in combination with a compensating allpass? I've never heard of this, can you post some link/paper/example? thank you!

Timothy Place's icon

@WOYTEG Yes, it is possible to combine an allpass with an IIR to make the phase more linear.

One cannot (obviously) remove the inherent delay, however, so it is often more effective (in the case stated here) to add the allpass to the input signal to impart to it the same phase response as the crossover.

Depending on how much you want to go crazy with this, here is an old paper on allpass design: http://www.ece.rice.edu/dsp/publicationsold/pub/designappl.pdf

It is a little challenging to sort through all of the noise when doing a web search on this subject as there is a lot of disagreement and actually hearing the results is highly dependent on the source sound material used for the testing.

Roman Thilenius's icon

six months later... i actually changed my FIR generator abstractions to take arguments for the size of the buffer, and with 511 (or actually 256 for symetrical) it sounds/works somewhat okay even when you put 4 of them in series to get a steeper slope.

to be honest, calculating the latency totally sucks for the context where i use it... it belongs to the things i hate with FIR that they are different when the samplingrate changes.

i am actually thinking of building it around biquad next time.

i *think* it should be possible to run a signal into a biquad, then reverse the signal in chunks (using a 3-windows system with tapping buffers) and run those reversed signals through 3 biquad filters... then reserve the chunks again and mix it 1:1 with the normal, non-reversed stream.

a total overkill CPU wise, it will need like 8-12 times more CPU only to make a biqad phase linear, but if i like the result it might be worth it.

granted, this still requires annoying latency calculations... but you can now change the filter frequency while it runs - without clicks - which you cant do that with buffir.

-110

Roman Thilenius's icon

hum, i wonder what the "latency" of biquad is like? one vector? no...

Roman Thilenius's icon

oh wait, i dont need to know that. you´d just match the "center" samples of n-0 and -n-0 and youre done.

woyteg's icon

Hm, roman, your idea sounds like a big adventure :)
If you really need phase linearity, I would really suggest playing around with allpasses after the biquad. I personally have always thought IIRs are never phase linear, but I believe timothy is right.
Moreover, if you really really need it, I would suggest calculating this stuff through.. Also, what you are proposing is a non-linearity, and you therefor lose all the nice tools we have for thinking about filters analytically (transfer functions and all that). So it will even by a bit tedious to test if it's working.
But I don want to discourage you!!
Regarding the latency of your biquad with the reversing: no idea :) I guess one vector/window or something?

woyteg's icon

Also:
If you take a biquad with a desired frequncy response and just put some process behind it that creates a symmetrical version of the impulse response of that filter, I am pretty sure the frequency/magnitude response will also change to something weird. But I don't know

Roman Thilenius's icon

running a signal reversed into a filter should be the same as running the signal into the "reversed" filter, "reversed" as in reversed tranfer function or reversed FIR buffer. should work for everything but FFT and slide.

so... after trying out all possible methods during the last 20 minutes... i´ve chosen finally a very _simple windowing system based on

[count~ 0 132300 0 1]

because it is easier to divide up a nonfractional number range into 3 equal spaces.

the windowing is made with > and < to the counter numbers and has a ***drumroll*** ... square form.

i will just loadbang the counter to "run" after all other things in the patch are loadbanged and we should be fine.

the reset of the tapping buffer which we read the stream reversed from now must always happen shortly before the associated window turns on - actually less than 0.33 seconds before it, because reading from a tapping buffer backwards requires _more than x2 the time of the stream. (thats also why i use 3 windows and not 2)

so there is plenty of time now where the tapout read can be started with a message.

of course in the end the single window output must be of a known sample position - not sure yet how to deal with that. but i think the main counter, which i am using like a main phasor here, should do it all.

my reverse reverb stream samplers are on the other computers so i cant continue now.

woyteg's icon

show us the patch!
(square window functions are best)

Roman Thilenius's icon

it is not a patch yet :P

funny, it is probably thej most simple windowing method i ever made, but i needed quite long until i found out what the requriements for the reverse stuff will be in this special case. before i was using a wavetable/cycle with a hanning curve followed by 33% silence, and each channel had to read from it using offset and modulo

now it is just four objects:

Max Patch
Copy patch and select New From Clipboard in Max.

Roman Thilenius's icon

boah, i have to rewrite my live reverser for that pupose; because it is worhtless when it is not 100% sampleexact.

i was able to replace the line~ to tapout~ with a count~ and create properly synced windows of known sample indexes but i failed in putting the stuff back together again because i got lost in counts, offsets, and delay times. :)

however, i´ve tried processing a file normal and reserved throught a biquad filter and sum them and it works perfectly, just like to be exspected when the transfer function is symetrical.

and i googled a bit and it seems this is not so new at all.

will post the final realtime process when it works.

Clint Moody's icon

Hey, Roman, any updates with this? I'm wanting to try to make a linear-phase filter in MaxForLive.

Roman Thilenius's icon

no, i never found the bug in the sample counting, it is still loosing one sample somewhere.

myself i use offline processing for that kind of stuff, one time forward and one time reversed through the same filter, sum it, and it is been processed symetrical. :)

Roman Thilenius's icon


also, it was close to 70 MSP objects and required simply too much CPU.

and i never found out how to calculate the max lenght. as a plug-in it would have had at least 2000 ms latency.