[sdiy] I suck at halfband filters and maths...

rburnett at richieburnett.co.uk rburnett at richieburnett.co.uk
Thu May 17 16:45:51 CEST 2018

```Is this just a thought exercise or is it required for a particular
application?

This isn't how *I* personally would make a half-band filter.  They are
usually done with FIR filters if the ultimate aim of the game is to drop
the sample rate down (decimation.)

FIR has a number of advantages here over IIR here:  It is inherently
stable (even with coefficient rounding on your low-end micro,) it has
linear phase response, and you don't need to calculate the output
samples that you will be throwing away later in the decimating process.

So if I was designing a half-band filter for a decimator I would design
an FIR using MATLAB, Octave, Remez Exchange (Parks/McClellan), whatever,
to meet the desired in-band ripple, transition-band width, and stop-band
attenuation requirements first.  Then run the input audio through this
FIR filter, only calculating the summations for the output samples that
I actually want to use in the process that follows.

You could do it with an IIR filter, but you would have to cascade quite
a few IIR biquad stages and head towards something like a Chebyshev or
Elliptic overall response to get a nice sharp half-band filter response
though.

-Richie,

On 2018-05-16 22:38, Gordonjcp wrote:
> ... which is why I'd like some assumptions checked.
>
> If I oversample something, say generating a waveform at twice the
> desired frequency, I can filter it to 1/4 of the sample rate ensuring
> that there's little-to-no energy above the "new" Nyquist frequency.  In
> a microcontroller that's as arithmetic-impaired as I am, I might want
> to do that using integers.
>
> If I don't mind the performance of the filter sucking a bit I can use a
> biquad and set its Q to be 0.5 - rather more round-shouldered than
> Butterworth - and by following RBJ's excellent cookbook something a bit
> useful shows up:
>
> w0 = 2 pi f0 / Fs = 6.28*12000/48000 = 1.57, give or take
> alpha = sin(w0) / (2*Q) = 0.9999 (or so) / (2* 0.5)
>
> and thus:
> a0 = 1 + alpha = 2 or thereabouts,
> a1 = -2 cos(w0) = 0, near as dammit
> a2 = 1 - alpha = 0 again
>
> b0 = (1-cos(w0))/2 = 0.5
> b1 = 1-cos(w0) = 1
>
> Normalising by dividing by a0, and we get
>
> b0 = 0.25
> b1 = 0.5
> b2 = b0
>
> so, using direct form 2, the equation for each sample would be:
>
> y = 0.25x + 0.5xd + 0.25xdd
>
> (where xd and xdd are the delay terms, because I can't figure out how
> to
> type superscripted -1 and -2 to indicate the unit delays on this
> keyboard)
>
> This does actually appear to roll off not too badly with for certain
> waveforms (like synth saw and squares that have been generated with a
> bit of bandlimiting) an acceptable attenuation of out-of-band stuff.
>
> Now, for the clever bit, that's a bit too clever for me.
>
> Looking at that I reckon it ought to be possible to add a third delay
> and then work out two input samples into a single output sample at the
> same time.  I need to sit down properly and have a play and try and
> remember enough high-school algebra to make it work.
>
> Does this make enough sense to anyone else that they can either tell me
> if I'm along the right lines, or if I've made some horrible fatal flaw
> in it somewhere?
```