What's Changed
This release lands the first cutover milestone of the varispeed-first engine rewrite: a new pull-based, allocation-free real-time engine that reaches 9/9 parity against the old streaming engine on the A/B quality matrix, plus a rebuilt general-purpose tempo tracker. Published on crates.io as timestretch 0.7.0.
Breaking Changes
BeatGridis rebuilt around a piecewise tempo model instead of a single BPM:beatschanges fromVec<usize>toVec<f64>(fractional-sample positions, the separatebeats_fractionalfield is gone), and it gainsdownbeats,segments: Vec<TempoSegment>,confidence, anddownbeat_confidencedetect_bpm/detect_beat_gridmove from an EDM-tuned 100–160 BPM detector to a general-purpose autocorrelation tempogram (50–220 BPM, soft log-normal octave prior, no hard folding) — detected values on existing material may shift;detect_beat_grid_with_optionsnarrows the range or hints a genre, andanalyze_for_djkeeps its 100–160 hint
Pull-Based Real-Time Engine (New)
A new engine module (src/engine/) implementing the ROADMAP's inverted, varispeed-first architecture — coexists with the existing StreamProcessor/StreamingEngine surface (frozen, unaffected) rather than replacing it yet.
- Pull-based RT core:
EngineProcessor::process(&mut [f32])fills exactly the requested frames — no allocation, locks, orResultin the audio path.EngineControllerwrites tempo through a lock-free timestamped mailbox (set_tempo_rate_atlands a retarget on an exact output sample);SourceProducerfeeds the source ring from the host thread - Varispeed-first keylock: sinc-resampler tempo head → LR8 band split at 150 Hz → un-keylocked low band (delay-matched pure delay, pitch follows tempo) + pitch-corrected high band, re-summed with a corrected true-allpass LR8 (the legacy crossover's −6 dB re-summation notch stays quarantined with the frozen engine)
- Two warm high-band correctors with hysteretic, phase-aligned handoff: beat-synchronous time-domain SOLA across the full DJ range (raised to ±9% rate deviation on owner listening — the small-FFT PV audibly loses top octave beyond it), phase vocoder (FFT 512/hop 128) beyond that, fading to plain varispeed at extreme rates (12–22%)
- Artifact-first control:
EngineConfig.pre_analysisattaches aPreAnalysisArtifactso SOLA splice placement and PV phase resets steer around real onsets, with online spectral-flux fallback when no artifact is attached - Deck semantics: allocation-free warm-start seek/loop-wrap priming (
EngineController::warm_start) with declick, timestamped tempo control, gapless loop wraps - WCET gates in CI: PV corrector renders at most one hop per block by construction;
qa/engine_wcet.rsholds p99.9 callback cost ≤ 0.5× budget (measured ≤ 0.20 at 64-frame callbacks)
Final A/B matrix campaign closed the three rows the old engine still won:
| row | old engine | new engine |
|---|---|---|
| cents_p95_ride4 | 1.86 | 0.23 |
| hf_retention_db_108 | −0.79 dB | −0.41 dB |
| env_swing_db_cross11 | 10.36 dB | 0.65 dB |
Also measured: kick transient sharpness ~70% sharper than the old engine (1.21 vs 0.68 at ±4% rate), ±8% cents ride p95 dropped to 0.57 (old 12.19), and click-free modulation torture at 1.5x/1.1x theoretical slew (tape) / 3x/1.3x (keylock) vs the old engine's 6x/1.5x bound.
Tempo Tracking Rewrite (New)
TempoTrackingOptions(crate root): tune the tempo search range, octave-prior center/width, or add a soft genre hint rangedetect_beat_grid_with_options:detect_beat_gridwith explicit tracking optionsTempoSegment(crate root): a piecewise-constant tempo stretch (start_beat,bpm), serialized in thePreAnalysisArtifactand used asBeatGrid's tempo model- Autocorrelation tempogram with harmonic reinforcement feeds a rewritten Viterbi/DP beat tracker that follows tempo drift instead of assuming a fixed BPM
QA & Tooling
- New engine gate suites:
qa/engine_keylock.rs,qa/engine_transients.rs,qa/engine_wcet.rs,qa/engine_ab.rs/qa/engine_ab_matrix.rs(machine-readable old-vs-new parity dashboard), plustests/engine_latency.rs,tests/engine_modulation_torture.rs,tests/engine_realtime_allocations.rs tests/beat_tracking.rs: new accuracy suite for the tempogram tracker- Public, redistributable 9-track DJ corpus (Creative Commons netlabel tracks, pinned SHA-256) wired into the BPM accuracy harness alongside the private corpus — surfaced two detector misses (1.46% and 1.38%) the private corpus never caught
- RubberBand comparison anomaly explained: the historic ~-24 LUFS / ~0.15-similarity rows on chirp/sweep content were the frozen offline hybrid driver (
src/stretch/hybrid.rs) attenuating uniformly ~28 dB whenever a preset was set, independent of the new engine;qa/rubberband_comparison.rsgains aTIMESTRETCH_RUBBERBAND_ENGINE=newmode for comparison
Full Changelog: v0.6.0...v0.7.0