ELE-250 · Lesson 10 of 12 · 23 min

The discrete-time Fourier transform, the DFT and the FFT

Everything so far about spectra has used integrals over continuous time. The microcontroller in the pedestrian signal has none of that. It has blocks of samples, a few kilobytes of memory and a few milliseconds per block to decide how loud the street is and whether the locator tone is coming through clearly. This lesson gives the frequency-domain tools that work on samples. The discrete-time Fourier transform (DTFT) is the theory: the spectrum of an infinitely long sampled signal, and the frequency response of a digital filter. The discrete Fourier transform (DFT) is the practice: a finite sum over N samples that a computer can evaluate. The fast Fourier transform (FFT) is not a different transform but a clever algorithm that computes the DFT hundreds of times faster, and it is one of the most important algorithms in engineering.

The discrete-time Fourier transform

For a discrete-time signal x[n], the DTFT is

\[X(e^{j\Omega}) = \sum_{n=-\infty}^{\infty} x[n]\,e^{-j\Omega n}, \qquad x[n] = \frac{1}{2\pi}\int_{-\pi}^{\pi} X(e^{j\Omega})\,e^{j\Omega n}\,d\Omega\]

Ω is the discrete-time frequency in radians per sample. The DTFT is always periodic in Ω with period 2π, because e^(−j(Ω+2π)n) = e^(−jΩn) for every integer n; that is lesson 9's periodic spectrum seen from the discrete side. All the information lies in one period, usually −π to π. When x[n] comes from sampling at f_s, Ω connects to physical frequency by Ω = 2πf/f_s, so Ω = π corresponds to the Nyquist frequency f_s/2. At 8 kHz, the 880 Hz locator tone sits at Ω = 2π(880/8000) ≈ 0.691 rad per sample.

The DTFT has the same properties as the continuous transform. In particular, convolution becomes multiplication, so a digital filter's frequency response is the DTFT of its impulse response, H(e^(jΩ)) = Σh[n]e^(−jΩn). For an FIR filter this is a finite sum that can be evaluated directly.

Worked problem

Frequency response of a moving average

Daniel's four-point moving average on the tachometer has h[n] = ¼ for n = 0 to 3. Find |H(e^(jΩ))| at Ω = 0, π/4, π/2 and π.

Show solution
  1. Write the DTFT as a finite geometric series and simplify.
  2. \[H(e^{j\Omega}) = \tfrac{1}{4}\big(1 + e^{-j\Omega} + e^{-j2\Omega} + e^{-j3\Omega}\big) = \frac{1}{4}\,\frac{\sin(2\Omega)}{\sin(\Omega/2)}\,e^{-j3\Omega/2}\]
  3. Evaluate the magnitude, taking the limit 1 at Ω = 0.
  4. \[|H(e^{j0})| = 1, \quad |H(e^{j\pi/4})| = \frac{1}{4}\cdot\frac{1}{0.383} \approx 0.653\]
  5. \[|H(e^{j\pi/2})| = 0, \qquad |H(e^{j\pi})| = 0\]

Answer: The moving average passes DC with gain 1, halves the amplitude of components a little above Ω = π/4, and completely removes Ω = π/2 and Ω = π. With readings every 50 ms (20 per second), those nulls are at 5 Hz and 10 Hz, so a pump vibration that wobbles the readings at 5 Hz is cancelled exactly. The phase term e^(−j3Ω/2) is a delay of 1.5 samples, linear in Ω, so the filter does not distort the shape of slow changes.

From the DTFT to the DFT

The DTFT needs infinitely many samples and gives a function of a continuous variable, so a computer cannot evaluate it exactly. The DFT makes two compromises. It uses a block of N samples, x[0] to x[N − 1], and it evaluates the spectrum only at N equally spaced frequencies, Ω_k = 2πk/N:

\[X[k] = \sum_{n=0}^{N-1} x[n]\,e^{-j2\pi kn/N}, \qquad x[n] = \frac{1}{N}\sum_{k=0}^{N-1} X[k]\,e^{j2\pi kn/N}\]

Each X[k] is a complex number, and the index k is called a bin. Bin k corresponds to the physical frequency f_k = k·f_s/N, so the bin spacing, or frequency resolution, is Δf = f_s/N. A longer block gives finer resolution: at 8 kHz, a 256-sample block (32 ms) has bins 31.25 Hz apart, and a 1,024-sample block (128 ms) has bins 7.8 Hz apart. This is lesson 7's duration–bandwidth trade-off again: to resolve frequencies Δf apart, you must listen for at least 1/Δf seconds.

For real input, the bins above N/2 are mirror images of those below, X[N − k] = X[k]*, because they represent the negative frequencies. Bin 0 is the DC value times N, and bin N/2 is the Nyquist frequency. A single sinusoid of amplitude A that falls exactly on bin k gives |X[k]| = AN/2 and zero in every other bin below N/2, which is how a DFT-based meter converts bin values back to amplitudes.

Leakage and windows

The DFT implicitly treats its N samples as one period of a periodic signal. If the block holds a whole number of cycles of a tone, the copies join smoothly and the tone falls in one bin. If not, the joins have a jump, and the jump's energy spreads into neighbouring bins. This spreading is spectral leakage. With 256 samples at 8 kHz, the 880 Hz tone falls at bin 880/31.25 = 28.16, between bins 28 and 29, so its energy leaks across many bins and its peak reads low. Leakage can hide a weak tone next to a strong one, which matters to Amara because she wants to measure a quiet locator tone in the presence of loud traffic.

There are two remedies. If the frequency of interest is known, choose N so that it falls on a bin: with N = 400 at 8 kHz, the bins are 20 Hz apart and 880 Hz is bin 44 exactly. If not, multiply the block by a window function that tapers smoothly to zero at both ends before taking the DFT. The Hann window, w[n] = ½(1 − cos(2πn/N)), is the usual choice. It makes each tone's peak a little wider but pushes the leaked energy far down, so weak tones become visible. Zero padding, appending zeros to a block before the DFT, gives more closely spaced bins that trace the spectrum more smoothly, but it adds no real resolution, because no new information about the signal has been added.

A plot of DFT magnitude in decibels against frequency from 600 to 1200 hertz for a 256-sample block containing an 880 hertz tone. The rectangular-window spectrum has a peak near 880 hertz with high side lobes that stay above minus 40 decibels across the plot. The Hann-window spectrum has a slightly wider peak with side lobes that fall below minus 60 decibels within a few bins.
Leakage from an 880 Hz tone that falls between bins of a 256-point DFT at 8 kHz. The Hann window trades a slightly wider peak for much lower leakage.

The fast Fourier transform

Evaluating the DFT directly takes N complex multiplications for each of N bins, N² in all: about 65,000 for N = 256 and a million for N = 1,024. The fast Fourier transform, popularized by Cooley and Tukey in 1965 though its core idea goes back to Gauss, cuts that to about (N/2)log₂N. For N a power of 2, the radix-2 FFT splits the samples into even- and odd-indexed halves, computes a half-length DFT of each, and combines them with one multiplication per pair, using the fact that the exponentials e^(−j2πkn/N) repeat. Applying the split recursively gives log₂N stages of N/2 operations. For N = 1,024 that is about 5,000 multiplications instead of a million, a speed-up of 200. On Cedarline's microcontroller, a 256-point FFT takes well under a millisecond, so the noise detector can update its spectrum every block.

Fast convolution

The FFT also makes long convolutions fast. Multiplying two DFTs and transforming back gives the circular convolution of the blocks, in which the end of the result wraps around to the beginning. Padding both sequences with zeros to at least N + M − 1 samples before the FFT prevents the wrap-around, so the result equals ordinary linear convolution. For a filter with hundreds of taps, transforming, multiplying and transforming back costs far less than direct convolution, and long signals are processed block by block with methods called overlap-add and overlap-save. Audio effects such as room reverberation, whose impulse responses last seconds, are run this way.

Worked problem

Choosing the block length

Amara wants the noise detector to tell the 880 Hz locator tone apart from traffic noise within 20 Hz of it, with the tone falling exactly on a bin and the spectrum updated at least 10 times a second. Sampling is at 8 kHz. What N should she use?

Show solution
  1. Resolving components 20 Hz apart needs bins no wider than 20 Hz.
  2. \[\Delta f = \frac{f_s}{N} \le 20\ \text{Hz} \quad\Rightarrow\quad N \ge \frac{8000}{20} = 400\]
  3. With N = 400, 880 Hz falls on bin 880/20 = 44 exactly.
  4. The block lasts 400/8000 = 50 ms, so the spectrum can be updated 20 times a second.

Answer: N = 400 meets all three needs. It is not a power of 2, but FFT routines for N = 400 = 2⁴ × 5² exist; alternatively N = 512 with a Hann window gives 15.6 Hz bins and puts 880 Hz near bin 56.3, at the cost of some leakage control.

A direct DFT and a recursive radix-2 FFT agree; leakage with and without a Hann window; and a block length that puts 880 Hz exactly on a bin.
import cmath, math

def dft(x):
    N = len(x)
    return [sum(x[n] * cmath.exp(-2j * math.pi * k * n / N) for n in range(N)) for k in range(N)]

def fft(x):                                  # recursive radix-2, len(x) a power of 2
    N = len(x)
    if N == 1:
        return list(x)
    even, odd = fft(x[0::2]), fft(x[1::2])
    tw = [cmath.exp(-2j * math.pi * k / N) * odd[k] for k in range(N // 2)]
    return [even[k] + tw[k] for k in range(N // 2)] + [even[k] - tw[k] for k in range(N // 2)]

fs, N = 8000, 256
x = [math.cos(2 * math.pi * 880 * n / fs) for n in range(N)]
X1, X2 = dft(x), fft(x)
print("max |DFT - FFT| =", f"{max(abs(a - b) for a, b in zip(X1, X2)):.1e}")
print(f"multiplications: direct {N*N}, FFT about {N//2*int(math.log2(N))}")

def peak_and_far(x):
    X = fft(x)
    mag = [abs(v) for v in X[:N // 2]]
    top = max(mag)
    k = mag.index(top)
    far = max(mag[k + 8:k + 20])               # leakage 8 to 20 bins away
    return k, 20 * math.log10(far / top)

hann = [0.5 * (1 - math.cos(2 * math.pi * n / N)) for n in range(N)]
k, rect_db = peak_and_far(x)
_, hann_db = peak_and_far([a * w for a, w in zip(x, hann)])
print(f"peak in bin {k} ({k*fs/N:.1f} Hz); bin spacing {fs/N} Hz")
print(f"leakage 8-20 bins away: rectangular {rect_db:.0f} dB, Hann {hann_db:.0f} dB")

y = [math.cos(2 * math.pi * 880 * n / fs) for n in range(400)]
Y = dft(y)
print(f"N = 400: bin 44 magnitude {abs(Y[44]):.1f} (= N/2), bin 45 magnitude {abs(Y[45]):.1e}")
Output
max |DFT - FFT| = 8.7e-12
multiplications: direct 65536, FFT about 1024
peak in bin 28 (875.0 Hz); bin spacing 31.25 Hz
leakage 8-20 bins away: rectangular -35 dB, Hann -70 dB
N = 400: bin 44 magnitude 200.0 (= N/2), bin 45 magnitude 5.2e-13

The DFT and FFT agree to rounding error, and the FFT needs about 1,000 multiplications instead of 65,536. The 880 Hz tone peaks in bin 28, at 875 Hz, the nearest bin. Without a window, the leakage 8 to 20 bins away is only about 35 dB below the peak; with the Hann window it drops to about 70 dB below, so a tone thousands of times weaker could be seen beside it. In the street, that difference decides whether the noise detector can still find the quiet locator tone while a loud truck passes on a nearby frequency. The cost of the window is a peak about twice as wide and a peak value about 6 dB lower, which the firmware corrects with a fixed scale factor, so Amara applies the Hann window to every block. With N = 400, the tone lands exactly in bin 44 with magnitude N/2 = 200 and essentially nothing in the next bin, as the theory says.

Common mistakes

  • MistakeReading bin k as frequency k hertz.

    InsteadBin k is at k·f_s/N hertz; the spacing is f_s/N.

  • MistakeExpecting zero padding to separate two close tones.

    InsteadResolution is set by the length of real data, about f_s/N for N real samples; padding only interpolates the spectrum.

  • MistakeIgnoring leakage when a tone falls between bins.

    InsteadChoose N to put the tone on a bin, or apply a window such as the Hann window.

  • MistakeUsing circular convolution from FFTs as if it were linear convolution.

    InsteadZero-pad both sequences to at least N + M − 1 samples first.

  • MistakeForgetting that bins above N/2 mirror those below for real signals.

    InsteadUse bins 0 to N/2 and double the amplitude of all but DC and Nyquist when converting to sinusoid amplitudes.

Summary and key terms

  • The DTFT X(e^(jΩ)) = Σx[n]e^(−jΩn) is periodic in Ω with period 2π; Ω = 2πf/f_s.
  • A digital filter's frequency response is the DTFT of its impulse response; the moving average has nulls at multiples of f_s/M.
  • The DFT evaluates the spectrum of N samples at N bins spaced f_s/N apart; longer blocks give finer resolution.
  • Tones between bins leak into neighbours; windows reduce leakage and choosing N can place a tone on a bin.
  • The FFT computes the DFT in about (N/2)log₂N operations instead of N².
  • FFT-based convolution with zero padding computes long linear convolutions quickly.
DTFT
The discrete-time Fourier transform, a continuous, 2π-periodic spectrum of a discrete-time signal.
DFT
The discrete Fourier transform of N samples, evaluated at N equally spaced frequencies.
FFT
A family of fast algorithms for computing the DFT in about N log₂N operations.
Bin
One of the N frequency samples of a DFT, spaced f_s/N apart.
Spectral leakage
The spreading of a tone’s energy into neighbouring DFT bins when it does not complete a whole number of cycles in the block.
Window function
A taper applied to a block of samples before a DFT to reduce leakage.
Zero padding
Appending zeros to a block before a DFT to interpolate the spectrum.

Practice problems

Work each problem on paper first, then reveal the answer to check.

  1. At f_s = 48 kHz, what discrete-time frequency Ω corresponds to 12 kHz?

    Show answer

    Ω = 2π(12/48) = π/2.

  2. What is the bin spacing of a 2,048-point DFT at 44.1 kHz?

    Show answer

    About 21.5 Hz.

  3. In a 1,000-point DFT at 10 kHz, which bin holds 1.25 kHz?

    Show answer

    Bin 125.

  4. Roughly how many multiplications does a 4,096-point radix-2 FFT need?

    Show answer

    (4096/2) × 12 ≈ 24,600, versus about 16.8 million direct.

  5. Where are the nulls of an 8-point moving average at f_s = 400 Hz?

    Show answer

    At multiples of 400/8 = 50 Hz: 50, 100, 150 and 200 Hz.

  6. Two sequences of length 300 and 100 are to be convolved with FFTs. What is the minimum FFT length?

    Show answer

    399; in practice the next power of 2, 512.

Lesson quiz · 5 questions

Score 60% or more to complete this lesson.

Take the quiz