Skip to content

Frequency-sampling design

Choose a filter's gain at the DFT frequencies, invert the DFT to get the taps, and calm the ripple with one sample in the gap.

Before this19.1 · 6 more
Chapter 19 · Lesson 2 of 4

First, the picture

Choose a filter’s gain at a few frequencies, 1 in the pass band and 0 above it, and the inverse DFT gives the taps. Watch the curve between the dots: it passes through every one and swings in between.

Pick the samples, get the taps

N_h = 33: the response at Ω_k = 2πk/33 is 1 for k = 0 to 4 and 0 from k = 5. The taps come from the inverse DFT.

pass band, worst
not yet
stop band, highest
not yet
0.00 / 13.00 s
Describe this picture

Two panels. The response panel plots Hzp(Ω)H_\text{zp}(\Omega) against Ω\Omega from 0 to π\pi rad/sample: the 17 samples at Ωk=2πk/33\Omega_k=2\pi k/33 as filled dots, with k=0k=0, k=4k=4 and k=5k=5 labelled, and the response as a solid line. The taps panel draws h[n]h[n] against the sample nn as stems with square heads. The readouts are the pass band’s worst value and the stop band’s highest, in dB; each reads “not yet” until the curve is drawn.

The clip lasts 13 s and has no control. First the dots appear one by one from k=0k=0: 1 for k=0k=0 to 4 (up to 0.24π0.24\pi) and 0 from k=5k=5 (0.30π0.30\pi). Then all 33 taps grow together, symmetric about α=16\alpha=16, with the centre one at 9/33=0.2739/33=0.273. Last, the response draws through the dots. It goes through every sample exactly and ripples between them, and the readouts end on 1.121 in the pass band and −15.9 dB in the stop band, next to the jump.

Pick the samples, get the taps

In Window-method FIR design (19.1) I started in time: take the ideal impulse response, cut it to NhN_h taps, and look at the gain that comes out. This page starts at the other end. I say what the gain should be at a few frequencies, and the inverse DFT finds the taps.

The idea comes from Sampling the spectrum (13.1). NN values of a spectrum at Ωk=2πk/N\Omega_k=2\pi k/N describe the signal repeated every NN samples. When NN is at least the signal’s length, they describe the signal itself. So if I choose NhN_h values of a gain and invert them, I get NhN_h taps whose spectrum passes through those values.

Let’s take Nh=33N_h=33, so the sample frequencies are Ωk=2πk/33\Omega_k=2\pi k/33 for k=0k=0 to 32. I want a filter with linear phase, so I choose real numbers Hzp(Ωk)H_\text{zp}(\Omega_k) for its zero-phase response from Linear-phase systems (17.3). That response is a sum of cosines, and a cosine has the same value at −Ω-\Omega as at Ω\Omega. By Frequency in discrete time (12.1), Ω33−k=2π−Ωk\Omega_{33-k}=2\pi-\Omega_k is the same frequency as −Ωk-\Omega_k, so the samples must be mirrored:

Hzp(Ω33−k)=Hzp(Ωk).H_\text{zp}(\Omega_{33-k})=H_\text{zp}(\Omega_k).

So only k=0k=0 to 16 are free: 17 numbers on the range from 0 to π\pi.

Next comes the delay. By 17.3, symmetric taps have H(ejΩ)=e−jαΩHzp(Ω)H(e^{j\Omega})=e^{-j\alpha\Omega}H_\text{zp}(\Omega) with α=(Nh−1)/2\alpha=(N_h-1)/2, which is 16 here. So the DFT values I hand to the inverse DFT are

H[k]=e−jαΩkHzp(Ωk),α=16.H[k]=e^{-j\alpha\Omega_k}H_\text{zp}(\Omega_k),\qquad \alpha=16.

The inverse DFT of The DFT (13.2) turns them into taps:

h[n]=1Nh∑k=0Nh−1H[k] ejΩkn=1Nh∑k=0Nh−1Hzp(Ωk) ejΩk(n−α).\begin{aligned} h[n]&=\frac1{N_h}\sum_{k=0}^{N_h-1}H[k]\,e^{j\Omega_kn}\\ &=\frac1{N_h}\sum_{k=0}^{N_h-1}H_\text{zp}(\Omega_k)\,e^{j\Omega_k(n-\alpha)}. \end{aligned}

Now pair each kk from 1 to 16 with its mirror 33−k33-k. The mirror has the same sample. Its arrow is ej(2π−Ωk)(n−α)=e−jΩk(n−α)e^{j(2\pi-\Omega_k)(n-\alpha)}=e^{-j\Omega_k(n-\alpha)}, because n−αn-\alpha is a whole number, and a whole number of turns changes nothing. Euler’s pair from Complex exponentials & phasors (3.4) adds the two arrows to 2cos⁡(Ωk(n−α))2\cos\big(\Omega_k(n-\alpha)\big), and the taps are

h[n]=1Nh[Hzp(0)+2∑k=116Hzp(Ωk)cos⁡(Ωk(n−α))].\begin{aligned} h[n]=\frac1{N_h}\Big[&H_\text{zp}(0)\\ &+2\sum_{k=1}^{16}H_\text{zp}(\Omega_k)\cos\big(\Omega_k(n-\alpha)\big)\Big]. \end{aligned}

Every term is real and the same at n=α+mn=\alpha+m as at n=α−mn=\alpha-m, so the taps are real and symmetric about α\alpha. By 13.1, these 33 taps have exactly the 33 spectrum samples I chose. Designing a filter this way is called frequency-sampling design.

For a first low-pass I set the samples to 1 for k=0k=0 to 4 and to 0 from k=5k=5 on. Sample 4 sits at Ω4=0.24π\Omega_4=0.24\pi and sample 5 at Ω5=0.30π\Omega_5=0.30\pi. One tap can be worked out by hand. At the centre, n=αn=\alpha, every cosine is cos⁡0=1\cos0=1, so h[16]=(1+2⋅4)/33=9/33=0.273h[16]=(1+2\cdot4)/33=9/33=0.273.

Think of a rope tied to posts. At every post the rope is held at the height you chose. Between the posts it hangs however it likes. The picture at the top of the page shows the posts, the taps they give, and the rope.

Watch the curve between the dots. In the pass band it rises to 1.121 between two samples of exactly 1. Next to the jump from 1 to 0 the stop band only gets down to −15.9 dB, which is a gain of 0.16.

Why does the rope hang the way it does? Put the formula for h[n]h[n] back into the zero-phase response of 17.3 and add up over nn first. Each sample then brings along one copy of a fixed curve:

Hzp(Ω)=1Nh∑k=0Nh−1Hzp(Ωk) sin⁡(Nh(Ω−Ωk)/2)sin⁡((Ω−Ωk)/2).H_\text{zp}(\Omega)=\frac1{N_h}\sum_{k=0}^{N_h-1}H_\text{zp}(\Omega_k)\, \frac{\sin\big(N_h(\Omega-\Omega_k)/2\big)}{\sin\big((\Omega-\Omega_k)/2\big)}.

The fraction is the Dirichlet kernel of The DTFT (12.2), the periodic sinc, moved to Ωk\Omega_k. Divided by NhN_h, it is 1 at its own sample and 0 at every other one, which is why the rope is held at each post. Between the posts the kernels’ ripples add. In a long run of equal samples they nearly cancel, but at a jump from 1 to 0 nothing on the far side cancels them. So the response rings, as 19.1’s plain cut did, and the cure is not to jump.

One sample in the gap sinks the ripple

Suppose the sample at the jump, k=5k=5, is not 0 but a value between 0 and 1. The step from 1 to 0 then has a stair in the middle. I call such an in-between value a transition sample. Everything else stays as before, so the taps still come from the formula above.

The gentler step has a price. The stop band now starts one sample later, at Ω6=0.36π\Omega_6=0.36\pi, so the transition is one sample wider. Think of a ramp beside a step: it is gentler, and it takes more room.

To compare fairly, I measure every version from Ω6\Omega_6. With the transition sample at 0 the filter is the one above, and from Ω6\Omega_6 on its highest point is −20.5 dB. The −15.9 dB peak sat at 0.33π0.33\pi, before Ω6\Omega_6.

Below, the sample at k=5k=5 moves from 0 up and back down. Watch the dotted level of the stop band’s highest point as it moves.

One sample in the gap sinks the ripple

The same 33 taps, with the sample at k = 5 (0.30π) set between 0 and 1. The stop band now starts at k = 6 (0.36π).

Transition sample 0: an abrupt step from 1 to 0. The stop band, from 0.36π, peaks at −20.5 dB.

transition sample
0.00
stop band, highest
−20.5 dB
0.00 / 13.00 s
Describe this picture

Two panels. The samples panel plots Hzp(Ωk)H_\text{zp}(\Omega_k) against Ω\Omega: the 17 samples as filled dots, except the one at k=5k=5 (0.30π0.30\pi), a larger filled diamond labelled “transition sample”. The gain panel plots the gain in dB, from −80 to 5, as a solid line. A dotted vertical line at Ω6\Omega_6 (0.36π0.36\pi) is labelled “stop band from here”, and a dotted level line marks the stop band’s highest point with its value. The readouts are the transition sample and the stop band’s highest point.

The clip lasts 13 s. It starts with the transition sample at 0, an abrupt step from 1 to 0, and the stop band peaks at −20.5 dB. The sample moves to 0.5, halfway, where the peak is −29.8 dB, then down to 0.39, where it is −42.1 dB, 22 dB below the abrupt step. After the clip the diamond is a handle named “Transition sample”, from 0 to 1 in steps of 0.01, and its value reads like “0.39: −42.1 dB”. The arrow keys move it by 0.01, Page Up and Page Down by 0.1, and Home and End jump to 0 and 1. At 0, 0.5 and 0.39 the caption is the one from the clip; elsewhere it is short, like “0.25: −30.0 dB.” The value is kept in the link, as gap.t.

After the clip, drag the diamond up or down to set the transition sample yourself, or use the arrow keys. Try 0.25 and then 0.5. Both sit near −30 dB, and the best value lies between them, not at the halfway point. Then try values above 0.5: at 0.75 the stop band is back at −20.5 dB, as bad as the abrupt step, and at 1 it is −16.1 dB.

The best single value is 0.3934, which gives −42.5 dB. That is 22 dB lower than with no transition sample. The pass band pays a little too: at 0.39 it strays up to 0.051 from 1.

Two transition samples do better still. The best pair is 0.5979 at k=5k=5 and 0.1106 at k=6k=6, and the stop band, which now starts at Ω7=0.42π\Omega_7=0.42\pi, peaks at −66.7 dB. The optimum is sharp: at 0.598 and 0.111 the peak is already −65.9 dB, and at 0.60 and 0.11 it is −61.7 dB.

How are such values found? Look again at the formula for the taps. Each tap is a sum of the samples times fixed numbers, so the gain at every Ω\Omega is too. Lowering the highest stop-band gain over a few free samples is then a problem called linear programming, and that is how Rabiner, Gold and McGonegal tabulated the best transition samples in 1970.

The maths behind it · the DFT matrix

Choosing the samples and inverting is solving Fh=H\mathbf{F}\mathbf{h}=\mathbf{H} with the DFT matrix of The DFT as a matrix (13.5): NhN_h equations for NhN_h unknowns, met exactly. Because the gain between samples is linear in the free samples, finding the best transition values is a linear program.

Worked example

Let’s meet the running spec of Filter specifications (18.1). At fs=8f_s=8 kHz, the gain must stay within 1±0.051\pm0.05 from 0 to 1 kHz and at most 0.01, which is −40 dB, from 1.5 kHz to 4 kHz.

Take Nh=31N_h=31. The samples are 8000/31=258.18000/31=258.1 Hz apart, so k=0k=0 to 3 lie at 0, 258.1, 516.1 and 774.2 Hz. These are in the pass band, and each is set to 1. The next two, k=4k=4 at 1032.3 Hz and k=5k=5 at 1290.3 Hz, fall in the gap between 1 and 1.5 kHz, so they are two transition samples. From k=6k=6, at 1548.4 Hz, every sample is 0.

Optimised by linear programming, the two transition samples come out as 0.909 and 0.296. The centre tap is then a hand calculation, as before. With α=15\alpha=15 every cosine is 1 at n=15n=15, so h[15]=(1+2(3+0.909+0.296))/31=0.304h[15]=\big(1+2(3+0.909+0.296)\big)/31=0.304.

On a fine grid, the pass band stays within 0.049 of 1, against the 0.05 allowed. The stop band peaks at −40.01 dB, a gain of 0.00999 against the 0.01 allowed. So 31 taps meet the spec, but only at the limit, with 0.01 dB to spare. Even letting the pass band use the full 0.05 only reaches −40.04 dB.

Two more taps give room. With Nh=33N_h=33 the samples are 242.4 Hz apart, and the transition samples are 0.456 at 1212.1 Hz and 0.0226 at 1454.5 Hz. The pass band stays within 0.042 of 1, and the stop band peaks at −48.0 dB. Two fewer than 31, Nh=29N_h=29, cannot meet the spec: the best stop band is −34.1 dB.

Compare that with Window-method FIR design (19.1), where Kaiser’s window needed 38 taps for the same spec. Frequency sampling gets there with fewer, but it depends on where the samples land against the band edges. With Nh=35N_h=35 the stop band is back up to −40.3 dB, only just passing again, although 33 taps had 8 dB to spare.

Where you’ll meet this

Frequency sampling is the natural way to design a filter to a response that was measured or drawn by hand, such as the correction for a room or a loudspeaker. SciPy’s firwin2 takes a list of frequencies and gains and joins them by straight lines on a dense grid. It then inverts the DFT and multiplies the taps by a window, as in 19.1, to calm the ripple. Audio equalisers and biquads (20.5) returns to equalising a measured response.

The same samples also give a filter structure. A comb filter puts zeros at every Ωk\Omega_k, and one resonator per nonzero sample puts a pole back on top of its zero, as in Resonators, notches and combs (17.4). When only a few samples are nonzero, that is a cheap way to compute a narrow-band filter, and Filter banks (23.1) builds banks of them.

Here only one or two samples were free, and the rest were fixed at 1 or 0. Optimal FIR design (19.3) frees every tap at once, so that the largest error over both bands is as small as it can be, and compares every method’s shortest filter for the running spec.

The maths behind it · overfitting

A curve forced through every data point can swing wildly between them; statisticians call it overfitting, and in polynomial fitting it is Runge’s phenomenon. Frequency sampling is exact interpolation in frequency, and its ripple is the same swing. Relaxing one point, as a smoother relaxes a fit, calms it.

Reference card

QuantityFormulaNotes
Sample pointsΩk=2πk/Nh\Omega_k=2\pi k/N_hthe DFT grid of 13.1
Linear phaseH[k]=e−jαΩkHzp(Ωk)H[k]=e^{-j\alpha\Omega_k}H_\text{zp}(\Omega_k), α=(Nh−1)/2\alpha=(N_h-1)/2mirrored samples, real taps
Taps (type I)h[n]=1Nh[Hzp(0)+2∑k=1αHzp(Ωk)cos⁡(Ωk(n−α))]h[n]=\frac1{N_h}\big[H_\text{zp}(0)+2\sum_{k=1}^{\alpha}H_\text{zp}(\Omega_k)\cos(\Omega_k(n-\alpha))\big]inverse DFT
Between samplesinterpolated by the Dirichlet kernel (periodic sinc)rings at a jump
One transition sample (Nh=33N_h=33)0.39: about −42 dBabrupt: −16 to −21 dB
Two transition samples (Nh=33N_h=33)0.5979, 0.1106: −66.7 dBwider transition
Running spec31 taps, two transition samples−40.01 dB, pass within 0.049: only at the limit

End of lesson 19.2

Where to go next.

Phasorium
LibraryEvery lesson, in order

Parts

About Phasorium
Look