Hey folks,
Today morning was aggressively boring, so naturally I ended up building a 2x2 MIMO active noise control simulator.
I have recently started poking around the border between DSP and control systems, and for some reason I am enjoying it far more than expected. I also do not entirely know why I am posting my random experiments, but maybe someone finds this useful, finds a cursed coefficient, or tells me that I have misunderstood acoustics in a particularly creative way.
The project is a cross-coupled FxNLMS system with:
- 2 reference microphones
- 2 anti-noise speakers
- 2 error microphones
- A full 2x2 primary acoustic-path matrix
- A full 2x2 secondary-path matrix
- Four 64-tap adaptive controller filters
- Noisy offline secondary-path identification
- Slowly drifting secondary paths
- Mixed, stereo WAV, and impulsive-noise scenarios
Julia handles the signal generation, acoustic models, WAV processing, metrics, diagnostics, and plots. I kept a complete Julia implementation as the numerical oracle and moved the sample-processing kernel into C23.
The C backend currently matches Julia to around 1.55e-15, with exactly 0.0 dB ERLE difference across all three scenarios. It is approximately 1.76x faster in the warmed benchmark.
Current final-window results at 8 kHz:
| Scenario | Combined ERLE |
|---|---|
| Mixed moving noise | 16.25 dB |
| Stereo WAV | 24.06 dB |
| Impulsive noise | 18.10 dB |
The impulsive benchmark reaches a sustained 80% of final cancellation in under 25 ms.
I tried to keep the simulation honest:
- The adaptive controller never sees the true secondary paths.
- It only receives reference signals, measured residuals, and separately estimated secondary paths.
- The C processing function performs zero heap allocations.
- Julia and C run the same deterministic scenarios.
- The C side is compiled as C23 with warnings treated as errors.
- The project runs GCC and Clang static analysis plus deterministic unit tests.
The default backend is C:
main()
The Julia oracle is still available:
main(:julia)
Repository:
This is still an offline simulator rather than a real headset or hardware ANC controller. The next genuinely different step would be separating render and adaptation into a real-time API with measured audio latency.
Feedback is very welcome, especially around the MIMO normalization, acoustic scenarios, Julia/C boundary, or anything that looks slightly cursed.
Have a great, day or night or whatever is it at your timezone
Adios
-JB