Skip to content

v0.7.0

Latest

Choose a tag to compare

@robmorgan robmorgan released this 13 Jul 22:17
8284b53

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

  • BeatGrid is rebuilt around a piecewise tempo model instead of a single BPM: beats changes from Vec<usize> to Vec<f64> (fractional-sample positions, the separate beats_fractional field is gone), and it gains downbeats, segments: Vec<TempoSegment>, confidence, and downbeat_confidence
  • detect_bpm/detect_beat_grid move 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_options narrows the range or hints a genre, and analyze_for_dj keeps 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, or Result in the audio path. EngineController writes tempo through a lock-free timestamped mailbox (set_tempo_rate_at lands a retarget on an exact output sample); SourceProducer feeds 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_analysis attaches a PreAnalysisArtifact so 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.rs holds 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 range
  • detect_beat_grid_with_options: detect_beat_grid with explicit tracking options
  • TempoSegment (crate root): a piecewise-constant tempo stretch (start_beat, bpm), serialized in the PreAnalysisArtifact and used as BeatGrid'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), plus tests/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.rs gains a TIMESTRETCH_RUBBERBAND_ENGINE=new mode for comparison

Full Changelog: v0.6.0...v0.7.0