Skip to content

Add the shared FIR substrate carried from SampleRateTap - #5

Merged
tap merged 2 commits into
mainfrom
claude/fir-substrate
Jul 23, 2026
Merged

Add the shared FIR substrate carried from SampleRateTap#5
tap merged 2 commits into
mainfrom
claude/fir-substrate

Conversation

@tap

@tap tap commented Jul 23, 2026

Copy link
Copy Markdown
Owner

M0 of the RatioTap plan (Appendix A): DspTap gains the shared layer that sits above the converter engines, extracted from SampleRateTap at the moment RatioTap became its second consumer — the same extract-on-second-consumer rule that created this repo.

What moves in

Five headers under include/tap/dsp/, each with a ported/extended contract battery (45 new tests; suite runs 96):

Header Contents Tests
kaiser.h bessel_i0, kaiser_beta, estimate_taps, design_prototype, design_prototype_compensated (zeros at k·fs, droop pre-compensated), solve_dense Prototype specs pinned at SampleRateTap's shipping preset numbers (fast/balanced/transparent/economy), branch-DC uniformity, 16 kHz scaling, plus a new non-power-of-two L=147 design check (RatioTap's shape)
sample_traits.h The sample-format core for float/Q15/Q31 FIR datapaths: coefficient Q formats (Q1.14 / Q1.30), exact int64 accumulation (Q31 products pre-shifted to Q45), single saturating rounding, tap::dsp::sample_type concept Every Q-format number, the rounding mode (half-up at 2^13), saturation, the 16-bit pre-shift, double-vs-float accumulation
fir_kernels.h dot_row (planar; SMLALD dual-MAC Q15 path on DSP-extension Arm), dot_tile_frame_major / dot_rows_frame_major (register-blocked channel-parallel). Macro gates renamed SRT_*TAP_DSP_* Bit-exactness of channel-parallel vs planar across the 8/4/2/1 tiling (channels 1–16), reference accumulation, odd-tap tail
quantize.h quantize_row_preserving_sum (largest-remainder row-sum preservation), refactored out of SampleRateTap's bank constructor into a free function Exact row sums over all 160 branches of a designed prototype, per-tap deviation bound, Q1.14 unity for a unity-DC row
analysis/ sine_analysis.h (LS fit, tracked variant, snr_db) and multitone_analysis.h (pink tone_comb, joint multitone fit, program_weighted_snr_db) from tests/support/ Instrument floors on exact synthetic signals, so consumer quality gates never rest on a degraded instrument

What deliberately does not move

  • The blend stratum (blend_factor, blend_factor_from_q64, blend): mu-interpolation machinery coupled to the ASRC's Q0.64 phase accumulator. It stays in SampleRateTap as a refinement layered on this core (RatioTap has no blend at all — exact phases are its point).
  • The polyphase bank, servo, ring, resampler — engine-specific.

Docs and policy

  • README gains the substrate section, including the fixed-point roadmap: Q15/Q31 are first-class embedded profiles (SampleRateTap measured float at ~19× Q15's instruction count on M33), with expected deployments in Bluetooth-adjacent conversion (RatioTap) and M33/M55-class eurorack/pedal targets (TapTools) — adopted per primitive as an explicit Q-format design, via traits over raw sample types rather than wrapper classes.
  • CLAUDE.md's golden-model discipline clause is extended accordingly.
  • Deletes a stray committed a.out.

Behavior change: none

Every function is carried verbatim apart from namespaces, TAP_DSP_ macro prefixes, and comment provenance. ANCHOR: markers are preserved where regions moved wholesale, so SampleRateTap's book can repoint its includes at the submodule path in the follow-up adoption PR — whose unchanged icount baselines (±3% CI gate on M33/M55/Hexagon) will prove the relocation costs nothing on the hot path.

Verified locally: full suite green (96/96) with -DTAP_DSP_WERROR=ON, scripts/tidy.sh clean over the new TUs, clang-format pre-commit clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ldeq57sBySx2nFTQsGcQB6


Generated by Claude Code

claude added 2 commits July 23, 2026 03:47
Five headers under include/tap/dsp/, extracted so RatioTap (the second
consumer) and SampleRateTap share one implementation of the layer above
the converter engines:

- kaiser.h: Kaiser prototype design (bessel_i0, kaiser_beta,
  estimate_taps, design_prototype, design_prototype_compensated with
  zeros at k*fs and droop pre-compensation), plus solve_dense.
- sample_traits.h: the sample-format core for float/Q15/Q31 FIR
  datapaths (coefficient Q formats, exact int64 accumulation, single
  saturating rounding) and the tap::dsp::sample_type concept. Format
  core only: engine-specific extensions (e.g. SampleRateTap's
  inter-phase blend) derive from these and refine the concept.
- fir_kernels.h: dot_row (with the SMLALD dual-MAC Q15 path for
  DSP-extension Arm cores), dot_tile_frame_major/dot_rows_frame_major
  (register-blocked channel-parallel kernels, bit-exact vs planar),
  target gates renamed SRT_* -> TAP_DSP_*.
- quantize.h: row-sum-preserving coefficient quantization
  (largest-remainder), refactored out of SampleRateTap's bank ctor.
- analysis/{sine,multitone}_analysis.h: the measurement instruments
  (LS sine fit + tracked variant; pink tone comb, joint multitone fit,
  program-weighted SNR) promoted from tests/support.

Contract batteries ported and extended (45 new tests): prototype specs
pinned at SampleRateTap's shipping preset numbers plus a non-power-of-two
L=147 design, Q-format/rounding/saturation contracts, planar vs
channel-parallel bit-exactness across the 8/4/2/1 tiling, exact row sums
over a designed prototype, and instrument floors on exact synthetic
tones.

README gains the substrate section (including the fixed-point roadmap:
Q15/Q31 as first-class embedded profiles for M33/M55-class targets,
traits over raw sample types rather than wrapper classes) and the
second-consolidation provenance note; CLAUDE.md's discipline clause is
extended to cover the fixed-point profiles. Also deletes a stray
committed a.out.

Behavioral change: none — every function is carried verbatim from
SampleRateTap apart from namespaces, macro prefixes, and comment
provenance; SampleRateTap adopts this via submodule in a follow-up PR
whose icount gates prove the move costs nothing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ldeq57sBySx2nFTQsGcQB6
The solve_dense verification loop indexed the saved matrix with an int:
clang's -Wconversion implies -Wsign-conversion (GCC's does not in C++),
so the macos-vdsp job failed under -Werror while linux-ooura passed.
Index with std::size_t. Verified locally with a clang -Werror build of
the full test suite, which also covers the TUs the failed CI run never
reached.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ldeq57sBySx2nFTQsGcQB6
@tap
tap merged commit 98abb04 into main Jul 23, 2026
12 checks passed
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