Skip to content

Improve beat acquisition and genre accuracy behind expanded corpus - #90

Merged
brxs merged 9 commits into
mainfrom
issue-77-beat-detection
Jul 10, 2026
Merged

Improve beat acquisition and genre accuracy behind expanded corpus#90
brxs merged 9 commits into
mainfrom
issue-77-beat-detection

Conversation

@brxs

@brxs brxs commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Closes #77.

This improves the Rust beat estimator's acquisition speed and genre coverage while preserving its blank-when-unsure contract.

  • locks a versioned 20-clip / 534-second corpus through Git LFS, with deterministic regeneration metadata, SHA-256 hashes, coverage validation, and a model-free verifier
  • records the unchanged shipping baseline and owner-approved targets before changing production code
  • ships the corpus-selected adaptive detector: complementary six-second band-flux and spectral-flux views, impulsiveness-based arbitration, and a two-second change probe with corroboration and recovery quarantine
  • applies the same detector to live streams and decoded-track analysis without moving work onto the realtime audio callback or changing the published analysis surface
  • documents the decision in ADR-0035, the rejected candidates, final per-clip measurements, clean-checkout reproduction, and completed hardware validation

Measured result

Metric Unchanged estimator This PR Approved gate
Worst required rhythmic acquisition 20 s or never 9 s <= 10 s
House -> dub recovery 16 s 8 s <= 8 s
Dub -> house recovery 15 s 1 s <= 8 s
Wrong steady / intro / beatless seconds 0 0 0
Wrong tempo-change seconds 1 / 3 1 / 0 <= 1 each

The final harness processes all 534 seconds in about 1.9 seconds (roughly 280x realtime on the validation machine). Every approved profile passes, including breakbeat/jungle, swung/2-step, sparse/minimal percussion, delayed rhythmic intros, opposed tempo changes, and the legacy beatless controls.

Implementation

  • Main evidence:
    • six-second band-split log-energy flux
    • six-second spectral flux from a reused 2048-frame FFT buffer
    • spectral priority only when onset impulsiveness clears the measured threshold
    • band fallback only when spectral evidence is absent or metrically agrees
  • Change handling:
    • a two-second spectral probe never displays directly
    • two mutually consistent contradictions are required while the main detector still confidently holds the old metrical clock
    • the first contradiction consumes the permitted one stale tick; the second blanks and quarantines the stale long-window result
    • reacquisition resumes only after the main detector and a confident probe agree
  • Gate agreement now uses the corpus's existing binary/ternary metrical levels within 8%, while preserving three-stable acquisition and one-miss grace.
  • rustfft 6.4.1 is pinned directly rather than used transitively.
  • FFT spectra and scratch buffers are reused; all estimator work remains on the existing non-realtime analysis thread.
  • AnchorGate, phase-anchor input, IPC/store state, engine callback, reset ordering, and downstream fallback contracts remain unchanged.

There are no prompt-, filename-, or genre-specific production branches.

Corpus and review checkpoints

The commit history deliberately preserves the measurement-first workflow:

  1. expand and lock the corpus
  2. measure the unchanged shipping estimator
  3. approve numeric targets
  4. accept ADR-0035
  5. ship the selected estimator and hard regression gates
  6. document and complete native/hardware validation

The committed corpus contains 20 stereo PCM16 / 48 kHz WAVs (97.8 MiB): ten immutable legacy fixtures, six new genre fixtures, two short-intro scenarios, and two opposed tempo-change scenarios. Missing fixtures, LFS pointer files, hash drift, invalid WAV contracts, incomplete coverage, unapproved targets, or metric regressions fail explicitly.

Reproduce it with:

backend/.venv/bin/python backend/scripts/spike_beat_corpus.py --verify
cd src-tauri
cargo test analysis::beat_corpus::the_expanded_spike_corpus_meets_approved_targets -- --nocapture

Validation

  • just check
    • Ruff format/check
    • ESLint and TypeScript
    • Clippy across the workspace with warnings denied
    • 176 backend tests
    • 572 frontend tests
    • 210 Rust shell tests (one timing diagnostic ignored)
    • 109 Rust engine tests
  • git lfs fsck: pass
  • model-free corpus verifier: 20 clips / 97.8 MiB pass
  • fresh local clone + git lfs pull + frontend build + verifier + approved corpus test: pass
  • native mrt2_small session on MacBook Pro Speakers at 48 kHz:
    • real house stream acquired 130.13 BPM at 0.881 confidence
    • 35-second ambient/no-drums stream remained blank
    • stop cleared BPM, confidence, and live beat immediately
  • completed owner listening checklist: acquisition, both tempo-change directions, model-switch reset, phase meter, synced echo, beat-quantised loops/freeze pads, two-deck audio, and CPU behaviour all pass

Documentation

  • docs/spike-beat-detection-issue-77.md — unchanged baseline, target derivation, candidate matrix, and final per-clip results
  • docs/adr/0035-dual-envelope-beat-detection-with-fast-change-invalidation.md — selected architecture and tradeoffs
  • docs/issue-77-hardware-checklist.md — native and owner listening evidence
  • .plans/issue-77-beat-estimator-acquisition-and-genre-accuracy.md — completed plan and retrospective

@brxs
brxs merged commit 34de825 into main Jul 10, 2026
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.

Improve the beat estimator: acquisition speed and genre accuracy, behind an expanded corpus

1 participant