Back to all projects

Apr 2025 – May 2025

EE

Last edited

Resolution and Robustness of a Three-Microphone DOA System

Built a direction-of-arrival (DOA) system using three omnidirectional CMA-4544PF-W microphones arranged in an equilateral triangle. Each microphone is filtered, sampled by an MCP3201 12-bit ADC over SPI, and read by a Raspberry Pi using DMA before SFTP upload for offline analysis.

Direction estimates come from pairwise cross-correlation between channels: the lag that maximises each correlation gives the inter-microphone delay, and the three delays are combined into an angle of incidence. Systematic testing covered 0°, 90°, 110°, and 270°, with additional sweeps over microphone spacing, source distance, and background-noise conditions.

Average angular deviation was under 2° at most directions, with low standard deviation. The notable failure mode appeared at 270° and 300°, where both bias and variance jumped sharply, most likely from room reflections, finite angular resolution at small inter-mic spacing, and per-microphone gain or phase variation.

Affiliation

NTNU

Partners

Report

  • Lab report

Keywords

  • C
  • Python
  • Raspberry Pi
  • MCP3201 ADC
  • Digital Signal Processing (DSP)
  • Cross-Correlation
  • Time-Delay Estimation

Deepdive

Introduction

This project is the second lab in NTNU’s TTT4280 Sensor og instrumentering sequence and reuses the multi-ADC acquisition pipeline from the first lab: a Raspberry Pi 3B+ driving Microchip MCP3201 12-bit ADCs over a shared, DMA-bit-banged SPI bus, with an LC supply filter on the 3.3 V rail. Here the analog front-end is three CMA-4544PF-W electret microphones arranged in an equilateral triangle, and the question is no longer “how close to the quantization bound does the chain run?” but “given three time-of-arrival measurements from a handclap, how well can you recover the direction the clap came from?” The answer turns out to be: very well at most angles (sub-2° mean error, low standard deviation), badly at a couple of structural-blind-spot angles (270°270° and 300°300°), and counter-intuitively better in a moderately noisy room than in a silent one.

Problem Definition

Three omnidirectional microphones sit at known positions p1,p2,p3\vec{p}_1, \vec{p}_2, \vec{p}_3 in the same plane as an unknown sound source s\vec{s} at azimuth θ\theta. A short broadband impulse, a handclap, produces a wavefront that reaches each microphone at slightly different times, and the system samples the three microphone signals synchronously at fs=31250Hzf_s = 31\,250\,\text{Hz}. Pairwise discrete cross-correlations recover the inter-microphone lags,

rij[l]  =  n=xi[n]xj[n+l],lZ,r_{ij}[l] \;=\; \sum_{n=-\infty}^{\infty} x_i[n]\, x_j[n+l], \qquad l \in \mathbb{Z},

and the lag lij=argmaxlrij[l]l^\star_{ij} = \arg\max_l r_{ij}[l] converts directly to a time delay τij=lij/fs\tau_{ij} = l^\star_{ij} / f_s. Under the plane-wave assumption (source far enough away that the wavefront is effectively flat across the array) and with the microphones placed in an ideal equilateral triangle, the three pairwise delays close into a closed-form azimuth estimator,

θ  =  arctan ⁣(3τ21+τ31τ21,τ31,2τ32).\theta \;=\; \arctan\!\left( \sqrt{3} \cdot \frac{\tau_{21} + \tau_{31}}{\tau_{21}, \tau_{31}, 2\,\tau_{32}} \right).

The system’s angular resolution is bounded above by how many distinct integer lags are physically possible between any two microphones. With inter-mic spacing dd and speed of sound vsound=343m/sv_{\text{sound}} = 343\,\text{m/s},

nmax  =  dfsvsound,n_{\max} \;=\; \left\lfloor \frac{d \cdot f_s}{v_{\text{sound}}} \right\rfloor,

so a lag can take any integer in [nmax,+nmax][-n_{\max},\, +n_{\max}], giving 2nmax+12 n_{\max} + 1 distinct delays and therefore at most that many distinct estimable directions per pair. At d=8cmd = 8\,\text{cm} that’s 0.0831250/343=7\lfloor 0.08 \cdot 31250 / 343 \rfloor = 7 lags either side, or 1515 distinct delays; at d=4cmd = 4\,\text{cm} it drops to 3.65=3\lfloor 3.65 \rfloor = 3 either side, or 77 delays, a quantization-floor on the angle estimate before any noise or geometry is introduced.

Approach

Three-microphone DOA architecture: three CMA-4544PF microphones in an equilateral triangle feed analog signals into three MCP3201 ADCs powered through an LC supply filter; the Raspberry Pi 3B+ reads three MISO lines in parallel over a shared SPI clock and chip-select; pairwise cross-correlations between the three channels yield three time delays which feed a closed-form arctangent estimator for the source azimuth. The resolution ceiling n_max = floor(d·f_s / v_sound) is shown on the right.
End-to-end DOA pipeline. The acoustic front-end is three omnidirectional microphones in an equilateral triangle; the digital back-end reuses the multi-ADC SPI pipeline from the earlier lab and adds three pairwise cross-correlations plus a closed-form arctan\arctan estimator for the source azimuth.

The pipeline reuses every piece of the digital chain from the predecessor lab and adds an acoustic front-end, three cross-correlations, and an angle estimator. Each subsection below covers one of those additions.

Microphone Front-End

Three Murata CMA-4544PF-W electret condenser microphones, omnidirectional with a 20Hz20kHz20\,\text{Hz}{-}20\,\text{kHz} band and a specified SNR of 60dBA60\,\text{dBA}, are arranged in an equilateral triangle on a breadboard with d=8cmd = 8\,\text{cm} between centres (the reference configuration; a 4cm4\,\text{cm} variant is tested separately). Each microphone shares the same 3.3V3.3\,\text{V} rail and ground as the rest of the board and drives its own MCP3201’s IN+ input. Because every channel is referenced to the same VDD and the same VREF, an offset or gain mismatch between two mics shows up as a constant time-domain bias rather than as a varying delay, which is the property the cross-correlation depends on.

Synchronous Acquisition

The three MCP3201s share a single SPI clock and a single chip-select line, with each device’s MISO returning on its own GPIO (18, 21, 22). The pigpio-based bit-banged SPI master fires a single CS pulse, all three ADCs convert in lock-step, and the host reads the three MISO bits in the same SPI transaction. The lock-step is the load-bearing detail: any per-channel sampling jitter shows up directly as a spurious τij\tau_{ij}, and from there propagates through the arctan\arctan to a biased θ^\hat{\theta}, so anything that desynchronises the three ADCs is a noise source on the angle estimate.

Pairwise Cross-Correlation

For each pair (i,j){(1,2),(1,3),(2,3)}(i, j) \in \{(1,2), (1,3), (2,3)\}, the host computes rij[l]r_{ij}[l] over the recorded buffer and picks the lag of the maximum. Cross-correlation works best on signals with broadband content, handclaps in particular have a wide spectrum and a short temporal envelope, which produces a sharp, well-localised correlation peak and good immunity to in-band confusers. Autocorrelation of any individual channel is used as a sanity check (it must peak at l=0l = 0 by definition); a broken or desensitised mic stands out as a wide, low autocorrelation hump rather than the expected sharp spike.

Time-domain recordings of the three microphone channels around a single handclap at ground-truth 0° azimuth, alongside the three pairwise cross-correlation curves with the lag of maximum correlation marked in red on each: τ₁₂ = -0.06 ms, τ₁₃ = 0.10 ms, τ₂₃ = 0.16 ms.
Three time-domain microphone signals around a single clap (top-left) and the three pairwise cross-correlation curves with the peak lag marked in red. The numerical τ12\tau_{12}, τ13\tau_{13}, τ23\tau_{23} at the top of each correlation panel feed directly into the closed-form arctan\arctan estimator for θ^\hat{\theta}.

Angle Estimation

The three delays plug into the closed-form θ\theta above. Resolution is set entirely by nmaxn_{\max}, at d=8cmd = 8\,\text{cm}, fs=31250Hzf_s = 31\,250\,\text{Hz} the system can distinguish 1515 delays per pair, which is what gates the angle resolution. The estimator assumes (i) the array is ideally equilateral, (ii) the wavefront is planar at the array, and (iii) the room is symmetric enough that no single mic sees a substantially earlier reflection than the others. Each of these assumptions becomes a controlled variable in the experimental section: shrinking dd tests the resolution ceiling, shrinking source distance tests the plane-wave assumption, and adding broadband background noise tests the correlation robustness.

Photograph of the breadboarded three-microphone array sitting on a printed protractor disc with degrees labelled around the circumference, with the three CMA-4544PF microphones, the three MCP3201 ADCs, the signal-line bundle, and the LC supply filter annotated.
Physical build. The three microphones sit at the vertices of an equilateral triangle on a breadboard mounted over a printed protractor disc; the right half of the board carries the three MCP3201s, the LC supply filter, and the Pi Wedge that routes to the Raspberry Pi. The protractor is what defines the ground-truth angles used in the test sweep.

Results

The reference configuration was tested at twelve ground-truth azimuths spanning [0°,360°)[0°, 360°), with 99 independent handclaps per azimuth from 1.5m\approx 1.5\,\text{m} in front of the array. The mean estimate sits within 2°\approx 2° of the ground truth at most angles, with two structural blind spots: 270°270° (standard deviation 13.087°13.087°, variance 171.264°2171.264\,°^2) and 300°300° (standard deviation 10.737°10.737°, variance 115.278°2115.278\,°^2). The other ten angles all land at standard deviation 8°\leq 8°, and most at 4°\leq 4°.

Ground-truth θ\thetaMean θ^\hat{\theta}Std σ\sigmaVariance σ2\sigma^2
0°356.99°356.99°4.70°4.70°22.0622.06
30°30°28.90°28.90°3.12°3.12°9.759.75
55°55°54.19°54.19°2.25°2.25°5.075.07
90°90°87.80°87.80°3.82°3.82°14.5814.58
110°110°106.97°106.97°2.63°2.63°6.936.93
130°130°128.93°128.93°5.97°5.97°35.6835.68
160°160°160.16°160.16°7.60°7.60°57.6957.69
210°210°195.50°195.50°7.96°7.96°63.3263.32
240°240°237.43°237.43°3.68°3.68°13.5213.52
270°270°229.39°229.39°13.09°13.09°171.26171.26
300°300°296.11°296.11°10.74°10.74°115.28115.28
330°330°326.07°326.07°3.83°3.83°14.6714.67

A second batch of experiments varied one parameter at a time, all at a fixed ground-truth θ=90°\theta = 90°:

ConditionMean θ^\hat{\theta}Std σ\sigmaVariance σ2\sigma^2
Reference (d=8cmd=8\,\text{cm}, 1.5m1.5\,\text{m}, silent room)87.80°87.80°3.82°3.82°14.5814.58
d=4cmd = 4\,\text{cm} (resolution test)87.58°87.58°4.53°4.53°20.5120.51
Source at 10cm10\,\text{cm} (plane-wave test)88.61°88.61°6.59°6.59°43.4543.45
Background blue noise88.02°88.02°2.23°\mathbf{2.23°}4.99\mathbf{4.99}

Three things in this second table are worth dwelling on. First, halving dd reduces the number of distinguishable lags per pair from 1515 to 77, so the quantization on τ\tau doubles, and variance roughly doubles (14.5820.5114.58 \to 20.51), exactly the prediction from the nmaxn_{\max} formula. Second, putting the source 10cm10\,\text{cm} from the array invalidates the plane-wave assumption: wavefronts arrive curved rather than flat, the τij\tau_{ij} become non-linear in the true geometry, and variance jumps by 3×\approx 3\times. Third, and this is the counter-intuitive result, adding broadband background noise reduces variance to its lowest value across all four conditions. The noise used was blue noise, which carries more energy at high frequencies than at low; combined with the impulsive clap, this broadens the signal’s spectrum and sharpens the cross-correlation peak, since correlation peaks are tighter when the input has flat broadband content rather than a few dominant low-frequency tones. The system isn’t merely robust to broadband background noise, it’s actively helped by it.

Clap recording at ground-truth 90° azimuth captured under a continuous blue-noise background, with the three pairwise cross-correlation curves and their peak lags: τ₁₂ = -0.16 ms, τ₁₃ = -0.13 ms, τ₂₃ = 0.00 ms. The correlation peaks are visibly sharper than in the silent-room reference.
Same handclap at θ=90°\theta = 90°, recorded with continuous blue-noise background. The correlation peaks are visibly sharper than in the silent-room reference, which is the mechanism behind the lowest measured variance (σ2=4.99°2\sigma^2 = 4.99\,°^2) across all four robustness conditions.
Simulated angle estimate as a function of source distance for a true source azimuth of 20°, at two array radii (0.1 m on the left, 0.01 m on the right). Both curves converge to the true value at long range; the 0.1 m array's error blows up below roughly 0.5 m as the plane-wave assumption fails.
Simulated θ^\hat{\theta} versus source distance at a true θ=20°\theta = 20° for two array radii. Both arrays converge to the true value at long range, but the larger array’s estimate diverges sharply below 0.5m\approx 0.5\,\text{m} as wavefronts curve across the aperture, directly explaining the variance jump observed empirically at the 10cm10\,\text{cm} source-distance condition.

Future Work

The 270°270° and 300°300° blind spots are the largest open question in the reference configuration. Both directions fall in the back-half of the array, and the high variance at those angles co-occurs with several of the nine measurements landing at θ^=220.893°\hat{\theta} = 220.893°, a quantized-to-grid value rather than a noisy spread, which is the fingerprint of the resolution floor being hit rather than of stochastic noise. Two changes attack this: characterise each mic’s individual offset (one cheap calibration sweep with a known source) and subtract a per-channel bias on τij\tau_{ij} before the arctan\arctan, and either tighten the equilateral geometry or move to a four-microphone tetrahedral arrangement that breaks the directional symmetry that makes 270°270° ambiguous in the first place.

The plane-wave breakdown at short source distances is well-understood and quantified by the simulation in Figure 21, error grows sharply below 0.5m\sim 0.5\,\text{m} from the array. For applications where the source is genuinely close (e.g. a wearable, or a hand-held listener that needs to localise a speaker 50cm\leq 50\,\text{cm} away), the right fix is to replace the closed-form arctan\arctan with a near-field model that treats each τij\tau_{ij} as a function of the position s\vec{s} rather than just its azimuth, and to solve the resulting system numerically over a 2D grid. This is more compute per estimate but it’s compute the Pi has to spare in the current pipeline.

The most interesting redesign is to lean harder into the broadband-noise finding. The system already works better with blue noise present; injecting a known broadband probe signal (a chirp, a pseudo-random pulse train, or simply continuous low-level blue noise from a co-located speaker) and cross-correlating against the known reference rather than between two unknowns would convert the system from a passive impulse-localiser into an active sonar-style ranger, with all the precision benefits that come from controlling the source spectrum end-to-end. The cross-correlation machinery doesn’t change; only what’s correlated does.

Two lower-hanging fixes round out the next iteration: replace the breadboard build with a soldered PCB (the unexplained 50Hz50\,\text{Hz} knee in the supply-filter response from the predecessor lab is almost certainly a layout artefact, and shows up here as additional in-band variance), and characterise each CMA-4544PF for sensitivity and self-noise before installation, since a single under-sensitive mic broadens its own correlation peak and biases every τij\tau_{ij} it contributes to. Both of these are mechanical improvements rather than algorithmic ones, but together they are the cheapest way to drive the reference-configuration standard deviation from 4°\approx 4° toward the 2°\approx 2° floor that the resolution ceiling at d=8cmd = 8\,\text{cm} would in principle allow.