Project Details – Acoustic Parabola with NLMS Filtering on ESP32
This project implements a real-time NLMS adaptive filter on an ESP32, using a 3D-printed acoustic parabola. The goal is to improve the signal-to-noise ratio (SNR) of a microphone placed at the focus of the parabola by dynamically subtracting ambient noise measured by a second microphone placed outside the focal area.
The entire data processing pipeline is fully digital, from input to output.
Goal
The idea is to suppress part of the noise captured by the focused microphone using a second microphone placed off-axis. The parabola provides a passive acoustic gain estimated at around 20 dB. The INMP441 microphone used here has a sensitivity of -26 dBFS, which theoretically allows for a decent range. In practice, the system has been mainly tested indoors, during filter development — and I never really took the time to try it outdoors.
Hardware Architecture
-
ESP32 DevKit (Xtensa LX6, dual-core, running FreeRTOS)
-
Two INMP441 digital microphones connected via I2S
-
Focus mic: captures signal + noise
-
Reference mic: captures mostly noise
-
-
Audio output: UDA1334 DAC connected to the second I2S port
-
RGB LED on the ESP32 dev board used to display real-time SNR
-
3D-printed parabola, with STL files included in the repository

Signal Processing & Implementation
The NLMS filter is implemented in fixed-point arithmetic, with double buffering to ensure smooth real-time operation. The code runs under FreeRTOS, with a dedicated task for processing. Espressif’s optimized DSP functions are used whenever possible to improve performance (dot products, vector ops...).

FIR Filter & Minimization Criterion
The adaptive filter implemented here is a Finite Impulse Response (FIR) filter. It works by producing an output signal y(n), which is a weighted sum of the past values of the input (the noise reference from the second microphone). These weights — the filter coefficients — are continuously updated.
The goal is to make this output y(n) match the noise component present in the main microphone signal d(n), so that it can be subtracted. The error e(n) is the difference between the desired signal (signal + noise) and the estimated noise.
The filter uses the Normalized Least Mean Squares (NLMS) algorithm to adjust its coefficients. It does this by minimizing the squared error e(n)^2, which means it constantly tries to improve its estimation of the noise. Normalization ensures that the learning rate remains stable even if the input signal varies in amplitude.
This approach allows the system to adapt in real time to changing noise conditions and continuously clean the signal.

Code & Resources
The code is written in C (ESP-IDF + FreeRTOS), with a modular design.
The GitLab repository includes:
-
Full source code (filter, I2S, LED, DAC)
-
files for the 3D-printed parabola
-
A README with wiring, schematic, and explanations
I plan to explore other signal processing methods on this platform, such as:
-
Wiener filtering
-
Spectral techniques
-
Even lightweight deep learning for detection or classification
This hardware setup offers a simple, accessible, and reusable test platform. If anyone wants to continue the experiment or suggest improvements, everything is open: code + CAD files are available.