Skip to content

desktop: persisted waveform-peaks cache + async load path - #34

Merged
robmorgan merged 2 commits into
mainfrom
desktop/waveform-cache
Aug 4, 2026
Merged

desktop: persisted waveform-peaks cache + async load path#34
robmorgan merged 2 commits into
mainfrom
desktop/waveform-cache

Conversation

@robmorgan

Copy link
Copy Markdown
Owner

Summary

Track loads no longer freeze the UI, and analyzed tracks load near-instantly on relaunch.

  • .tspeaks binary sidecar persists the 3-band peaks pyramid's base level (u8-quantized, versioned 60-byte header). Keyed by the same mono-signal FNV hash as the .tsanalysis.json sidecar, so renamed and retagged files keep their cache. Corrupt/truncated/mismatched files silently recompute and rewrite; writes are temp+rename atomic. Upper pyramid levels rebuild from the cached base via the existing halving loop.
  • Async load path: decode, peaks, and pre-analysis all run on a background worker; results install through an mpsc channel polled each frame, guarded by the existing analysis_generation counter (rapid successive loads discard stale results). The file panel shows a spinner while decoding.
  • Grid unification: the UI beat grid now derives from the pre-analysis artifact (grid_from_artifact), deleting the duplicate synchronous detect_beat_grid_buffer pass — beat detection runs once per load, and BPM appears instantly on a sidecar hit.

Zero new dependencies; no library changes.

Testing

  • 21 new unit tests: cache corruption matrix (magic/version/rate/hash/length/truncation/trailing garbage), quantization roundtrip, atomic-write temp cleanup, grid adapter, and headless load-worker tests against a hand-written WAV fixture (message ordering, cache hits, decode errors, stale generations).
  • cargo test --all-targets (68 passed), cargo clippy --all-targets -- -D warnings, cargo fmt --check — all clean in desktop/.
  • Live app verification on macOS: cold load computes and writes the sidecar (10,860 bytes for the 12 s test track — exactly header + 6×1800 buckets); relaunch logs Peaks: using cached sidecar; playback runs with zero underruns; a truncated sidecar triggers silent recompute and rewrite.

🤖 Generated with Claude Code

robmorgan and others added 2 commits August 4, 2026 13:20
Track loads no longer freeze the UI: decode, peaks, and pre-analysis all
run on a background worker, with results installed through a channel
polled each frame under the existing analysis-generation guard.

- New .tspeaks binary sidecar persists the base pyramid level
  (u8-quantized, versioned header, keyed by the same mono-signal FNV
  hash as the .tsanalysis.json sidecar, so renames and retags keep the
  cache). Corrupt or mismatched files silently recompute and rewrite;
  writes are temp+rename atomic.
- Upper pyramid levels rebuild from the cached base via the existing
  halving loop (BandPeaks::from_base_level).
- The UI beat grid now derives from the pre-analysis artifact
  (grid_from_artifact), eliminating the duplicate synchronous
  detect_beat_grid_buffer pass; BPM lands instantly on a sidecar hit.
- File panel shows a spinner while decoding / awaiting analysis.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Stage 12's fuzz/no-panic scope only listed the artifact JSON loader; the
new binary peaks-cache reader is the same class of untrusted-input
parser and belongs on the list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@robmorgan
robmorgan merged commit fe11694 into main Aug 4, 2026
10 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.

1 participant