Chirp-Z Transform / Zoom-DFT Simulator Back
Signal Processing Simulator

Chirp-Z Transform / Zoom-DFT Simulator — High-Resolution Narrow-Band Analysis

The plain DFT splits 0..F_s/2 into N equal bins. The Chirp-Z transform (CZT) zooms into any range [f_start, f_end] with M bins. Watch two closely spaced tones become resolvable in real time.

Parameters
First frequency f_1
Hz
Second frequency f_2
Hz
CZT start frequency f_start
Hz
CZT end frequency f_end
Hz

Sampling rate F_s = 1000 Hz, N = 256 samples, CZT output M = 256 bins. Input signal: x[n] = sin(2 pi f_1 n / F_s) + sin(2 pi f_2 n / F_s).

Results
DFT resolution F_s/N (Hz)
CZT resolution (f_end-f_start)/M (Hz)
Target frequency gap Df (Hz)
Peaks resolved by CZT
DFT (top) and CZT (bottom) magnitude spectra

Top: DFT |X[k]| (blue), 0..F_s/2 in N bins. Bottom: CZT |X[k]| (red), [f_start, f_end] in M bins. Yellow lines mark f_1, f_2.

Theory & Key Formulas

The Chirp-Z transform (CZT) is a generalised DFT that samples the Z-plane along a logarithmic spiral at M points:

$$X[k] = \sum_{n=0}^{N-1} x[n]\,A^{-n}\,W^{nk}, \qquad k = 0,1,\dots,M-1$$

with $A = A_0 e^{j\theta_0}$ and $W = W_0 e^{-j\phi_0}$. For a Zoom-DFT we choose:

$$A = e^{j\,2\pi f_\text{start}/F_s}, \qquad W = e^{-j\,2\pi (f_\text{end}-f_\text{start})/(M\,F_s)}$$

which places M evenly spaced bins across $[f_\text{start}, f_\text{end}]$. The plain DFT splits $0..F_s/2$ into N bins, so the resolutions are:

$$\Delta f_\text{DFT} = \frac{F_s}{N}, \qquad \Delta f_\text{CZT} = \frac{f_\text{end}-f_\text{start}}{M}$$

With the defaults (F_s=1000, N=M=256, f_start=90, f_end=120) the DFT has 3.91 Hz/bin while the CZT has 0.117 Hz/bin — about 33x finer.

What is the Chirp-Z Transform / Zoom-DFT Simulator?

🙋
I'm trying to separate 100 Hz and 105 Hz with a DFT but I only see one peak. What's going on?
🎓
That's the resolution wall of the plain DFT. Roughly speaking, the DFT splits 0 to F_s/2 into N bins, so the resolution is $\Delta f = F_s/N$. With F_s = 1000 Hz and N = 256 that's about 3.91 Hz per bin. A 5 Hz gap is right at the edge, and once you add the leakage from windowing the two peaks blur into one. Look at the blue DFT curve at the top — there's just one bump near 100 Hz.
🙋
So I just need more samples?
🎓
In principle, yes. But to get 0.1 Hz/bin you'd need N = 10,000 — about 10 seconds of data. That's a deal-breaker for real-time analysis or non-stationary signals. Enter the chirp-Z transform: $X[k] = \sum_n x[n] A^{-n} W^{nk}$. By picking the right $A$ and $W$ you can analyse, say, only 90 to 120 Hz with 256 bins. Look at the red CZT curve below — same 256 samples, but 100 Hz and 105 Hz are now two clean peaks.
🙋
Wow, 0.117 Hz/bin. That feels like magic — there must be a catch?
🎓
Good question. The trade-off is observation time and noise rejection. With N still fixed, the record length N/F_s = 0.256 s is unchanged, so the true Rayleigh limit $1/T$ doesn't move. CZT only buys you finer bin spacing inside the chosen band. In practice that's exactly what you want for radar range-Doppler maps or modal vibration analysis where the band of interest is narrow.
🙋
How does it compare with FFT in cost?
🎓
FFT is $O(N \log N)$. A direct CZT is $O(N \cdot M)$, but Bluestein's trick re-expresses the sum as three FFTs and gives $O((N+M) \log(N+M))$ — almost as fast as a plain FFT. With N = M = 256 this tool's direct loop is plenty fast (65,536 multiply-accumulates), but for large N you'd reach for scipy.signal.czt, which uses Bluestein internally.

FAQ

An FFT computes an N-point DFT in O(N log N). A direct CZT is O(N M), but Bluestein's algorithm reformulates it as three FFTs of length L = 2^ceil(log2(N+M-1)) (two forward, one inverse), giving O(L log L). This tool uses N = M = 256 so the direct sum is fast enough, but production code (for example scipy.signal.czt) uses Bluestein's algorithm.
In radar Doppler processing or modal analysis of machines, the band of interest is usually a tiny part of the full spectrum. Reaching the same resolution with a plain FFT requires very long records, but CZT can zoom into just the relevant band. For example, analyzing 100 +/- 10 Hz with 256 bins gives 20/256 = 0.078 Hz resolution, equivalent to N = F_s/df = 12,800 samples for a plain DFT.
Goertzel efficiently computes the DFT coefficient at a single (or a few) frequencies, costing O(N) per tone, so M tones cost O(N M). CZT is also O(N M) directly, but it computes M points along a contour on the Z-plane in one shot and is suited to dense neighbouring frequencies. Goertzel is preferred for sparse tones such as DTMF detection; CZT is preferred for full zoom spectra.
The CZT bin width is (f_end - f_start)/M, which is the smallest displayed resolution. The actual accuracy depends on SNR and the analysis window: with parabolic or zero-pad interpolation you can typically estimate frequency to about 1/10 of a bin. With the default 30 Hz band over 256 bins (0.117 Hz/bin), interpolation can reach roughly 0.01 Hz frequency estimation.

Real-world applications

High-resolution Doppler analysis in radar and sonar: in pulse-Doppler radar, the Doppler band that contains target velocities is usually a tiny part of the full spectrum. CZT zooms into that Doppler band with high resolution, allowing closely spaced targets (formation aircraft, weather echoes) to be resolved. The same idea drives medical Doppler ultrasound and weather wind retrievals.

Modal analysis and structural health monitoring: bearing-fault detection in rotating machinery and ambient-vibration testing of bridges and buildings rely on tracking small shifts in natural frequencies (signs of damage or material aging). Zooming into a narrow modal band with CZT delivers 0.01 Hz frequency tracking, dramatically improving the sensitivity of structural health monitoring (SHM) systems.

Carrier-frequency estimation in communications: satellite links and narrow-band IoT (LoRa, NB-IoT) need to compensate small carrier offsets caused by Doppler shift or oscillator drift. A high-resolution CZT around the expected carrier improves the tracking loop of automatic frequency control (AFC) and helps the receiver stay locked.

Acoustic and musical-instrument analysis: the timbre of an instrument or the texture of a singing voice depends on small frequency variations of each harmonic (vibrato, chorus). Zooming around each harmonic with CZT exposes micro-modulations invisible to a plain FFT, which is useful for instrument design, voice synthesis and audio quality evaluation.

Common misconceptions and caveats

The most common misconception is that CZT can resolve arbitrarily close tones. CZT only improves the bin spacing (display resolution); it does not change the intrinsic frequency-resolving power of the signal, which is set by the observation time $T = N/F_s$ via the Rayleigh limit $\Delta f_R = 1/T$. With this tool's defaults that's $1/0.256 \approx 3.9$ Hz. A 5 Hz gap is barely resolvable; if you push f_2 down to 102 Hz you'll see the CZT peaks merge into one — finer bins do not help.

The second misconception is that CZT is always faster than FFT. A direct CZT is $O(N \cdot M)$, so with N = M = 8192 you face 67,108,864 multiply-accumulates versus about 106,496 for an FFT — roughly 600x slower. CZT is competitive only via Bluestein's reformulation, which gives $O((N+M) \log(N+M))$. This tool implements the direct sum for clarity, but real applications should call scipy.signal.czt or a hardware CZT IP core.

Finally, do not assume that CZT magnitude bins can be compared directly with DFT bins. Each CZT bin sees the input through a different effective phase rotation $A^{-n}$, so the main-lobe width and side-lobe levels are not uniform across bins. To recover absolute amplitudes you need either a per-bin calibration or a window function (Hann, Hamming) on x[n] together with the standard window-correction factor. The vertical axis here is relative magnitude only, not an absolute amplitude measurement.