My son decided to try implementing a loudness sensor on the KL25Z board—last night he designed a circuit to interface an electret microphone to the A-to-D on the KL25Z, wired it up, wrote a small test program, and got an LED to be controlled by the loudness on the microphone. He still needs to adjust the gain of his amplifier (the sensitivity was too low) and improve his loudness detection algorithm. Currently the system only responds to very loud noises, but he’d like it to be able to pick out the beat in music even if the music is being played fairly softly.
I think that the best way to do what he wants is with digital filters (and some non-linear computations, like absolute value or squaring), but he doesn’t have any filter theory. I’m going to try writing a few blog posts to cover the basics of implementing some simple digital filters, so that he can try out his ideas.
This post is going to cover the fundamental mathematical tool underlying most digital signal processing: the z-transform (which is related to the Laplace and Fourier transforms in continuous signal processing).
If we have a semi-infinite sequence of numbers, , then the z-transform of the sequence is . For example, for the constant sequence , the z-transform is . For the sinusoidal function with angular frequency radians per sample, amplitude A, and phase , , the z-transform is .
The z-transform is a linear transform—that is, if we take any two sequences and with z-transforms and , then the z-transform of is .
One thing that is cool about z-transforms is that they can easily represent what happens if we delay a signal. Consider the two sequences and . If the z-transform of the first sequences is , then the z-transform of the second sequence is just .
A linear filter consists just of multiplications by constants, delay elements, and additions. The simplest filters (mathematically) are finite-impulse response filters:
The output is computed as , and the z-transform is . We can simplify this to , a simple polynomial in . The function is known as the transfer function of the filter. The transfer function is sometimes written as .
The impulse response of a filter is the output it provides when the input is 1 for the first sample and 0 thereafter. The z-transform of an impulse is the constant function 1, so the z-transform of the impulse response of a filter is just the transfer function for the filter. For the FIR filter in the picture above, the impulse response is . Because the response is zero after a while, this is a finite impulse response.
When we are designing or analyzing filters, we often want to think about what they do to sinusoids, since we know that adding, multiplying, and delaying sinusoids of a given frequency produces another sinusoid, but with a different amplitude and phase .
How do we convert the transfer function of the filter into the phasor ?
Note that delaying a sinusoid by 1 time unit is the same as subtracting from its phase, so multiplying by the z-transform by must be the same as multiplying by or setting .
So we can get the phasor for a given angular frequency just by plugging into the transfer function! This makes plotting the amplitude and phase response of a digital filter very simple.
Let’s look at a very simple filter averaging the last 4 samples, so , and . If we plot the gain (the absolute value of Y/X) as a function of frequency f, we can see that this is a low-pass filter:
Here is the gnuplot source code for the gain plot above:
set title "Averaging 4 adjacent samples" set key bottom left set samples 10000 set ylabel "Gain (y/x)" set logscale y set yrange [0.009:1.1] set xlabel "frequency [cycles/sample]" set logscale x set xrange [0.001:0.5] # transfer function H(z)= (1+z**(-1)+z**(-2)+z**(-3))/4 j=sqrt(-1) amplitude(omega) = abs(H(exp(j*omega))) phase(omega) = imag(log(H(exp(j*omega)))) * 180/pi # phase in degrees plot amplitude(2*pi*x) notitle
I rarely use FIR filters (other than when I’m being very lazy and just averaging a few samples for downsampling), but usually use infinite-response filters, which I’ll leave for a subsequent post.