ITU compliance Stage 2: residual-echo post-filter, comfort noise, AEC chain#7
Merged
Merged
Conversation
… chain mutap/postfilter.h delivers the Stage 2 items of docs/itu-compliance.md: - residual_suppressor: per-bin Wiener gain on E whose DEPTH comes from a leakage estimate (residual power per unit echo-estimate power) gated by mic-vs-echo-estimate coherence. The discriminator correlates the MIC (D = E + Yhat), never E, against Yhat: a converged adaptive filter keeps E orthogonal to its reference, so coh(E, Yhat) saturates at 0.34 while adapting where coh(D, Yhat) measures 0.99. Gains are constrained to a causal 2B-tap filter (rectangular cut — a Hann taper measured WORSE double-talk transparency), attack-smoothed against estimator chatter, and suppressed bins are refilled with comfort noise shaped to a two-window minimum-statistics noise floor (one-pole trackers measured either -8 dB undershoot or tens-of-seconds acquisition). - aec_chain: canceller + suppressor as the unit the compliance matrix measures. Defaults to the RAW partitioned FD-Kalman core, not pem_afc: open-loop AEC has an exogenous far end — no closed-loop bias to remove — and PEM's predictor refit floors misalignment near -20 dB where the raw core measures -75.6 dBm0(A) bare with double-talk immunity from its own noise-PSD tracking. pem_afc (grown an echo_estimate_block() accessor) still composes via the 3-argument branch. Measured on the golden model (test_postfilter.cpp, all margin targets): ST residual -80.5/-89.7 dBm0(A) cabin/studio (target < -64; NLMS core -66.2, 16 kHz -70.7), DT send atten 1.14/1.03 dB (<= 1.5), DT echo loss worst band 37.9/34.2 dB (>= 33), ERL 43.2 dB by 600 ms / 46.9 by 1200 (>= 40/46), comfort noise -1.50 dB level / <= 1.69 dB per band / pumping 2.9 dB / build-up 11.6 ms. Full tables and the four design decisions the measurements forced are in the matrix's "Stage 2 delivered" section. Instrument fix: A-weighting poles above Nyquist (12.2 kHz pair at fs = 16 kHz) are prewarp-clamped to 0.45 fs — tan() past pi/2 flipped sign and the 16 kHz chain measurements went NaN. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TLE2rvptWxV8catE8vTvgx
…honest number ASan (and MSVC, via the garbage it read) caught NearEndBuildUpTime reading 250 ms past the end of its level trace: the near-end onset sat at 5/6 of the run but the settled-level window needed 2 s of tail. Onset moved to 2/3 (3.5 s of tail) with an explicit size guard. Measured honestly, build-up at gain_release 0.9 is 26.0 ms — over the switching rows' 25 ms margin target (the old 11.6 ms figure was computed against the corrupted median). Release 0.85 measures 20.9 ms and is the new default; 0.8 was measured too fast for the rest of the board (studio worst DT echo-loss band fell to 32.8 dB, under the 33 dB target). Full re-measurement at 0.85, all margin targets still met: ST -79.9/-88.9 dBm0(A), DT atten 1.05/0.93 dB, DT echo loss worst band 38.0/34.1 dB, comfort noise -1.20 dB, pumping 3.3 dB. Test comments, matrix table and README refreshed; ItuChain suite re-run green under ASan+UBSan. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TLE2rvptWxV8catE8vTvgx
dcb2254 to
a223fb4
Compare
f5b5243 to
558395d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 2 of the ITU compliance plan: the residual-echo suppressor + matched comfort noise (
mutap/postfilter.h), andmutap::aec_chain— the canceller + post-filter unit the compliance matrix measures. Stacked on #6 (Stage 1 signal layer); rebases ontomainafter #6 merges.What's in it
residual_suppressor<Sample>— per-bin Wiener gain on the canceller output E whose depth comes from a leakage estimate (residual power per unit echo-estimate power), gated by mic-vs-echo-estimate coherence. Gains constrained to a causal 2B-tap filter (one block of latency), attack-smoothed, suppressed bins refilled with comfort noise shaped to a two-window minimum-statistics noise floor. RT contract as everywhere: constructor allocates and may throw; everything after is noexcept and allocation-free.aec_chain<Sample, Canceller>— defaults to the raw partitioned FD-Kalman core;pem_afcstill composes via its 3-argument surface (it grew anecho_estimate_block()accessor).tests/test_postfilter.cpp— 12 measured-first tests pinning every Stage 2 deliverable at its margin target, on both fixture rooms, both cores, 48 kHz and 16 kHz.The three design decisions the measurements forced
Measured vs matrix margin targets (all pass)
Chain config for all of the above: raw FD-Kalman, transition 0.9998 + initial uncertainty 10 (both swept; 0.99995 costs double-talk transparency and tracking, the larger P(0) buys ~4 dB of early convergence), suppressor at defaults.
Full test suite: 124/124 pass locally. Rejected designs (power-leakage ratios, instantaneous-|E|² rules, coh(E,Ŷ), Hann-tapered gain cut, one-pole floor trackers) are documented in the header comments with their measured failures.
Still Stage 3's to prove: the per-row multi-rate compliance suite, spectral echo mask, switching/activation battery, stability sweep, and the G.168-adapted rows.
🤖 Generated with Claude Code
https://claude.ai/code/session_01TLE2rvptWxV8catE8vTvgx
Generated by Claude Code