On 20 March 2013 03:48, Alexander E. Patrakov <patrakov at gmail.com> wrote: > Matthew Robbetts <wingfeathera at gmail.com> wrote: >> On 19 Mar 2013, at 18:34, "Alexander E. Patrakov" <patrakov at gmail.com> >> wrote: >> >> > 2013/3/19 Justin Chudgar <justin at justinzane.com>: >> > > I've created a module to ensure that only low frequencies are sent >> > > to devices at the end of an "lfe"/"subwoofer" channel. This module >> > > allows the user to select the master channel, the low pass cutoff >> > > frequency (aka corner freq, -3dB freq) and the number of filter >> > > poles. >> > >> > Sorry, I cannot sign off this filter implementation. >> >> The filter implementation looks fine to me. Do you mean the coefficient >> calculation? > > I don't really know, that was a blackbox test. Will look again today. Oh sorry, I thought you'd looked at the code. > >> > First, the filter currently fails the "attenuation must be 3 dB at the >> > cut-off frequency" test that all Butterworth filters must pass. >> >> [That's not a very clear way to describe things. A filter is either a >> Butterworth or it isn't, and that is determined by ts transfer function. >> Specfic aspects of its frequency response are really side-effects of its >> Butterworthiness.] > > Well, what is implemented is certainly not a Butterworth filter of Nth order with a given cut-off frequency. > >> Anyway: in what way does the filter not roll off correctly? > > I have not tested the roll-off. Only the statement about the -3 dB frequency. > >> The coefficient calculation looks to me like a quick swipe from the Audio EQ >> cookbook (I haven't verified that). Those formulae work pretty well, so >> if this filter isn't working right then presumably Justin has made a >> small error in that somewhere. > > Quite possible. Or it may be that I have misunderstood the expected result. > > Looking again at the code, in do_filter() I see a strange loop over the poles that, essentially, filters the signal through the same biquad (and not through N/2 biquads with independent history) over and over again. *sigh*, obviously. I missed that. The looping looks cute but yes, it is doing it wrong. All the filters might share coefficients, but each filter definitely needs its own biquad_data struct. > >> Justin, a relatively easy way to verify your coefficient generation is >> to use Matlab's (well, Octave's!) 'butterworth' function. This will get >> you the coefficients you need directly. >> >> >> > Second, Q=sqrt(2) is only valid for a 2nd order Butterworth filter. >> >> Well, to be clear, it *makes* it a Butterworth filter. The Q in the >> transfer function is the only thing distinguishing a Butterworth from >> any other filter you can make with a biquad. > > Higher-order Butterworth filters use more than one biquad, with different values of Q. But indeed, a 2nd order Butterworth filter takes one biquad with Q=2. > >> Although, since you want him to use a cascade of Butterowrth filters, he >> surely *should* use Q=2? > > Yes, for Butterworth filters of 2nd order. However he wrote some code that pretends (if I understood the intent correctly) to do arbitrary order lowpass Butterworth filtering with a given cut-off frequency. Ah sorry, I see what you mean. Yes, you're right. Either, the coefficient design code should be changed to the arbitrary filtering correctly (probably quite a lot more code to do this), or the the user interface should be constrained to only actually allow the user to ask for second-order Butterworth. I agree that the latter is probably more suitable. I clearly have not added very much here. Sorry for the noise!