What's Changed
This release completes the engine rewrite: the old push-based streaming engine and the hybrid batch stretcher are deleted (ROADMAP Stages 8–9, net −22.9k lines), leaving the pull engine as the only engine — serving real-time and batch through one graph. The vestigial EDM preset system goes with it, beat analysis gets two measured accuracy fixes, and keylock becomes a live, click-free engine parameter. Published on crates.io as timestretch 0.8.0.
Breaking Changes — old engine deleted
- Removed:
StreamProcessor,StreamingEngine,StreamProfile,ControlPath,StreamLatencyReport,StreamPitchQuality,TransientResetStats,HybridStretcher,MultiResolutionStretcher,Wsola,StereoMode, thestreammodule, andStretchParams::{stereo_mode, with_stereo_mode, with_stream_profile} - Batch/offline (
stretch,stretch_into,stretch_buffer) is rebased onto the engine graph with exact output length; streaming and offline are now sample-identical by construction (tests/streaming_offline_determinism.rs) timestretch-clidrops--streaming/--chunk-size- The live keylock chain drops its phase-vocoder corrector entirely — owner listening rejected the PV at every threshold it was placed behind (measured: PV loses 2.5–3.9 dB top octave vs SOLA's ~1 dB at ±10% rate), so beat-synchronous SOLA carries the whole corrected range and the PV engages only past the correction fade end (22% rate deviation), inaudible by construction. Keylock WCET mean drops ~3× (0.026 vs ~0.08 of budget; p99.9 = 0.30 at 64-frame callbacks, strict CI gate)
- Offline low-band contract (owner decision):
stretch()shares live keylock semantics — within the corrected range (~0.833–1.25) content below the 150 Hz crossover follows tempo in pitch, offline exactly as on a deck; wide ratios render on the batch PV path with full-spectrum pitch preservation - Old-engine QA harnesses deleted; the quality dashboard is the engine matrix, re-anchored on absolute thresholds derived from new-engine measurements
Breaking Changes — EDM presets removed
- Removed:
EdmPreset,StretchParams::with_preset, the CLI--presetflag, and the dead tuning fields none of which ever reached the pull engine (hop_size,wsola_*,beat_aware,band_split,multi_resolution,elastic_*,hpss_enabled,residual_*,crossfade_mode, and friends —CrossfadeModegoes with them) - Migration:
VocalChop's one live effect survives aswith_envelope_preset(EnvelopePreset::Vocal), or--envelope vocalon the CLI; the other presets need no replacement - The analytic tonal fast path in
stretch()(which only fired with a preset set) is deleted; pure tones now render through the real engine
Live Keylock Switching (New)
EngineController::set_keylock(bool)/keylock_target(): toggle high-band pitch correction during playback with a ~12 ms per-sample crossfade to delay-matched varispeed — no engine rebuild, no gap; SOLA stays warm while bypassed so re-engage is instant and converged- The desktop deck's Tape/Keylock combo now switches instantly at constant latency
Beat Analysis Accuracy
- Onset/beat detection latency compensated: markers used to sit ~29 ms before the audible attack (FFT-window timestamp convention). Measured bias on a ground-truth 125 BPM kick train: −31.6 ms → −2.6 ms; on a real 320 kbps EDM track: −29 ms → −1.7 ms.
PREANALYSIS_VERSIONbumps to 4; older cached sidecars regenerate automatically - BPM estimation switches to the median of K-beat-baseline intervals, telescoping away a cyclic frame-grid sawtooth that read flat tracks ~0.2% high: 125.23 → 125.03 (synthetic 125.000 train), 125.22 → 124.99 (real 125.0 EDM track) — the displayed number no longer drifts a beat every ~8 minutes when beatmatching
Desktop Deck
- Audible CDJ-style waveform scrub: dragging the zoomed waveform plays a raw varispeed scratch voice that chases the pointer (pitch follows hand speed, both directions), with release momentum (τ = 150 ms exponential glide) that lands bit-exactly on a pre-computed frame and crossfades back into the engine time-aligned
- Grid-quantized auto-loop: one-press 4-beat loop snapped to the beat grid, with halve/double resizing from 1/8 to 32 beats
- README screenshot recapture is now a repeatable skill (
desktop/.claude/skills/readme-screenshot)
Toolchain
- MSRV raised from 1.82 to 1.85; crate and desktop app move to Rust edition 2024 (enables cargo's MSRV-aware resolver v3)
- Development toolchain pinned to Rust 1.97.0 via
rust-toolchain.toml; CI stable jobs build with the pinned compiler (the MSRV job still tests 1.85.0) - The
web/WASM demo is removed — it targeted the deleted old-engine API and no longer compiled (last present at22e5117)
Full Changelog: v0.7.0...v0.8.0