Beamforming Microphone Array
Short answer. A beamformer combines the channels of a microphone array with per-channel delays so that sound from one direction adds up coherently and sound from other directions does not. Delay-and-sum with M microphones gives up to 10 log10(M) dB of gain against uncorrelated noise — 6 dB for four microphones, 9 dB for eight — but only for a source in the steering direction, and only while the spacing stays under half a wavelength. Above that spacing the array has grating lobes and picks up directions you did not intend.
How to do it
The geometry, and the delay you are compensating
For a linear array with spacing d and a source at angle theta from broadside, the sound reaches adjacent microphones with a time difference of tau = d sin(theta) / c, with c about 343 m/s. Beamforming is applying that delay to each channel, or its negative, before summing. Nothing more complicated is happening in a delay-and-sum beamformer, and the whole design lives in d and M.
Spacing sets the frequency range. To avoid spatial aliasing — the array equivalent of the sampling theorem — d must be no more than half the wavelength of the highest frequency you care about. At 8 kHz the wavelength is 4.3 cm, so d must be 2.1 cm or less. That is why far-field arrays use 2 to 4 cm spacing, and why a widely spaced array is only usable at low frequencies. A 2 cm spacing is unambiguous up to 8.6 kHz, which covers speech.
Why the gain is 10 log10(M), and when it is not
Sum M channels coherently for a target in the steering direction and the target amplitude grows by a factor of M. Sum M channels of noise that is uncorrelated between microphones and the noise power grows by a factor of M, so the amplitude grows by sqrt(M). The ratio improves by sqrt(M) in amplitude, which is 10 log10(M) in power: 6.0 dB for four microphones, 9.0 dB for eight, 12.0 dB for sixteen.
The assumption is uncorrelated noise, which covers sensor self-noise and some diffuse room noise. It does not cover a coherent interferer: a loudspeaker playing in the room reaches every microphone with a fixed phase relationship, and the array treats it exactly as it treats the target. Against a fully coherent noise source in the steering direction, the array gain is 0 dB. Against one off-axis, the gain comes from the directional response rather than from the microphone count.
The off-axis response is what you are actually buying
The gain at the steering angle is the easy number and it is nearly the same for every geometry. The number that matters is the response as a function of angle, because that is what suppresses the interfering talker sitting to the side. Two summary figures: the directivity index, which is the on-axis response divided by the average over all directions (roughly 6 dB for a four-microphone endfire array, 10 to 15 dB for a larger two-dimensional one), and the depth and width of the first null.
For a linear array at 4 kHz with 2 cm spacing, a source at 90 degrees from broadside is cancelled almost completely — the four channels arrive at 0, 84, 168, and 252 degrees of phase, which sums to nearly zero. That is a real and useful property, and it is also why the array has to be steered: the null is only where the geometry puts it, not wherever you need it.
The failure modes that dominate the arithmetic
Microphone mismatch. The theoretical null depth is infinite; a 1 dB level difference between channels limits it to about 15 to 20 dB, and a phase mismatch does the same. Calibration matters more than the beamformer math, and an uncalibrated consumer array cannot reach its own theoretical response.
Reflections. The delay model assumes a single direct path per source. In a room, the reflections arrive from other directions with their own delays, and the array cannot null them all. Measured directivity in a real room is typically 5 to 10 dB shallower than the simulation, which is why array designs are validated in an anechoic chamber and then re-validated in the target room.
Two sources at the same angle. A beamformer has no way to separate them, because separation comes from the direction difference and there is none. Two talkers on the same side of the array are a source-separation problem, not a beamforming problem, and no amount of microphone count fixes it.
What to specify when you buy array data
Array geometry, microphone count, and spacing — because they determine the usable frequency range, and an array specified without a spacing cannot be evaluated. The calibration method and the residual gain and phase mismatch between channels, because that is what sets the achievable null depth. Whether the channels are sample-synchronized, since an unknown inter-channel delay of even a few samples destroys the response at high frequencies.
And the room, for the same reason as the previous page: a beamformer trained on simulated anechoic array data has never seen a reflection, and reflections are most of what a real array records. A dataset of multi-channel recordings with a stated geometry, a stated calibration, and a real room is a different product from a set of simulated channels.
Code
A delay-and-sum beamformer over a synthetic four-microphone linear array, printing the signal gain, the noise gain, and the resulting SNR gain as the source moves off axis.
import numpy as np
C, SR, D, M = 343.0, 16000, 0.02, 4
t = np.arange(SR) / SR
FREQ = np.fft.rfftfreq(t.size, 1.0 / SR)
rng = np.random.default_rng(0)
def array_of(sig, theta_deg):
"""Exact per-mic copy of sig, delayed by the propagation time for a linear array."""
tau = D * np.sin(np.deg2rad(theta_deg)) / C
F = np.fft.rfft(sig)
return np.stack([np.fft.irfft(F * np.exp(-2j * np.pi * FREQ * m * tau), n=t.size)
for m in range(M)])
def beamform(X, steer_deg):
"""Delay-and-sum steered to steer_deg, with the delays applied in frequency."""
tau = D * np.sin(np.deg2rad(steer_deg)) / C
F = np.fft.rfft(X, axis=1)
return np.fft.irfft(F * np.exp(2j * np.pi * FREQ * tau * np.arange(M)[:, None]),
n=X.shape[1], axis=1).mean(axis=0)
sig = np.sin(2 * np.pi * 4000 * t)
noise = rng.normal(0, 1, (M, t.size))
sig_in = (sig ** 2).mean() # signal power at a single microphone
noise_in = (noise[0] ** 2).mean() # noise power at a single microphone
print('array: %d mics, %.1f cm spacing, %.1f cm aperture' % (M, D * 100, (M - 1) * D * 100))
print('wavelength at 4 kHz: %.1f cm; unambiguous up to %.0f Hz with this spacing'
% (C / 4000 * 100, C / (2 * D)))
print('maximum array gain against uncorrelated noise: %.1f dB' % (10 * np.log10(M)))
print()
print('source signal noise SNR gain')
print('angle gain gain over one mic')
for deg in (0, 30, 60, 90):
sig_out = (beamform(array_of(sig, deg), 0) ** 2).mean()
noise_out = (beamform(noise, 0) ** 2).mean()
print('%4d deg %+6.1f dB %+6.1f dB %+6.1f dB'
% (deg, 10 * np.log10(sig_out / sig_in),
10 * np.log10(noise_in / noise_out),
10 * np.log10((sig_out / noise_out) / (sig_in / noise_in)))) - pip install numpy. The array is simulated, so no audio files and no calibration are needed.
- Expected output: the noise gain is +6.0 dB at every angle, because uncorrelated noise does not depend on where the source is. The signal gain is 0.0 dB at 0 degrees and falls to roughly -19 dB at 90 degrees, so the SNR gain runs from about +6 dB to about -13 dB.
- The delays are applied in the frequency domain rather than by interpolating the waveform, so the fractional-sample delays are exact and the null at 90 degrees is as deep as the arithmetic allows.
- Set D to 0.10 instead of 0.02 and rerun: the array is now ambiguous above 1.7 kHz, and the response at 4 kHz develops grating lobes that put the source back into the output at angles where it should be suppressed.
Where this goes wrong
Choosing the spacing without checking the aliasing limit
A spacing above half the shortest wavelength produces grating lobes: directions other than the intended one that pass through at full gain, so the array picks up an interferer it was supposed to reject. The limit is 343 / (2 x d) Hz — 8.6 kHz at 2 cm, 1.7 kHz at 10 cm. Wide spacing is not better; it just moves the usable band down.
Assuming the theoretical array gain against a coherent interferer
The 10 log10(M) figure requires noise that is uncorrelated between microphones. A loudspeaker, a competing talker in the same room, or a fan heard by every microphone arrives coherently and gains nothing from the array. In a small room with one dominant interferer, the measured array gain is often close to 0 dB, and the improvement has to come from the directional response instead.
Skipping calibration
A 1 dB gain difference or a few degrees of phase mismatch between channels limits the achievable null depth to 15 to 20 dB, no matter what the geometry says. Consumer arrays are rarely calibrated channel to channel, so a beamformer tuned on a calibrated research array will underperform on the deployment hardware. Ask for the measured channel mismatch, not the nominal specification.
Applying a single-channel enhancement stage before the beamformer
Running dereverberation or spectral gating on each channel independently destroys the phase relationships between channels, which is the only information a beamformer has. The pipeline still runs and still produces plausible audio, but the spatial gain is gone. If the array matters, keep the multichannel stage multichannel until after the beamformer.
Tuning the steering angle on the training data
Steering to the average talker position in your corpus looks reasonable and produces an array that is wrong for every individual recording. The steering angle is a per-recording decision, usually from a direction-of-arrival estimate or from the geometry of the deployment. A fixed angle baked into a trained model does not transfer to a different room layout.
When to buy the data instead of building the pipeline
Buy when you need multi-channel recordings with a known geometry and a stated calibration, because that combination is what makes the data usable for beamforming and it cannot be recovered from a stereo mix. Buy when you need real rooms rather than simulated ones, since reflections are what a real array records and the difference between simulated and measured directivity is 5 to 10 dB. Buy when you need array data at the geometry of your deployment — the microphone count and spacing have to match, or the beamformer you train is for a different instrument. If you are validating a delay-and-sum design or estimating the achievable directivity for a geometry you are still choosing, simulate it; the code above is the whole calculation and it costs nothing.
More technical reference
-
Neural Speech Codec
neural speech codec
-
Word Error Rate (WER)
word error rate
-
Character Error Rate (CER)
character error rate
-
Speaker Diarization
speaker diarization
-
Forced Alignment
forced alignment
-
Voice Activity Detection (VAD)
voice activity detection
Need data for Beamforming Microphone Array?
Tell us the language, the hours, and what the data needs to look like. You will get a real number and a real timeline — not a range. If we cannot source it well, we will tell you that instead.
- Pilot batch before the full run, so problems surface early.
- Consent documentation delivered with the data.
- No medical or clinical data. No recorded telephone calls.