Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ which of its decisions were superseded. Read PLAN.md before implementing anythin
re-derive decisions it has already settled (compile-time direction, profile vocabulary, the
three-leg test strategy, the pinned-eps cross-validation design).

Current state: **v0.1 (M6 complete), M7a measurement harness landed.** Design/schedule/tables
(M2), the streaming converter for float/Q15/Q31 with committed scipy reference vectors (M3/M4),
the golden cross-validation against SampleRateTap at pinned eps (M5, test-only submodule), the
bluetooth_bridge example + C ABI + executed demo notebook (M6), and the embedded CI matrix +
instruction-count ratchet (M7a: Cortex-M33/M55 + Hexagon under QEMU, eight fixed workloads gated
two-sided ±3% against `bench/baselines.json` — `scripts/icount.py`). Next: the M7 levers, one
measured PR each, superblock codegen first — see PLAN.md section 7. Any change that moves a
workload's count beyond ±3% must re-record baselines (`icount.py --update` per target) in the
same PR; an *improvement* beyond tolerance fails the gate too, by design.
Current state: **v0.2 — M7 codegen phase complete.** v0.1 (M0–M6): design/schedule/tables, the
streaming converter for float/Q15/Q31 with committed scipy reference vectors, the golden
cross-validation against SampleRateTap at pinned eps (test-only submodule), bluetooth_bridge +
C ABI + executed notebook. M7 (v0.2): the embedded CI matrix + instruction-count ratchet
(Cortex-M33/M55 + Hexagon under QEMU, eight workloads gated two-sided ±3% against
`bench/baselines.json` — `scripts/icount.py`), then three measured codegen levers — superblock
walk, committed trip counts, symmetry-halved tables — outputs bit-identical throughout; PLAN.md
section 7 records each lever's numbers. Remaining levers are deferred until a consumer pulls
them (they change the output contract). Any change that moves a workload's count beyond ±3%
must re-record baselines (`icount.py --update` per target) in the same PR; an *improvement*
beyond tolerance fails the gate too, by design.

## The charter constraints (load-bearing)

Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.24)
project(RatioTap VERSION 0.1.0 LANGUAGES CXX)
project(RatioTap VERSION 0.2.0 LANGUAGES CXX)

# ==============================================================================
# RatioTap — synchronous 44.1 <-> 48 kHz sample rate conversion, as fast as
Expand Down
17 changes: 12 additions & 5 deletions PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,18 @@ executed (it measures the shipping C++, not a Python re-implementation).
(Hexagon down_q31 +2.7%); Arm came out slightly ahead (M33 Q31 −2.5%).

v0.1 ships at M6. Nothing in M7+ blocks it. **Status: M0–M6 complete —
v0.1 shipped (2026-07-23). M7a measurement harness + M7b superblock
codegen + M7c committed trip counts + M7d symmetry halving landed
(2026-07-23/24); next lever candidates: multistage decomposition,
minimum-phase economy variant, or the M33 float story if a consumer
needs it.**
v0.1 shipped (2026-07-23). M7 codegen phase complete — v0.2 (2026-07-24):
M7a measurement harness, M7b superblock codegen, M7c committed trip
counts, M7d symmetry halving, all measured, outputs bit-identical
throughout. Cumulative vs the M7a baselines: M55 Q15 −59%/−60% and float
−35%/−37%; M33 Q31 −26%/−27%, Q15 −15%/−16%; Hexagon Q15 −13%/−10%,
Q31 −15%/−7%; table storage halved. The remaining levers (multistage
decomposition, minimum-phase economy, IIR pre-filter, FFT offline path)
all change the output contract or serve currently-unpressured needs
(storage, latency) — deferred until a consumer pulls them: a latency
need pulls minimum-phase; a storage need pulls multistage; an MCU float
consumer pulls the accumulation-contract discussion (a DspTap decision,
since double accumulation is the float golden model's identity).**

## 8. Acceptance criteria (v0.1)

Expand Down
28 changes: 17 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,24 @@ on the Tap family's shared FIR substrate
float/Q15/Q31 sample-format traits, measured dot-product kernels, row-sum
quantization, measurement instruments).

> **Status: v0.1 (milestone M6).** The converter is in for all three sample
> formats: float (the golden model, pinned against committed scipy
> reference vectors sample-for-sample), Q31 (tracks float within −147 dB;
> measures 146 dB at 997 Hz — exceeding float, whose float32 I/O is its
> own bound), and Q15 (format-limited: pair it with `economy`, which is
> both cheaper *and* quieter than `transparent` at 16 bits). The golden
> cross-validation against SampleRateTap's async engine at pinned
> eps = L/M−1 agrees to −109 dB (down) / −99 dB (up) over every phase.
> The `bluetooth_bridge` example, the C ABI (`tools/capi/`), and the
> executed demo notebook (`notebooks/ratio_demo.ipynb`) complete v0.1.
> **Status: v0.2 (M7 codegen campaign).** v0.1 shipped the converter for
> all three sample formats: float (the golden model, pinned against
> committed scipy reference vectors sample-for-sample), Q31 (tracks float
> within −147 dB), and Q15 (format-limited: pair it with `economy`, which
> is both cheaper *and* quieter than `transparent` at 16 bits), plus the
> golden cross-validation against SampleRateTap's async engine (−109 dB
> down / −99 dB up over every phase), the `bluetooth_bridge` example, the
> C ABI, and the executed demo notebook. v0.2 is the measured optimization
> campaign on top — four levers, each gated by the instruction-count
> ratchet, outputs bit-identical throughout: the superblock walk,
> committed compile-time trip counts, and symmetry-halved tables. Since
> the campaign's baselines: **Q15 −59%/−60% and float −35%/−37% on
> Cortex-M55, Q31 −26%/−27% on Cortex-M33, Q15 −13%/−10% on Hexagon —
> with table storage halved** (economy Q15 up: 6.9 KiB). The remaining
> PLAN §7 levers (multistage, minimum-phase, IIR, FFT) change the output
> contract and stay deferred until a consumer needs them.
> [PLAN.md](PLAN.md) is the authoritative roadmap (charter, architecture
> decisions, milestones, acceptance criteria);
> decisions, milestones, acceptance criteria, per-lever measurements);
> [HANDOFF.md](HANDOFF.md) is the original design brief it grew from.

## Quick start
Expand Down
2 changes: 1 addition & 1 deletion include/tap/ratio/ratio.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "tap/ratio/schedule.h" // IWYU pragma: export

#define TAP_RATIO_VERSION_MAJOR 0
#define TAP_RATIO_VERSION_MINOR 1
#define TAP_RATIO_VERSION_MINOR 2
#define TAP_RATIO_VERSION_PATCH 0

namespace tap::ratio {
Expand Down
Loading