Skip to content

Add dsp::room — image-source ER + SH-domain FDN, verified against the R1–R10 harness#13

Merged
tap merged 2 commits into
mainfrom
claude/ambitap-roadmap-max-assessment-tiuszu
Jul 4, 2026
Merged

Add dsp::room — image-source ER + SH-domain FDN, verified against the R1–R10 harness#13
tap merged 2 commits into
mainfrom
claude/ambitap-roadmap-max-assessment-tiuszu

Conversation

@tap

@tap tap commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Summary

The real-time C++ phase of room~ (ROADMAP Wave 3 item 4), implementing exactly the architecture the harness selected in #12: Allen–Berkley image-source early reflections (< 30 ms, SH-encoded point sources) plus the 16-line SH-domain FDN — verified delay set, signed-Hadamard feedback/output, group-delay-corrected per-line absorption FIRs, injection-aligned octave-shaped input FIRs, SN3D per-order gains, energy-calibrated tail.

Acceptance is the harness itself: tools/room_render renders the C++ SH IR for the exact seed-11 configuration and the notebook's own gate functions evaluate it. Every enforced gate matches the prototype — R1 arrivals 0.437 samples, R4 worst T20 +6.0% (per-band identical), R7 order balance 0.16 dB, R8 |rE| 0.053, R9 worst per-band IACC deviation 0.079 / broadband-re-reference 0.020, R10 byte-identical across separate processes. ER/tail sample deviations vs the float64 prototype ≤ 3.6e-8.

Engineering notes:

  • Determinism: the seed-11 noise/sign draws are baked as generated room_data.h (regenerated by scripts/generate_room_data.py) since numpy's PCG64 stream isn't reasonably reproducible in C++; everything derived is computed at runtime from parameters.
  • Real-time contract: rebuilds ride async_rebuilder with 256-sample adoption crossfades; the partitioned injection convolution keeps its history in the object so parameter swaps are click-free; FDN state is float32 with the reasoning documented in-header (orthogonal feedback, loop gain ≤ ~0.92 — unlike NFC's near-unit-circle poles). Fixed documented latency (latency_samples(), ~53 ms at 48 kHz) from the injection alignment inherent to the verified design.
  • Doc revision (deferred from Wave 3: dsp::xtc with X1–X6 gates; room~ harness-first phase (R1–R10 + FDN verdict) #12 per the doc's own process): R9's broadband gate restated relative to the diffuse-field reference — the ideal order-3 reference itself measures 0.429 — and the seed-11 results row added to the results log.

Downstream

ambitap.room~ (mono → HOA bus external) is ready on the AmbiTap-Max branch; needs this merged + submodule bump. That completes the ROADMAP object line (16 externals).

Test plan

  • 141/141 tests green under gcc AND clang-18, both AMBITAP_WERROR=ON
  • C++ render passes every notebook gate the prototype passed (side-by-side numbers above)
  • R1–R3 exactness tested against an independent image-source enumeration; per-band T20/EDT via a C++ Schroeder estimator; determinism; block-size invariance; mid-stream rebuild continuity; RT-safety allocation guard
  • clang-format clean (room_data.h excluded alongside the other generated tables)
  • CI matrix on this PR
  • Listening pass (release checklist — the bypass rule)

🤖 Generated with Claude Code

https://claude.ai/code/session_012VeadvCRUHJdneFNwRbFAM


Generated by Claude Code

claude added 2 commits July 4, 2026 01:54
…selected design)

Implements the architecture the R1-R10 harness selected (notebooks/
room_model.py, seed 11): Allen-Berkley image sources < 30 ms as
nearest-sample taps on a shared delay ring, SH-encoded via evaluate_sh with
amplitude prod(beta)/r; 16-line FDN with the verified delay set 431-3989,
signed-Hadamard feedback and output matrices, per-line 255-tap linear-phase
absorption FIRs fitted to 10^(-3(L+D)/(fs*T60(f))) with loop group delay
counted (faithful firwin2 replica over Ooura), ~53 ms octave-shaped
injection-aligned input FIRs, SN3D per-order output gains, tail level
calibrated to the prototype's energy target. The rejected velvet
decorrelator variant is not implemented.

Determinism: numpy's PCG64 stream is not reasonably reproducible in C++, so
the raw seed-11 draws are baked as generated room_data.h (~780 KB,
hrtf_data.h style; scripts/generate_room_data.py regenerates); everything
derived is computed at runtime from parameters. Injection alignment is
non-causal by up to 2549 samples at 48 kHz -> fixed documented
latency_samples() on every path. Rebuilds ride async_rebuilder (decoder
idiom) with 256-sample crossfades on adoption; injection convolution is a
shared-spectrum partitioned overlap-save whose history lives in the object
so parameter swaps stay click-free. FDN state is float32 (documented: loop
gain <= ~0.92 per traversal, orthogonal feedback — rounding enters at
~-150 dB and decays at T60; design math is double on the worker).

Acceptance: tools/room_render renders the seed-11 config and the notebook's
own gate functions evaluate it — every enforced gate matches the prototype
(R1 0.437 smp, R4 worst T20 +6.0% band-identical, R7 0.16 dB, R8 0.053, R9
worst dev 0.079 / broadband-re-reference 0.020, R10 byte-identical across
processes); ER/tail deviations vs the float64 prototype are <= 3.6e-8.

Tests: R1-R3 exact mirrors vs independent image enumeration, per-band
T20/EDT (Schroeder estimator in C++), calibration energy, determinism,
toggle composition, block-size invariance, mid-stream rebuild continuity,
RT-safety allocation guard. 141/141 green under gcc and clang-18, both
with AMBITAP_WERROR=ON; clang-format clean (room_data.h excluded alongside
the other generated tables).

docs/PERCEPTUAL-VERIFICATION.md: R9 broadband regated relative to the
diffuse-field reference per the first measurement run (the ideal order-3
reference itself measures 0.429); seed-11 results row added to the log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012VeadvCRUHJdneFNwRbFAM
MSVC treats fopen as deprecated (C4996) and the WERROR leg fails on it;
binaural_render.cpp's std::ofstream is the repo precedent. Byte-identical
output; short writes now detected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012VeadvCRUHJdneFNwRbFAM
@tap tap merged commit 18654e9 into main Jul 4, 2026
13 checks passed
@tap tap deleted the claude/ambitap-roadmap-max-assessment-tiuszu branch July 4, 2026 02:14
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