Understanding FFT Spectral Leakage and Windowing Functions
In digital signal processing (DSP), the Fast Fourier Transform (FFT) is an indispensable tool for spectral analysis. However, a major practical issue in FFT analysis is spectral leakage. This phenomenon occurs when a signal is analyzed over a finite time window, and the signal frequency does not align perfectly with the FFT bin centers.
In this article, we will mathematically analyze the root cause of spectral leakage and explore how various windowing functions (like Hann, Hamming, and Blackman-Harris) are used to mitigate this effect.
What is Spectral Leakage?
The discrete Fourier transform (DFT) of a finite-duration signal of length is given by:
When we truncate a continuous-time signal to samples, we are implicitly multiplying the infinite signal by a rectangular window function :
In the frequency domain, multiplication in time corresponds to periodic convolution in frequency. The spectrum of a rectangular window is a Dirichlet kernel (often approximated by a Sinc function):
The sidelobes of this Sinc function have relatively high amplitudes. The first sidelobe is only about below the main lobe. If the input signal contains a frequency component that does not correspond to an exact integer number of cycles in the observation window, the energy of that component leaks into the sidelobes of , masking smaller nearby signals.
Windowing Functions
To reduce spectral leakage, we apply a non-rectangular window function to the signal before computing the FFT. Good window functions taper smoothly to zero at the boundaries, which reduces the amplitude of the sidelobes in the frequency domain at the cost of widening the main lobe.
Window Characteristics
Rectangular Hann / Hamming
+-----------+ .---------.
| | / \
| | / \
-+-----------+- -+-----------------+-
1. The Hann Window
The Hann window is defined as:
It has a maximum sidelobe level of , which is a significant improvement over the rectangular window.
2. The Hamming Window
The Hamming window is very similar but does not go exactly to zero at the edges:
It minimizes the peak sidelobe level to .
3. Implementing Windowing in TypeScript / JavaScript
Below is a simple implementation of windowing in TypeScript:
export function applyHannWindow(signal: number[]): number[] {
const N = signal.length;
const windowed = new Array<number>(N);
for (let n = 0; n < N; n++) {
const w = 0.5 * (1 - Math.cos((2 * Math.PI * n) / (N - 1)));
windowed[n] = signal[n] * w;
}
return windowed;
}Performance Comparison
Here is a summary of the trade-offs of common windowing functions:
| Window Type | Main Lobe Width (3dB) | Peak Sidelobe Level (dB) | Sidelobe Roll-off Rate | | :--- | :--- | :--- | :--- | | Rectangular | | | | | Hann | | | | | Hamming | | | | | Blackman | | | |
Choosing the right window depends on whether your application requires high frequency resolution (narrow main lobe) or high dynamic range (low sidelobes).