mutap.aec~: selectable post-filter engine — @postfilter 0/1/2 with @model - #17
Merged
Conversation
@PostFilter grows from a boolean into the post-filter ENGINE selector: 0 = off, 1 = the classical ITU-certified chain (exactly the old 'on'), 2 = the learned chain — the same raw-Kalman canceller and receive guard with the coherence suppressor swapped for MuTap's trained band-gain network (tap::mu::aec_chain_nn via aec_chain_nn_preset). Old patches with 0/1 keep their exact meaning; future engines get 3, 4, ... @model selects the learned engine's weights: a MUNN file path, or empty for the built-in model — suppressor_v2_48k embedded as a generated byte-array header (52,570 parameters, trained at this external's native geometry: 48 kHz, block 256; tools/ml in the MuTap repo, every training input clean-licensed). A model carries its own geometry: publish() coerces @block to the trained hop with a console notice, warns on a sample-rate mismatch, and a bad weights file posts an error and leaves the running engine untouched. Engine rebuild failures are no longer silent. Help patcher and maxref document the engine choice and the measured trade (learned: stronger single-talk ERLE on speech at equal transparency; classical: certified, stronger off-domain double-talk — and still the default). Tests cover the new defaults, the 0..2 clamp, and the built-in model's block coercion; both suites pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y3Y23Xavpd31igC1mDDcWg
The external now includes mutap/nn_chain.h and nn_suppressor.h. After tap/MuTap's branch merges (rebase/squash), repoint this pin at the identical tree on main per the template's submodule rule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y3Y23Xavpd31igC1mDDcWg
MSVC finds min::symbol -> std::string ambiguous (three basic_string overloads match); go through c_str(). The generated weights header now carries clang-format off/on guards so the format gate skips the byte array (regenerated from the same v2 model — content unchanged). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y3Y23Xavpd31igC1mDDcWg
tap/MuTap#33 merged (rebase); the pin moves from the branch head to the identical tree on main (1d258d3), per the submodule rule in the PR notes. Package builds and tests green against the pinned submodule itself (no MuTap_ROOT override). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y3Y23Xavpd31igC1mDDcWg
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.
What this changes
@postfiltergrows from a boolean into the post-filter engine selector — 0 off, 1 the classical ITU-certified chain (exactly the old "on"), 2 the learned chain (tap::mu::aec_chain_nn) — with a new@modelattribute for user-trained MUNN weights and MuTap's 48 kHz v2 model embedded as the built-in default. Companion PR: tap/MuTap (the library side; this PR's submodule pin points at its branch head).Why
Users should choose the residual-suppression engine by material and need: the classical coherence suppressor is certified and material-agnostic (still the default); the learned engine measures ~+19 dB single-talk ERLE on speech at better near-end transparency. The enum +
@modelshape leaves room for future engines (3, 4, …) and future models without new binaries.Verification
mutap.aec~, incl. the 0..2 clamp, new defaults, and the built-in model's @block coercion to 256);ctestgreen. Built and tested on Linux against the branch library; macOS/Windows externals are CI's gate, not built here.postfilter $1toggles still mean exactly 0/1.@modelfile posts an error and leaves the running engine untouched (rebuild failures are no longer silent).Notes for the reviewer
@postfiltertype widens bool→int (values 0/1 keep their meaning; getters now return 0/1/2). With@postfilter 2,@blockfollows the loaded model's trained block size (coerced with a console notice) and a sample-rate mismatch warns.submodules/MuTap→ the tap/MuTap branch head this depends on. After that PR merges by rebase/squash, repoint at the identical tree onmainbefore this merges.mutap_nn_weights_default.his generated (tools/ml/export_weights.py --headerin MuTap) — 776 KB, do not hand-edit.🤖 Generated with Claude Code
https://claude.ai/code/session_01Y3Y23Xavpd31igC1mDDcWg
Generated by Claude Code