Expand description
Pitch-preserved audio time-stretch (WSOLA), pure Rust, no C.
Change the tempo of an audio stream without changing its pitch - speed a podcast to 1.5x without the chipmunk effect. The engine is WSOLA (Waveform Similarity Overlap-Add): a time-domain method that is real-time capable, good on speech, and far simpler than a phase vocoder.
§Why WSOLA (and how it works)
Naive tempo change resamples - playing samples faster shifts pitch up. WSOLA instead cuts the input into overlapping frames, lays them back down at a different spacing (closer together to speed up, further apart to slow down), and overlap-adds them with a Hann window. Placing frames at a new spacing changes duration; keeping each frame’s samples untouched preserves pitch. The “WS” part is the trick that avoids clicks: before laying down each frame, it searches a small window of nearby input positions for the segment whose waveform best continues the previous frame, so the overlap-add joins coherent waveforms instead of fighting phases.
With a periodic Hann window at 50% overlap the windows sum to unity, so at
tempo 1.0 (and a zero-offset match) the output reconstructs the input.
§Streaming API
TimeStretch is a streaming processor over interleaved f32 frames. Feed
decoder output with push, pull stretched frames for
the sink with pull, and flush
at end of stream. Tempo is settable mid-stream.
use wsola::TimeStretch;
let mut ts = TimeStretch::new(44_100, 2).unwrap();
ts.set_tempo(1.5); // 1.5x faster, same pitch
ts.push(&[0.0f32; 4096]); // interleaved stereo frames from the decoder
let out = ts.pull(1024); // interleaved frames for the output sinkFor a whole buffer at once, use the stretch convenience function.
Structs§
- Config
- Tuning for the WSOLA windows, in milliseconds.
Config::defaultis a good starting point for speech; largerhop_msis smoother but smears transients, largersearch_msimproves waveform matching at the cost of CPU. - Time
Stretch - A streaming, pitch-preserving time-stretcher over interleaved
f32frames.
Enums§
- Error
- Errors from constructing or driving a
TimeStretch.
Constants§
- MAX_
TEMPO - See
MIN_TEMPO. - MIN_
TEMPO - Lowest and highest tempo the stretcher will honor;
TimeStretch::set_tempoclamps to this range.
Functions§
- stretch
- Time-stretch a whole interleaved buffer in one call: pitch-preserved tempo
change by
tempo. Equivalent tonew+set_tempo+push+pull+flush, and a good first port of call for offline use and tests.
Type Aliases§
- Result
- Convenience alias for results from this crate.