← All tutorials

Reverberation and Dereverberation

Measure a room, then remove its tail.

On this page

1 A room is a filter 2 Echoes 3 The parts of a room response 4 How long a room rings 5 A model of the tail 6 Reading the decay off a response 7 Measuring a real room 8 Why a room is hard to undo 9 Removing the late tail 10 Reverberation in code 11 When dereverberation goes wrong 12 References

Speech recorded across a room sounds distant because the walls send back delayed copies of it. The room is one filter, its impulse response h: this page describes h, measures how long it rings, and removes its late tail from a single recording.

dry sound x room h wet sound y what a room does measure and remove 2Echoes 3Parts 4Ring time 5Tail model 6Decay curve 7Measuring 8Hard to undo 9Late tail
Figure 1. One room filter; each row opens its section.

1 A room is a filter

Clap once in a lecture hall and the microphone records the clap, then the hall answering it. That answer is the room’s impulse response h. A room is a linear time-invariant (LTI) filter: speak a word instead, and every sample of the word gets the same answer, so the room’s tail runs on after each sound. The room material on this page follows the thesis by Anushiravani (2016).

clap room h itself word room word plus tail
Figure 2. 1A clap in gives h out. 2A word comes out with h’s tail after every sample (illustrative).
A recording made in a room is the dry sound filtered by the room, plus noise.
y = x ∗ h + v
x is the dry sound, what a microphone right at the mouth would record. h is the room response from the talker to the microphone, and ∗ is convolution, so y stacks one copy of h per sample of x, as the word in Figure 2 shows. v is background noise. Every later section works on this line.

2 Echoes

The ear hears copies of a sound as separate echoes when they arrive about 50 to 100 ms apart; closer copies fuse into reverberation. A film editor matching a dubbed line to a scene’s echo can read those copies off a recording: find the peaks of the recording’s log power over time, keep each peak’s delay and height relative to the first sound, and rebuild the echo as delayed, smaller clicks. The simplest room response is exactly that, a few clicks far apart, here at a 16 kHz sampling rate.

An echo kernel is the sound plus delayed, smaller copies of it.
h[n] = δ[n] + 0.5 δ[n − D] + 0.25 δ[n − 2D]
This is a simple h for the line of section 1. δ[n] is one click at sample 0, so δ[n − D] is the same click D samples later. With D = 1,600 samples, 100 ms at 16 kHz, the kernel plays the sound, a half-height copy 100 ms later and a quarter copy at 200 ms.
1 0 ms 0.5 100 ms 0.25 200 ms h, at 16 kHz 1,600 samples apart
Figure 3. An echo kernel: three clicks, 100 ms apart (illustrative).

3 The parts of a room response

A real room sends back thousands of copies. The first to arrive is the direct sound, then a few distinct early reflections off the nearest walls, then so many reflections that they merge into a dense tail that dies away smoothly.

direct early reflections late tail time after the clap
Figure 4. 1Direct sound, early reflections, then a noise-like late tail (illustrative).

Early reflections colour the sound but help a listener understand it. The late tail smears each sound over the next, and that is the part section 9 removes.

4 How long a room rings

The standard measure of a room is how long its tail takes to fall by 60 dB, called T60. Offices sit around 0.2 to 0.6 s and large churches near 3 s (Pacheco and Seara 2008). A bigger room rings longer, because sound travels further between walls; softer walls ring shorter, because each bounce loses more. The room of Figure 5 is a 5 m by 4 m by 3 m box.

5 m 4 m 3 m V = 60 m³ S = 94 m²
average absorption aT60
0.1, bare walls1.028 s
0.20.514 s
0.4, soft walls0.257 s
Figure 5. Doubling the absorption halves T60 (illustrative room).
Sabine’s rule: volume makes a room ring, absorbing surface stops it.
T60 = 0.161 · VS · a
T60 is in seconds; 60 dB is a factor of 1,000 in amplitude (decibels). V is the volume in m³, S the total surface in m², and a the average share of sound each surface soaks up per bounce, from 0 to 1. The constant 0.161 is 24 ln 10 divided by the speed of sound, 343 m/s, with ln the natural log. With V = 60 and S = 94, the box gives 0.514 s at a = 0.2, the middle row of Figure 5. The rule ignores temperature, furniture and frequency.

The direct sound weakens with distance, 6 dB per doubling, while the room’s tail fills the space at about the same level everywhere. Somewhere the two are equal: that distance is the critical distance dc.

+10 0 −10 0.25 0.5 1 2 4 m +7.8 +1.8 −4.2 −10.2 room direct dc = 0.616 m
Figure 6. 1Past dc the room is louder than the direct sound (same room, a = 0.2).
How far from the talker the room takes over.
dc = 0.057 · √VT60
dc is in metres, V in m³ and T60 in seconds. The constant 0.057 comes from Sabine’s 0.161 and the way the direct sound spreads over a sphere. The room of Figure 5 gives dc = 0.616 m. Inside dc the direct sound is louder; beyond it the microphone hears mostly room. A bigger room pushes dc out, a longer T60 pulls it in. The form assumes a talker that sends sound equally in all directions. Section 8 uses it: a microphone inside dc is the cheapest fix.

5 A model of the tail

The dense tail looks like noise, and it falls by the same number of decibels every second. Polack’s model writes it as exactly that: white noise, whose power is spread evenly over frequency, under a falling exponential. Take T60 = 0.5 s at fs = 16 kHz: the envelope falls 30 dB in 0.25 s and 60 dB in 0.5 s.

sample ntimeenvelope
00 s1, 0 dB
4,0000.25 s0.032, −30 dB
8,0000.5 s0.001, −60 dB
Figure 7. The envelope of a 0.5 s tail at 16 kHz (illustrative).
A room tail is Gaussian white noise that fades at a fixed rate.
h[n] = b[n] · e−ζn
b[n] is Gaussian white noise, a fresh bell-curve draw per sample. The exponential is the envelope in Figure 7: it multiplies the amplitude by the same factor every sample. Only the decay ζ carries the room.
ζ = 3 ln 10T60 · fs
ζ is the decay per sample. At n = T60 · fs the exponent is 3 ln 10, so the envelope is 10−3 = 0.001, −60 dB. For the example, T60 · fs = 8,000 samples gives ζ = 8.63 × 10−4 per sample.

Real tails die faster at high frequencies, where air and soft surfaces absorb more, so T60 is usually given per frequency band. Simulators that need the early reflections too place mirror images of the talker behind each wall, the image method of Allen and Berkley (1979).

6 Reading the decay off a response

A measured tail is too noisy to read a slope off directly. Schroeder’s trick is to add up, at each sample, all the energy still to come. Take an illustrative envelope sampled every 50 ms, 1, 0.5, 0.25 and 0.125: the energies are their squares, and the sums from each time to the end fall close to a straight line in dB (the last step bends because the sum stops).

energy (envelope squared) decay curve, dB 1 0 0.25 50 0.06 100 0.02 150 0 50 100 150 0 −6.1 −12.3 −19.3 time in ms
Figure 8. 1Summing from each time to the end gives a near-straight line in dB (illustrative).
Turn a noisy tail into a straight line, then read T60 off its slope.
EDC[n] = Σm ≥ n h[m]²
The energy decay curve (EDC) at sample n is the energy still to come, shown in dB relative to its start. Summing smooths the noise in b[n] away. In Figure 8 the sums are 1.33 at 0 ms and 0.33 at 50 ms, a drop of 6.1 dB.
T60 = 60 dBdecay rate in dB/s
The slope turned into a time. The first steps of Figure 8 fall about 6 dB per 50 ms, which is 120 dB per second, so 60 dB takes 0.5 s.
T60 ≈ 2 · T30
A real recording rarely has 60 dB of range above its noise, so ISO 3382, the international standard for measuring rooms, fits a least-squares line (Linear Regression, section 2.3) from −5 to −35 dB. T30 is the time that line takes to fall those 30 dB, and doubling it gives T60. On a clean 0.5 s tail the fit gives 0.50 s.

Background noise under a tail adds energy that never fades, so the EDC flattens onto a noise floor. Where that floor sits above −60 dB, the curve never reaches −60 dB, which is why the fit stops at −35 dB.

0.5 s
none

Figure 9. 1The fit band, doubled, reads T60 until a near noise floor bends the fit over 5% long (simulated tail).

7 Measuring a real room

To measure h, play a click and record. A popped balloon is the classic click, but the thesis finds its “dynamic range and the frequency range … are not broad enough”, and repeated pops “vary too much”. Acousticians play a sine sweep instead, a tone that glides from low to high frequency, loud and the same every time.

recording = sweep ∗ h ∗ inverse of the sweep sweep ∗ inverse = a click h
Figure 10. Convolving with the sweep’s inverse turns the sweep into a click and leaves the room.

Because convolution order does not matter, convolving the recording with the sweep’s inverse pairs the sweep with its inverse, which leaves a click, and a click convolved with h is h itself (Figure 10). The loudspeaker and microphone add their own responses, so flat devices are used or their responses are removed by deconvolution. Measured responses are shared in databases such as the Aachen Impulse Response (AIR) database (Jeub et al. 2009), so a dry sound can be placed in a real room by convolution.

8 Why a room is hard to undo

The goal is the dry x from one wet recording y. Inverting h directly fails for three reasons. A room response is usually not minimum phase, meaning a response whose inverse is both stable and causal, so its exact inverse needs future samples or grows without bound. Frequencies where the room nearly cancels itself blow up the noise when divided. And Wiener deconvolution needs h, which one recording does not give.

The first fix is position: a microphone inside dc (section 4) records more talker than room. When that is not possible, the methods of Figure 11 remain.

MethodWhat is reported
Wiener deconvolution, divides out a known hneeds h; useful only on the room’s minimum-phase part (The Wiener Filter, section 6)
Beamforming, several microphones aimed at the talkerused in hearing aids and headsets
Per-band noise gate, mutes a band once it falls quietworks on drums, fails on speech, can pump (audible level surges)
Complex cepstrum, splits room from voice in the log spectrum“little use in practical cases”
Linear prediction residual, what a speech predictor missessame problem as the cepstrum
Non-negative matrix factorization (NMF) with a room modellearns the room per band (NMF, section 7.4)
Late-tail spectral subtractionone microphone, needs T60; tested at 0.34 to 1.7 s (section 9)
Figure 11. Only one-microphone methods that need no h fit a single recording; rows 2 to 5 follow the thesis.

9 Removing the late tail

Lebart, Boucher and Denbigh (2001) treat the late tail as noise that can be predicted. In each frequency bin of the short-time Fourier transform (STFT), the tail now is whatever was in that bin a moment ago, faded by the room’s decay. They tested one microphone on rooms with T60 from 0.34 to 1.7 s and reported large gains for a speech recognizer.

Take T60 = 0.5 s and a split Td = 40 ms between early and late. In 40 ms the power falls to 0.331 of itself, −4.80 dB. An illustrative bin that held power 2.0 then is predicted to hold 0.662 of late tail now.

The late tail now is the room’s decay applied to what the bin held a moment ago.
Δ = 3 ln 10T60
Δ is the decay per second, the ζ of section 5 times fs. T60 = 0.5 s gives Δ = 13.8 per second.
Plate[t] = e−2ΔTd · Py[t − Td]
Py[t] is the reverberant power in one STFT bin of the frame at time t; every line here holds bin by bin. Td is the early and late split in seconds. The 2 is there because power is amplitude squared. With Td = 40 ms the factor is 0.331, so 2.0 earlier predicts 0.662 now.
Spectral subtraction with the late tail as the noise, floored.
G[t] = max(1 − Plate[t]Py[t], β)
G is the power gain for the bin: the share that is not late tail. β, a small floor, plays the role it plays in spectral subtraction: no bin drops to an empty hole. This page uses β = 0.1, a teaching value. With 1.0 now and 0.662 predicted late, G = 0.338. The bin keeps its phase, the timing part of each STFT value, unchanged.
40 ms

Plate[t] = e−2ΔTd · Py[t − Td]
The late tail in each bin: the power Td ago, faded by the room.
G[t] = max(1 − Plate[t]Py[t], β)
The floored gain in each bin, with β = 0.1.
Pkept[t] = G[t] · Py[t]
Pkept is the power each bin keeps; its phase is unchanged.

Figure 12. 1Bin 3 was loudest Td ago, so no bin loses more; bin 2 keeps the most (illustrative powers).

KnobRaise itLower it
T60, known or estimated (section 6)removes more tailleaves more tail
Td, commonly 40 msleaves more early reflectionsstarts removing reflections that help a listener
β, no single defaultmore tail, less musical noiseless tail, more musical noise
Figure 13. The three settings and what each one trades.

Late-tail removal runs frame by frame and causally, in front of a speech recognizer or as offline cleanup. The paper used 128-point Hamming frames with 75% overlap, zero-padded to 256. On top of the STFT it costs one exponential factor per recording and one division per bin per frame.

10 Reverberation in code

A simulated room from section 5, a stand-in dry sound through it, and T60 read back with the T30 fit.

import numpy as np, scipy.signal as sps

fs, t60 = 16000, 0.5
n = np.arange(int(1.2 * t60 * fs))
zeta = 3 * np.log(10) / (t60 * fs)
h = np.random.default_rng(0).standard_normal(n.size) * np.exp(-zeta * n)

dry = np.random.default_rng(1).standard_normal(fs)
wet = sps.fftconvolve(dry, h)

energy = np.cumsum(h[::-1] ** 2)[::-1]
edc_db = 10 * np.log10(energy / energy[0])

i5, i35 = np.argmax(edc_db <= -5), np.argmax(edc_db <= -35)
slope = np.polyfit(n[i5:i35] / fs, edc_db[i5:i35], 1)[0]
t30 = -60 / slope  # 0.496
  1. 1The tail model at T60 = 0.5 s, 16 kHz: Gaussian noise times e−ζn, 0.6 s long.
  2. 2A second of white noise stands in for speech; the wet signal is x ∗ h.
  3. 3The EDC: square, sum from the end backwards, convert to dB.
  4. 4Fit a line from −5 to −35 dB and turn its slope into the time for 60 dB; it comes out at 0.496.

Late-tail removal on that wet signal, with the settings of the walkthrough. The frames are this page’s choice, not the paper’s: 512 samples with a hop of 128 samples, 8 ms, so Td is exactly 5 frames.

f, t, Y = sps.stft(wet, fs, nperseg=512, noverlap=384)
Py = np.abs(Y) ** 2
td, hop = 0.04, 512 - 384

d = round(td * fs / hop)
delta = 3 * np.log(10) / t60
p_late = np.zeros_like(Py)
p_late[:, d:] = np.exp(-2 * delta * td) * Py[:, :-d]

beta = 0.1
G = np.maximum(1 - p_late / np.maximum(Py, 1e-12), beta)
_, clean = sps.istft(np.sqrt(G) * Y, fs, nperseg=512, noverlap=384)
  1. 1The STFT of the wet signal and its power Py per bin and frame.
  2. 2The late power: the frame 5 back, times e−2ΔTd = 0.331.
  3. 3The floored gain is a power gain, so the bins are scaled by its square root before the inverse STFT.

pyroomacoustics (Scheibler et al. 2018) builds rooms with the image method. Its inverse_sabine function turns a target T60 into wall absorption, and a room’s measure_rt60 reads it back from the simulated response. Its default sampling rate is 8 kHz, so set the room to 16 kHz for this page’s numbers.

11 When dereverberation goes wrong

What you seeCauseFix
The EDC flattens before −60 dBBackground noise under the tailFit −5 to −35 dB and double (Figure 9)
Convolved audio sounds pitched or wrongKernel and recording at different sampling ratesResample first (Aliasing, section 5)
One T60 sounds wrong across the bandHighs die faster than lowsUse T60 per band (section 5)
Twinkling tones after late-tail removalMusical noise from bins pushed to the floorRaise β (Spectral Subtraction for Denoising, section 6)
Figure 14. Four common faults, with cause and fix.

Learning the room filter while a call runs is a different job, done by an echo canceller.

12 References