Broadband default

FXLMS is the reference broadband feedforward controller in this codebase.

Filtered-X LMS combines a causal reference microphone, an FIR control filter, and an identified secondary-path estimate. In the repository benchmark suite it is the strongest general-purpose controller: fast to converge, straightforward to tune, and capable of deep attenuation when the secondary-path model is usable.

Core Equations

The control output is an FIR inner product:

\[y(n) = \sum_{i=0}^{N-1} w_i(n) x(n-i)\]

The reference is filtered through the secondary-path estimate:

\[x'(n) = \sum_{i=0}^{M-1} c_i x(n-i)\]

The adaptive update is then:

\[w_i(n+1) = w_i(n) - \mu e(n) x'(n-i)\]

The negative sign matters. This repository follows the acoustic superposition convention used in active noise cancellation, where the anti-noise adds at the error sensor rather than subtracting electrically.

Why It Works Well Here

The benchmark suite shows 61.127 dB attenuation in the primary broadband case with convergence by sample 256. That combination of strong steady-state performance and fast convergence is why FXLMS is the first controller to try unless the disturbance is strongly periodic or the reference microphone is contaminated.

Running RMS

The residual drops quickly and stabilizes at a very low floor in the matched broadband scenario.

FXLMS running RMS plot.

Step-size sweep

The sweep shows a clean improvement curve until the controller crosses into instability at an overly aggressive step size.

FXLMS step-size sweep plot.

Tuning Notes

Using It From C++

#include "anc/fxlms_controller.h"

anc::FxlmsConfig config;
config.controllerOrder = 48;
config.secondaryEstimate = {0.0, 0.12, 0.38, 0.21, -0.05};
config.stepSize = 0.005;
config.leakage = 1.0;

anc::FxlmsController controller(config);

for (std::size_t sample = 0; sample < reference.size(); ++sample) {
  const double control = controller.synthesize(reference[sample]);
  const double error = disturbance[sample] + secondaryPath(control);
  controller.adapt(error);
}

The controller exposes weights() and filteredReferenceHistory() when you need instrumentation or debugging around adaptation state.

CLI Reproduction

build\Debug\anc_cli.exe `
  --algorithm fxlms `
  --summary analysis_output\raw\fxlms_broadband_summary.csv `
  --timeseries analysis_output\raw\fxlms_broadband_timeseries.csv `
  --samples 12000 `
  --controller-order 48 `
  --step-size 0.005