Skip to content

v0.11.0

Latest

Choose a tag to compare

@robmorgan robmorgan released this 05 Aug 02:34
7ca0984

What's Changed

This release lands wide-range Master Tempo — a second, honest-latency keylock profile covering the engine's full 0.25–2.0 tempo range (ROADMAP Stage 11) — and consolidates per-track analysis into a single .tsa container owned by the library: timestretch 0.11.0 on crates.io.

Breaking Changes

  • timestretch-cli analyze now writes the binary .tsa analysis container by default (<input>.tsa) instead of <input>.tsanalysis.json. An explicit -o out.json keeps the legacy JSON format, and --pre-analysis sniffs magic bytes and accepts either.
  • EngineProfile gains the WideKeylock variant — external exhaustive matches over the enum will need a new arm.
  • Desktop: tracks converge to one .tsa sidecar. Valid legacy .tsanalysis.json artifacts are absorbed into the container on load, and both legacy sidecars (.tsanalysis.json, .tspeaks) are deleted once the on-disk container supersedes them.

Wide-Range Master Tempo (Stage 11)

  • EngineProfile::WideKeylock: a full-spectrum FFT-2048/hop-256 identity-locked phase-vocoder corrector with artifact-driven per-band phase resets, keylocking across tempo rates 0.25–2.0 with no correction fade. Constant pipeline delay of 2144 frames (48.6 ms at 44.1 kHz) — its own honest latency contract alongside the untouched 12.7 ms standard keylock chain.
  • Built on a falsification experiment first: a ±30/±50/±100/−75% listening matrix against varispeed, the shipped wide phase vocoder, and RubberBand references identified the coherence-blend taper as the cause of robotic wide slowdowns (now held at 0.20, settled by live A/B) and 75% overlap as the −75% click/level blowup (hop = FFT/8 eliminates it).
  • Gate suite: strict WCET p99.9 of 0.328 vs the 0.5 budget at 64-frame callbacks, zero-alloc steady state, click-free wide rides and snaps, an exact-constant latency contract gate (≤55 ms), and seven wide A/B matrix gates (steady-state pitch error 0.09–0.50 cents p95).
  • Supporting engine API: PhaseVocoder::set_wide_ratio_coherence_blend, StreamingSincResampler::set_step_anchor (uniform chunks consumed uniformly) and StreamingSincResampler::flush_into (drains the sinc lookahead tail without losing the final half-window), and Stage::warm_start_settle_frames for per-stage warm-start preroll.

.tsa Analysis Container

  • io::tsa: one content-bound chunked binary file per track — a 28-byte identity header (sample rate, mono length, content hash) plus versioned ARTF (pre-analysis artifact) and PEAK (3-band waveform peaks) chunks. Unknown tags and versions skip forward-compatibly; readers reject-don't-panic on hostile input.
  • Two API layers: bytes (AnalysisFile::to_bytes / from_bytes / from_bytes_validated) for apps that store analysis blobs in their own database keyed by content_hash, and sidecar file wrappers (read_analysis_file, read_analysis_file_validated, write_analysis_file, analysis_file_path) with atomic writes.
  • analysis::waveform: the desktop app's 3-band waveform peaks pyramid moved into the library (BandPeaks, PeakLevel, NUM_BANDS) so any frontend gets display peaks without reimplementing the analyzer.
  • read_preanalysis_json / write_preanalysis_json are deprecated (still working) in favor of the container; PreAnalysisArtifact::matches_identity added for callers that already hold the (rate, length, hash) identity.

Desktop

  • Range selector (Standard | Wide) with a seek-priced engine rebuild that preserves the playhead, and a live pipeline-latency readout next to it.
  • Track loads no longer freeze the UI: decode, peaks, and pre-analysis run on a background worker, and analyzed tracks load near-instantly on relaunch via the persisted peaks cache (now stored in the .tsa container).

Full Changelog: v0.10.0...v0.11.0