M3: nn_suppressor on tap::dsp::nn; the speech predictor's pitch search accumulates in Sample - #46
Merged
Merged
Conversation
The wake-word plan's M3: the dense and GRU arithmetic now lives in DspTap (tap::dsp::nn, tap/DspTap#15) and nn_suppressor consumes basic_dense and basic_gru. The weight arrays are moved into the kernels at construction (one copy in memory). The kernels' loop order is exactly the one this header carried, so the promotion is bit-identical in both profiles on the shipping v2 model against the pre-refactor binary; the six parity cases pass at the M2 depths, the M2 battery passes unchanged, and the nn_suppressor ratchet moved -0.12 % / -0.10 % on m55 and -0.19 % / -0.11 % on m33 (16 k / 48 k) with every other scenario unchanged to the instruction. submodules/dsptap points at the M3 tree; repoint at the identical tree on main once the DspTap PR merges. Follow-up to the M2 finding on the Cortex-M33 leg: the speech predictor's pitch search (lpc.h) accumulated its normalized correlation in double for every lag from 32 to 400 over a 1024-sample window — about a million software double operations per 64-sample block on a core without FP64, and two thirds of the tonal PEM headline's 1085 s under qemu mps2-an505 (the test harness's deliberate double room simulation was the other third: 772 s with it switched to float). The search now accumulates in Sample. The double profile is bit-for-bit unchanged; the float rows' measured numbers are unchanged to the MSG bisection's 0.5 dB quantum (kalman-loop tonal ASG +7.81 dB before and after, PEM tonal +10.84 -> +11.13, ERLE and misalignment identical). The tonal headline now takes 31 s on the M33 emulator and the full float selection 174 s, so the MUTAP_ON_TARGET_SOFT_FP64 exclusion is removed: the M33 leg runs exactly the M55's selection. docs/wake-word-plan.md carries the M3 record and the corrected M2 finding; HANDOFF.md points at M4. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JuUg1ZBxm3fyBqWgQv6H1G
tap/DspTap#15 merged by squash; this is the identical tree, reachable after branch cleanup. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JuUg1ZBxm3fyBqWgQv6H1G
tap
pushed a commit
to tap/MuTap-Max
that referenced
this pull request
Sep 5, 2026
tap/MuTap#46 (96b4572), which carries DspTap 58210ae (tap/DspTap#15) as its nested pin. The learned post engine mutap.aec~ instantiates is bit-identical on the shipping v2 model in both profiles; the speech predictor's pitch search now accumulates in Sample (double profile unchanged). No source change in the externals. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JuUg1ZBxm3fyBqWgQv6H1G
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
Two things, one commit.
M3 of the wake-word plan. The dense and GRU arithmetic now lives in DspTap (
tap::dsp::nn, tap/DspTap#15) andnn_suppressorconsumesbasic_dense/basic_gru; its weight arrays are moved into the kernels at construction, so there is one copy in memory.submodules/dsptappoints at the M3 tree.Follow-up to the M2 finding on the Cortex-M33 leg. The speech predictor's pitch search (
lpc.h) accumulated its normalized correlation in double for every lag from 32 to 400 over a 1024-sample window, about a million software double operations per 64-sample block on a core without FP64. It now accumulates inSample. The M33 leg'sMUTAP_ON_TARGET_SOFT_FP64exclusion is removed: it runs exactly the M55's float selection.Why
The audit asked for the learned kernels to be promoted only after M2 had given them oracles in both profiles, so that "no behaviour change" is a measurement rather than a claim. It is: see below.
The pitch-search change is the root cause of the M2 finding. An experiment separated the two suspects: with the test harness's deliberate double room simulation switched to float the tonal PEM headline still took 772 s of its 1085 s on the M33 emulator, so the harness was a third of the cost and the library two thirds. Fixing the library rather than the tests keeps the harness as the double oracle it was designed to be and restores the four PEM scenarios to the M33 leg. It also matters beyond the wake word: on the RP2350 class of core the shipping float-profile PEM canceller was spending most of its cycles in software double.
Verification
nn_inferbuilt frommainand from this branch, driven by the same 200-block signal through the shippingsuppressor_v2_48k.munn: outputs identical to the bit in both profiles (max diff 0.0).test_parity.pycases pass at the M2 depths (double ≤ 2.9e-8, float ≤ 2.9e-7, pinned 1e-6).nn_suppressor_16k/_48kmoved −0.12 % / −0.10 % on m55 and −0.19 % / −0.11 % on m33; every other scenario unchanged to the instruction (+0.00 %). Baselines left as they are; the drift gate holds.aec_testrows' ERLE and misalignment identical to three decimals.Notes for the reviewer
speech_predictor::analyze()'s pitch search accumulates inSample; the float profile's lag/beta decisions can differ from before at the ~1e-6 relative level of a float normalized correlation, which is below the voicing decision's resolution and did not move any pinned number by more than the bisection quantum. The double profile is unchanged.nn_suppressor'sconfig::weightsarrays are moved out at construction (documented in the config).submodules/dsptap→ the M3 tree on DspTap'sclaude/mutap-wake-word-plan-2i63pe(4e9a29a). After Add tap::dsp::nn: dense and GRU inference kernels DspTap#15 merges by rebase/squash, the pin is repointed at the identical tree on DspTapmain; MuTap-Max's MuTap pin follows once this merges.bench/icountbaselines are untouched because the drift is inside the ±3 % gate; re-seeding is for real cost changes.🤖 Generated with Claude Code
https://claude.ai/code/session_01JuUg1ZBxm3fyBqWgQv6H1G
Generated by Claude Code