Introduction

Clap your hands inside an empty cathedral and listen. The single crack blooms into a long, rich decay — each wall, column and vault contributing a slightly delayed reflection. That characteristic echo tail is called the impulse response of the room, and it contains everything acoustically interesting about the space.

Now imagine you want a violin recorded in a dry studio to sound as though it were played in that cathedral. One equation achieves it: convolution. Take every sample of the dry signal and add to the output a scaled, time-shifted copy of the impulse response. The result is mathematically identical to what a microphone placed in the cathedral would have captured.

The catch? Done naively, convolution of a signal of length NN with an impulse response of length MM costs O(NM)O(N \cdot M) multiplications — for a 10-second recording at 48 kHz and a 3-second cathedral reverb tail that is roughly 1.4 billion operations. Play it in real time? Impossible.

Enter the Fast Fourier Transform. By converting both signals to the frequency domain, multiplying pointwise, and converting back, the same result arrives in O((N+M)log(N+M))O((N+M) \log (N+M)) steps. That logarithmic compression is the difference between impractical and instant, and it is why every modern reverb plugin — and most film sound stages — runs on this single algorithm.

Hear the Difference

The demo below synthesizes a short dry click and a simplified cathedral impulse response entirely in JavaScript, then convolves them using the browser's Web Audio API (which runs FFT-based convolution internally). Press the buttons to hear each sound and watch the waveform.

<!-- {{c_html_intro}} -->
<p class="hint">{{hint_para}}</p>
<div class="controls">
  <button id="btn-dry" type="button">{{btn_dry}}</button>
  <button id="btn-wet" type="button">{{btn_wet}}</button>
</div>
<div class="label-row">
  <span id="lbl-signal">{{lbl_signal}}</span>
</div>
<canvas id="canvas" width="560" height="180"></canvas>
<div class="status" id="status">{{status_ready}}</div>
/* {{c_css_intro}} */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; padding: .4rem; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .8rem; line-height: 1.45; }
.controls { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .5rem; }
button {
  font: 600 14px system-ui, sans-serif;
  padding: .45rem 1rem;
  border: 1px solid #1d3557;
  background: #1d3557;
  color: #fff;
  border-radius: 8px;
  cursor: pointer;
  transition: background .15s;
}
button:hover { background: #2a4a70; }
button.active { background: #e63946; border-color: #c92f3c; }
.label-row { font-size: .82rem; font-weight: 600; color: #555; margin-bottom: .3rem; min-height: 1.1em; }
canvas { width: 100%; max-width: 560px; height: 180px; display: block;
         border: 1px solid #cdd9e3; border-radius: 8px; background: #f7f9fb; }
.status { font-size: .9rem; font-weight: 600; margin-top: .5rem; min-height: 1.4em; color: #1d3557; }
// Code not found

Notice how the dry click is over in milliseconds while the reverb tail rings out for seconds. Every sample of that tail was produced by a single pointwise multiplication in the frequency domain — the FFT did the heavy lifting so you don't have to wait for a billion direct multiply-and-add operations.

The FFT Shortcut

The mathematics here rests on a single identity known as the Convolution Theorem:

F{xh}=F{x}F{h}\mathcal{F}\{x * h\} = \mathcal{F}\{x\} \cdot \mathcal{F}\{h\}

Convolution in the time domain equals pointwise multiplication in the frequency domain. That is remarkable because:

  • Naive convolution (the direct sum): for each of the NN output samples you sum MM terms, giving O(NM)O(N \cdot M) work. With typical audio lengths this can be billions of multiplications.
  • FFT route: transform xx and hh each in O(LlogL)O(L \log L) where L=N+M1L = N + M - 1 (the next power of two above that), multiply the LL frequency-domain coefficients pointwise in O(L)O(L), then inverse-transform in O(LlogL)O(L \log L). Total: O(LlogL)O(L \log L) — roughly O((N+M)log(N+M))O((N+M) \log (N+M)).
  • The speedup: for a 10-second signal (N480,000N \approx 480{,}000) convolved with a 3-second IR (M144,000M \approx 144{,}000), the naive approach needs 6.9×1010\approx 6.9 \times 10^{10} operations; the FFT route needs 1.2×107\approx 1.2 \times 10^7 — roughly 5700 times faster.

The fast Fourier transform itself was published by Cooley and Tukey in 1965, though Gauss knew a version two centuries earlier. It computes the Discrete Fourier Transform of length LL in O(LlogL)O(L \log L) by recursively splitting the problem into two half-size DFTs — the classic divide-and-conquer structure that makes the logarithm appear.

In practice, real-time reverb plugins use partitioned convolution: the impulse response is split into short blocks and each block is convolved with a matching segment of the live audio stream, keeping latency below a single buffer at roughly 256 samples (~5 ms at 48 kHz) while still paying only the FFT cost per block.

Where It Matters

Convolution is one of the most ubiquitous operations in computing, and the FFT shortcut matters wherever it appears:

  • Audio production: every reverb, chorus and echo plugin in a digital audio workstation uses FFT convolution. Film and game audio pipelines capture impulse responses of real spaces — concert halls, car interiors, church naves — and stamp them onto entirely synthetic sounds.
  • Image processing: a Gaussian blur, a sharpening kernel or an edge detector applied to a photograph is a 2-D convolution. For large images and large kernels the FFT version dominates; it is the engine inside camera RAW processors and medical imaging software.
  • Polynomial and big-integer multiplication: multiplying two degree-nn polynomials naively costs O(n2)O(n^2); via FFT it costs O(nlogn)O(n \log n). The same trick makes fast multiplication of very large integers possible — the method used in modern arbitrary-precision libraries.
  • Cross-correlation and matched filtering: radar, sonar and MRI scanners all detect a known pattern by cross-correlating the received signal with a template. FFT makes that feasible in real time.
  • N-body and gravitational simulation: particle simulations approximate long-range forces on a grid and then convolve with a gravitational kernel — again, FFT does the heavy work.

The recurring theme is the same: whenever you need to "slide one signal over another and measure their overlap at each position," you are computing a convolution, and the FFT makes it tractable.

Conclusion

A single mathematical identity — convolution in the time domain equals multiplication in the frequency domain — turns a calculation that would take seconds of CPU time per audio frame into one that finishes in microseconds. That is the entire story of convolution reverb, and it is a perfect illustration of a theme that runs through all of fast multiplication and signal processing: the right representation can make the impossible routine.

Cooley and Tukey published their FFT algorithm in 1965. Within a decade it had transformed radar processing, seismic analysis and telecommunications. Today it runs inside your headphones every time a reverb plugin breathes life into a dry studio recording — silently placing violins in cathedrals, drums in caves and voices in spaces that exist only as a few seconds of recorded silence after a hand-clap.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/fft-convolution-reverb/Content licensed under CC BY-NC 4.0.