Skip to content

Wave 3: dsp::xtc with X1–X6 gates; room~ harness-first phase (R1–R10 + FDN verdict)#12

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

Wave 3: dsp::xtc with X1–X6 gates; room~ harness-first phase (R1–R10 + FDN verdict)#12
tap merged 3 commits into
mainfrom
claude/ambitap-roadmap-max-assessment-tiuszu

Conversation

@tap

@tap tap commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

The two perceptual Wave 3 items, executed per docs/PERCEPTUAL-VERIFICATION.md — the numeric gates are implemented and passing, the listening pass remains the release gate.

dsp::xtc — crosstalk cancellation (computed KEMAR plant, v1 presets-only per the doc's open-question #2). Per-bin regularized 2×2 inversion H = (Cᴴ C + β(f) I)⁻¹ Cᴴ, closed-form (no Eigen; header builds against AmbiTap::fft alone). β(f) is band-shaped in log-f and scaled by the local ⅓-octave-smoothed plant power — the global-scale alternative forfeits cancellation exactly at the weak 300 Hz band edge (3.6 → 23 dB min in-band XTC). Ipsilateral coloration normalized against the smoothed P-diagonal; +12 dB gain ceiling with exactly reciprocal makeup baked into the shipped FIRs; 1024 taps, 512-sample latency.

Gate results (thresholds from the doc): X1 60.7/58.5/62.8 dB mean in-band XTC at ±10/20/30° (gate ≥ 20); X2 16.8 dB at ±2 cm (≥ 12); X3 24.3 dB at ±5° yaw (≥ 12); X4 0.76 dB design-point coloration (≤ 3); X5 11.78 dB ceiling (≤ 12); X6 byte-identical. One documented deviation: the ±5 cm per-frequency ≥ 0 dB clause is provably incompatible with in-band cancellation (~1.9 rad path skew at 6 kHz; derivation in the test) — that clause gates the band mean (7.8 dB).

room~ harness-first phase (per open-question #3: architecture decided from the notebook, not from listeners). New capi export ambitap_builtin_hrtf_hrir() (time-domain SH-reconstructed HRIR — the doc's stated prerequisite, verified byte-exact from Python); notebooks/room_model.py (exact shoebox image-source ER + 16-line SH-domain FDN + synthesized-convolution reference); notebooks/room_verification.ipynb executed with all 21 enforced R1–R10 checks passing for both architectures. Decisive numbers: R7 per-order energy 0.16 dB (±1.5), R9 per-band IACC deviation vs the diffuse reference 0.079 (≤ 0.15).

Verdict: implement the FDN tail in C++ — statistically indistinguishable from the by-construction-diffuse convolution tail on the architecture-deciding gates, at a fraction of the CPU, with parametric RT60. One threshold revision flagged for the doc (to land with the C++ phase per its revision process): broadband IACC ≤ 0.3 is unattainable through an order-3 LS render — the ideal diffuse reference itself measures 0.429 — so the harness gates IACC relative to that reference.

Downstream

ambitap.xtc~ (Max external) is ready on the AmbiTap-Max branch; it needs this merged and the submodule bumped. The room~ C++ implementation (FDN per the prototype spec) is the next scoped task.

Test plan

  • 130/130 tests green (121 pre-existing + 9 xtc gates incl. an RT-safety allocation guard)
  • xtc gate tests use an independent textbook-DFT plant model (not the library's FFT)
  • Notebook executes end-to-end, byte-identical across two runs (fixed seed)
  • capi export verified byte-exact against a Python-side SH table sum
  • clang-format clean on all touched C++
  • 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 3 commits July 3, 2026 23:14
Two-speaker transaural canceller for a computed KEMAR plant (span,
distance): per-bin H = (C^H C + beta(f) I)^-1 C^H via closed-form 2x2
complex inversion (no Eigen — the header builds against AmbiTap::fft
alone). beta(f) is raised-cosine in log-f between the in-band value and
1.0 outside 100 Hz-9.5 kHz, scaled per bin by the 1/3-octave-smoothed
local plant power — a global scale forfeits cancellation at the weak
300 Hz band edge (min in-band XTC 3.6 dB -> 23 dB). Ipsilateral response
normalized to the smoothed geometric-mean diagonal of P = C·H (X4);
global gain scale fits the worst filter gain onto 11.5 dB with exactly
reciprocal makeup attenuation baked into the FIRs (X5); response fades
to zero above 19 kHz. 4096-bin design -> 1024-tap FIRs, 512-sample
latency. Design on the control thread; process() wait-free.

tests/test_xtc.cpp implements the PERCEPTUAL-VERIFICATION.md gates with
an independent textbook-DFT plant model: X1 measures 60.7/58.5/62.8 dB
mean in-band XTC at spans 10/20/30 deg (gate 20); X2 16.8 dB at ±2 cm
(gate 12) — the ±5 cm per-frequency floor is provably incompatible with
in-band cancellation (~1.9 rad path skew at 6 kHz; derivation in the
test) so that clause gates the band mean (7.8 dB); X3 24.3 dB at ±5 deg
yaw; X4 0.76 dB design-point coloration; X5 11.78 dB ceiling; X6
byte-identical determinism. RT-safety allocation guard extended to xtc.
130/130 tests green; clang-format clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012VeadvCRUHJdneFNwRbFAM
…e, HRIR capi export

Executes the PERCEPTUAL-VERIFICATION.md room protocol before any real-time
C++ exists, so the tail architecture is decided by numbers:

- tools/capi: new ambitap_builtin_hrtf_hrir() — time-domain SH-reconstructed
  KEMAR HRIR at a direction (the sum probe_response performs before
  discarding phase), the doc's stated capi prerequisite. Verified byte-exact
  against a Python-side table sum.
- notebooks/room_model.py: offline prototype — shoebox image-source early
  reflections encoded as HOA point sources, a 16-line SH-domain FDN tail
  (mutually-prime delays 9-83 ms, signed-Hadamard feedback, per-line 255-tap
  linear-phase absorption FIRs fitted to the parameterized T60(f) with loop
  group delay counted, Jot-style shaped noise input FIRs, second Hadamard
  distributing lines onto SH channels with SN3D per-order gains), and a
  synthesized-convolution tail as the by-construction-diffuse reference.
- notebooks/room_verification.ipynb (executed): the R1-R10 gates as
  deterministic functions of a rendered SH IR, reusable unchanged against
  the future C++ implementation. All 21 enforced checks PASS for both
  architectures: ER arrivals 0.44 smp (gate 1), DOA 0.024 deg (5), ER
  levels 0.0000 dB (0.5), T20 worst +6.0% (10), EDT +21.1% (25), C50/C80
  0.56 dB (2, monotone), per-order energy 0.16 dB (1.5), late |rE| 0.053
  (0.1), per-band IACC dev vs diffuse reference 0.079 (0.15),
  byte-identical determinism.
- Verdict: implement the FDN in C++ — indistinguishable from the diffuse
  convolution reference on R7/R9 at a fraction of the cost. One threshold
  revision flagged for the doc (with the C++ phase, per its process): the
  broadband IACC <= 0.3 gate is unattainable through an order-3 LS render —
  the ideal diffuse reference itself measures 0.429 — so the harness gates
  IACC relative to that reference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012VeadvCRUHJdneFNwRbFAM
The clang CI legs (linux-clang, macos-appleclang) failed on signedness
warnings gcc does not emit: iterator + size_t in the output copies
(now std::copy_n) and int loop indices used as size_t subscripts in the
gate tests. 130/130 green under both gcc and clang-18 with
AMBITAP_WERROR=ON; clang-format clean.

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