Files
Tha.Les 2a40dc504e feat(player): playback speed control with pitch preservation (#241)
* feat(player): playback speed control (0.5x to 2.0x)

Adds a speed slider to the transport footer (desktop) and mixer tab
(mobile) so users can slow down or speed up tracks for practice.

- audioEngine: store _playbackRate, apply to new AudioBufferSourceNodes
  on startSources(), and fix getCurrentTime() to account for rate so
  the waveform playhead and loop detection stay accurate at non-1x speeds
- transport: applySpeed() propagates rate to both engine and streaming
  paths; scroll-wheel support (+-0.25 per tick); double-click resets to 1x
- state: playbackSpeed variable + setter; speedEl/speedLabelEl DOM refs
- player: resetSpeed() called in destroyPlayer() so a new track always
  starts at 1x
- mobile: speed slider in mixer transport section, state.speed reset on
  track open

* fix(player): move speed control below play button, centered

* fix(player): tempo bar full-width below transport, TEMPO label + gold slider

* fix(player): center 1.0x on tempo slider (range 0-2, midpoint = 1.0)

* feat(audio): pitch-preserving tempo via SoundTouch AudioWorklet

Voices and instruments no longer pitch-shift when changing playback speed.
A WSOLA time-stretcher runs as an AudioWorkletProcessor on the master bus
so a single node handles all stems. Falls back to tape-effect if the worklet
API is unavailable.

* fix(audio): close array literal in Promise.all ([]) was missing ]
2026-06-30 11:43:50 +01:00
..
2026-05-04 10:57:08 +01:00