Skip to content

rational: Q15 and Q31 in the C ABI - #66

Merged
tap merged 1 commit into
mainfrom
claude/sample-rate-expansion-strategies-ezqzu6
Oct 8, 2026
Merged

tap merged 1 commit into
mainfrom
claude/sample-rate-expansion-strategies-ezqzu6

Conversation

@tap

@tap tap commented Oct 7, 2026

Copy link
Copy Markdown
Owner

What this changes

  • New format constants: TAP_SR_RATIONAL_FORMAT_FLOAT / _Q15 / _Q31, stable values 0 / 1 / 2.
  • New entry points:
    • tap_sr_rational_create_format(chain, profile, format, channels)
    • tap_sr_rational_create_stage_format(L, M, profile, divisor_num, divisor_den, format, channels)
    • tap_sr_rational_format(c)
    • tap_sr_rational_process_q15 / _q31, taking interleaved int16_t (Q0.15) and int32_t (Q0.31)
    • tap_sr_rational_flush_q15 / _q31
  • Existing float functions: unchanged. create and create_stage are the float case.
  • Wrong-format calls return 0 and consume and write nothing. An unknown format returns NULL.
  • Implementation: the engine behind the ABI is templated on the sample type, so each format runs the same basic_chain / basic_stage C++. The library exports exactly 23 symbols (16 before), still with hidden visibility.
  • ctypes binding: Chain(name, fmt="q15") and Stage(..., fmt="q31") take int16 and int32 numpy arrays.
  • Docs: README C ABI section, CLAUDE.md, plan v0.12, and the header preamble.

Why

You picked this from the post-M6 list. The fixed-point profiles exist for M33 / M55-class deployments, and an FFI consumer there needs them without wrapping the C++ itself.

Verification

  • Tests: test_capi.cpp now checks every one of the 28 chain constants against its named basic_chain, bit for bit, in float, Q15 and Q31. It compares outputs, flush, accounting, latency and MACs.
    • The stage constructor is checked in Q15 and Q31 too.
    • The format is reported correctly, a wrong-format call is refused without changing state, and unknown formats return NULL.
  • Builds: 286/286 tests pass with clang 18 -Werror and the C ABI on. gcc -Werror passes the rational label (113/113). clang-tidy and clang-format are clean.
  • Exports: nm -D lists exactly the 23 tap_sr_rational_* functions.
  • Binding: a smoke run shows Q15 down_2 within 1.5e-5 of the float converter on the same tone, and Q31 3/4 reporting its exact ratio and MACs.
  • Unaffected: the notebooks measure float and don't change. The ratchet doesn't exercise the C ABI.

Notes for the reviewer

  • This departs from the family convention. bridge's and async's C ABIs are float-only: the notebooks measure the golden model, and the C++ tests pin fixed point. This one carries the fixed-point profiles too, and its header says so. If you'd rather keep the family uniform, the alternative is a separate fixed-point ABI per engine; I didn't build that.

🤖 Generated with Claude Code

https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA


Generated by Claude Code

The C ABI now carries the fixed-point profiles beside float, for FFI
consumers on the M33 / M55-class deployments the profiles exist for:

- tap_sr_rational_create_format(chain, profile, format, channels) and
  tap_sr_rational_create_stage_format(...), with TAP_SR_RATIONAL_FORMAT_
  FLOAT / _Q15 / _Q31 (stable values 0 / 1 / 2). The existing create
  functions are the float case, unchanged.
- tap_sr_rational_format(c), tap_sr_rational_process_q15 / _q31 and
  tap_sr_rational_flush_q15 / _q31.
- A process or flush call in another format than the converter's
  returns 0 and consumes and writes nothing.

The engine behind the ABI is templated on the sample type, and each
format is the same basic_chain / basic_stage C++. The library exports
exactly 23 symbols (16 plus seven), still with hidden visibility.

The tests check every chain constant bit for bit against its named
basic_chain in float, Q15 and Q31 (outputs, flush, accounting, latency,
MACs). The stage constructor is checked in Q15 and Q31. Wrong-format
calls must be refused and leave the converter untouched, and unknown
formats return NULL.

The ctypes binding takes fmt="q15" / "q31" (int16 / int32 arrays). The
notebooks still measure float and are unaffected.

The family's other C ABIs (async, bridge) remain float-only by their
stated convention; this one departs from it deliberately, and its header
says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015VR1VC4SDGxHZQQsQvPBaA
@tap
tap merged commit 82543d6 into main Oct 8, 2026
28 checks passed
@tap
tap deleted the claude/sample-rate-expansion-strategies-ezqzu6 branch October 8, 2026 01:28
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