Time and pitch
Change speed without pitch, pitch without speed, and fit audio to an exact length.
Slowing a recording down also lowers its pitch, because that is how playback speed works. Time stretching changes the length and keeps the pitch; pitch shifting changes the pitch and keeps the length. BoxLang Audio does both in plain Java with WSOLA (waveform similarity overlap-add).
music = audioOsc( "saw", audioFreq( "A3" ), 4 );
faster = audioStretch( music, 1.25 ); // 25 percent faster: 3.2 s, same pitch
slower = audioStretch( music, 0.8 ); // 5 s, same pitch
exact = audioFitTo( music, 3.5 ); // exactly 3.5 seconds
up = audioPitch( music, 3 ); // a minor third higher, still 4 s
octave = audioPitch( music, -12 ); // an octave lower
| Function | Range | Does |
|---|---|---|
audioStretch( audio, rate ) | 0.25 to 4 | Speed factor. 2 is twice as fast and half as long |
audioFitTo( audio, seconds ) | any | Stretch to an exact length |
audioPitch( audio, semitones ) | plus or minus 24 | Shift the pitch, length unchanged |
How well does it work
WSOLA cuts the audio into overlapping windows of about 50 ms and lays them out again at a new spacing, each shifted a little to where it lines up best with the one before. That keeps tone and transients natural for moderate changes:
- Within about 25 percent the result is clean on music and speech. Past that, expect some roughness on dense chords and a slight echo on sustained notes.
- Changes beyond 2 times or under 0.5 times are made in two passes.
- Pitch shifting stretches by the opposite amount and then plays the result at the new speed. The character of a voice (its formants) moves with the pitch, so a voice shifted far sounds like a different, smaller or larger, person.
Cutting music to a video
audioFitTo is for matching a picture. If the music is much too short, loop part of it instead of stretching it a long way: build a loop with audioLoopify and repeat it.
Command line
bx-audio stretch cue.wav cue-fit.wav --seconds=30
bx-audio stretch cue.wav slower.wav --rate=0.8
bx-audio pitch song.wav lower.wav --semitones=-2