Skip to content

k·fs transmission zeros, the economy preset, the program-weighted metric, and the book's epilogue#31

Merged
tap merged 8 commits into
mainfrom
claude/program-weighted
Jul 4, 2026
Merged

k·fs transmission zeros, the economy preset, the program-weighted metric, and the book's epilogue#31
tap merged 8 commits into
mainfrom
claude/program-weighted

Conversation

@tap

@tap tap commented Jul 4, 2026

Copy link
Copy Markdown
Owner

What this is

The two experiments from the music-dsp (RBJ) thread, productionized, plus the book chapter that tells the story. Follows from the verification notebook (#30).

The design change

detail::designPrototypeCompensated places transmission zeros at every integer multiple of the sample rate (one-sample-rect convolution) with the sinc droop pre-compensated inside the passband spec: the 1/sinc tilt is expressed as a short cosine series (weighted LS via a small dense solver) — in time, a sum of the brickwall kernel at integer shifts, so the design stays closed-form with no FFT. Two direct-DFT correction passes hold ripple to ±0.003 dB on every preset. The composite is centered exactly like the plain design; the fractional-delay tests caught the half-fine-sample rect-centering bug (−72 dB at 1 kHz, +6 dB/octave) on the first build, as designed.

  • balanced/transparent flip to imageZeros at equal tap count: worst-case numbers unchanged, passband flat to ±0.003 dB, low-band folded images 10–20 dB deeper (997 Hz prototype floor: −144 → −158 dB). fast stays plain.
  • New economy preset (L=512, T=32, zeros): two-thirds of balanced's per-sample compute, 0.16 ms less group delay.

The new metric

tests/support/multitone_analysis.hpp: 24 pink-weighted log-spaced tones, joint LS fit (sequential fit-subtract floors at 48 dB — measured), DC modeled in the fit (pre-subtracting the sample mean also floors at 48 dB — measured; a finite tone window has a legitimate mean), Fisher-weighted clock-ratio pooling. ProgramWeighted.InstrumentFloor pins the instrument itself at >145 dB on synthetic tones (measured 151.9).

Measured outcome (full converter, +200 ppm)

preset program-weighted worst-case 19.5 kHz sine compute
balanced 134.5 dB 105 dB 1.0×
economy 131.6 dB 77 dB (documented, gated) 0.67×

RBJ's trade, quantified: 2.9 dB of program-weighted quality for 33% of the compute, with the worst-case number kept visible in docs, tests, and the book.

Test-gate re-pins

Fractional-delay and Q15 DC-gain gates re-pinned to the documented ±0.01 dB passband contract (the old numbers leaned on the plain Kaiser's incidental ±0.0001 dB flatness); alignment bugs still fail them by >20 dB. Host suite: 70/70 under -Werror.

Expected CI note — embedded ratchet

Constructor design cost grew ~3× in transcendentals (still constructor-only, off the audio path; audio-path instruction counts are unchanged — same T, same kernels). Embedded icount scenarios include construction, so the ±3% two-sided ratchet will trip on short scenarios; per the algorithm-change rule I'll regenerate baselines from this PR's CI logs and push them here, with the PERFORMANCE.md entry (included) as justification.

The book

New epilogue chapter, "A letter from the list": the whole episode — verify-before-you-argue, the two-specifications lesson, the instrument's own two measured failure modes — with live pw_* excerpts from the new code. George Box epigraph.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9


Generated by Claude Code

claude added 8 commits July 4, 2026 20:40
…ighted metric

The music-dsp thread's suggestion, productionized inside the passband
spec. designPrototypeCompensated builds the droop pre-compensation as a
cosine series in f (weighted LS via a small dense solver) -- in time, a
sum of the brickwall kernel at integer shifts, so the design stays
closed-form with no FFT -- then windows and convolves with a one-sample
rect whose zeros land on every k*fs. Two direct-DFT correction passes
hold ripple to +/-0.003 dB on every preset. The composite is centered at
(L*T-1)/2 exactly like the plain design (the even-length rect shifts by
half a fine sample; the fractional-delay tests caught the -72 dB error
of getting that wrong).

balanced/transparent flip to imageZeros (equal taps, worst-case numbers
unchanged, low-band folded images 10-20 dB deeper); fast stays plain.
New economy preset (L=512, T=32, zeros): 2/3 of balanced's per-sample
compute, measured 131.6 dB on the new program-weighted metric vs
balanced's 134.5 -- the RBJ trade, quantified -- with the worst-case
19.5 kHz sine at 77 dB kept visible in tests and docs.

New tests/support/multitone_analysis.hpp: 24 pink-weighted log-spaced
tones, joint LS fit (sequential fit-subtract floors at 48 dB; measured),
DC modeled in the fit (subtracting the sample mean beforehand injects a
constant the sine basis cannot absorb -- also measured, also 48 dB),
Fisher-weighted clock-ratio pooling. An instrument self-test pins the
floor at >145 dB on synthetic tones.

Fractional-delay and Q15 DC-gain gates re-pinned to the documented
+/-0.01 dB passband contract (the old numbers leaned on the plain
Kaiser's incidental +/-0.0001 dB flatness); a half-sample alignment bug
still fails them by >20 dB.

https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
The RBJ episode as the book's closing chapter: verify before you argue
(his 108/120/12-per-doubling figures reproduced to half a dB), the T=32
claim refuted at the worst-case spec and then understood as a different
spec, the k*fs zeros productionized inside the passband contract (with
the half-sample rect-centering bug the fractional-delay tests caught),
the program-weighted instrument and its own two measured 48 dB failure
modes, and the economy preset's 131.6-vs-134.5 dB outcome. George Box
epigraph. Live excerpts via pw_* anchors; the pw_comp_design anchor is
re-scoped to the design contract with pw_comp_rect for the zeros
themselves.

https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
The ratchet's first run priced the naive design loops at +225.4M
instructions per M55 scenario (constant across all seven -- pure
constructor cost, audio path untouched): ~2M libm sin/cos calls, and
far worse where doubles are soft (seconds of boot on an M33-class
part). Before ratifying baselines at that price: sin(pi*c*(t-m)) now
expands by angle addition over M+1 precomputed shift constants with the
per-tap sin/cos advanced by a unit rotator (re-synced via libm every
4096 taps); the probe DFT uses one rotator per frequency; the fit basis
uses the Chebyshev recurrence. ~3k libm calls remain. Coefficients move
only at rotator-rounding level; all 70 host tests pass unchanged,
including the ripple/zero/alignment gates.

https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
Trig-lite constructor measured at +33.7M instructions per M55 scenario,
constant across all seven (the audio path's counts are unchanged; the
delta is construction only), down from the naive form's +225.4M.
Justification: PERFORMANCE.md 'Compensated prototype design' entry.
README icount table regenerated by scripts/update_icount_docs.py. The
ratchet job stops at the first failing target, so m33 and hexagon
baselines follow from the next runs' logs (documented bootstrap
pattern). Also drops the README's stale private-repo note.

https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
…rgets

The M33 leg priced the trig-lite design at +1.90G instructions per
scenario: on a soft-FP64 target every double flop is a ~140-instruction
libcall, so the ~14M design flops -- not libm -- were the bottleneck
there. Cut to one correction pass and 24 probes: ripple margin still
>=2.2x on every preset (balanced/transparent/economy re-verified,
including 16 kHz scaling), roughly halving the design flops. Two
passband-edge fractional-delay gates re-pinned between the new measured
ripple and the +/-0.01 dB contract bound. Known-debt entry records the
remaining constructor cost on soft-FP64 targets, the ratchet-sensitivity
dilution, the construction-as-its-own-scenario follow-up, and the RP2350
DCP caveat.

CI: the ratchet job's M33/Hexagon steps now run even when an earlier
target fails (if: !cancelled()) -- each target's numbers are independent
evidence, and stopping at the first failure forced a serial baseline
harvest.

https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
One run, all targets (the !cancelled() decoupling): M55 +16.1M
(hardware FP64), Hexagon +131.3M, M33 +928.7M (soft-FP64) instructions
of construction per scenario, constant across all seven scenarios per
target -- the constant-delta signature confirming the audio path is
untouched. The M55 leg tripped the two-sided ratchet downward
('IMPROVED beyond tolerance') against the interim two-pass baselines,
which is the gate working as designed. README icount table regenerated.

https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
The baseline-harvest rounds queued six full CI stacks for dead commits,
each holding runners through QEMU target builds. Pushes now cancel their
own branch's in-flight runs; the latest commit is the only one that
matters for every gate in this repository.

https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
@tap tap merged commit c094252 into main Jul 4, 2026
28 checks passed
@tap tap deleted the claude/program-weighted branch July 4, 2026 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants