Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Narrowband ANC — PLL-Tracked Tonal Noise Cancellation

A single-mic, single-speaker prototype that detects dominant tone(s) in ambient noise and continuously emits a phase-compensated anti-tone to cancel them.

This is not a full active-noise-cancellation system in the headphone sense — it's a narrowband tonal canceller, closer to what's used for transformer hum or motor-drone suppression than to consumer ANC. Read the Limitations section below before judging results.

How it works

  1. Acquisition — every ~1.5s, an FFT scan of a rolling buffer finds the top 3 dominant frequency peaks (with parabolic interpolation for sub-bin accuracy).
  2. Tracking — each acquired tone is handed to its own Phase-Locked Loop (PLL). The mic signal is demodulated (I/Q) against a local oscillator; the resulting phase error steers the oscillator's frequency via a PI controller. This is what lets the system self-correct drift instead of relying on a single stale FFT snapshot.
  3. Anti-noise synthesis — once locked, each tracked tone generates a 180°-inverted, latency-compensated sine wave, summed and sent to the output device.
  4. Latency calibration — a chirp is played and cross-correlated against what the mic records, giving a measured round-trip latency instead of a guessed constant.

Status (current)

Working, with known issues:

  • Lock is achievable and holds for single steady tones once the PLL settles.
  • Occasional input/output underflow — the per-sample Python loop in the I/Q low-pass filter is not fast enough to reliably keep up with the real-time audio callback. This is a known, understood bug — the fix (vectorizing the filter, e.g. with scipy.signal.lfilter) is scoped but not yet merged. Do not be surprised by audio glitches/underflow prints.
  • Cancellation depth is currently mild — audible but partial.

Limitations

  • Single mic, single tone family. This can only ever cancel stationary tonal noise (hums, whines, motor/fan drones). It cannot and will not cancel broadband noise (traffic, speech, transients) — that's a mathematical limitation of frequency-peak tracking, not a bug.
  • Acoustic isolation matters. If the speaker output leaks back into the mic (no headphones, open air), the frequency/phase estimate is being computed on a self-contaminated signal.
  • Real ANC headphones use FxLMS with a separate reference mic and error mic — a materially different (and better) architecture. This project is a narrowband PLL tracker, a legitimate but different technique.

Setup

pip install sounddevice numpy matplotlib
# Linux also needs:
sudo apt install libportaudio2

Usage

python src/narrowband_anc_pll.py
  1. Click "Auto-Calibrate Latency" first — stay quiet, uses open speakers.
  2. Switch to headphones for output.
  3. Play a steady tone or hum near the mic.
  4. Watch the status line — wait for [LOCKED] before judging cancellation.
  5. Adjust gain/latency sliders if needed.

Roadmap

  • Vectorize the I/Q low-pass filter to fix input/output underflow
  • Add a second (error) microphone and move toward FxLMS
  • Log cancellation depth (dB) automatically for reporting
  • Multi-tone amplitude balancing when tones are close in frequency

Background

This started as an ESP32 + desktop hybrid ANC attempt during an internship. The original single-tone, blocking-playback version did not achieve usable cancellation due to architectural issues (unsynchronized mic/speaker clocks, non-continuous output, single-frequency-only tracking, open-loop frequency estimation). This repo is the rebuilt, closed-loop version developed to directly address those failure modes.

About

No description or website provided.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages