DSP Explorables
Pitch shifting and time stretching
Play a record at the wrong speed and two things change at once: the music gets faster, and it gets higher. A sampler (a synthesiser that plays back recordings) relies on exactly that, to get every note on the keyboard from one recording. But very often we want only one of the two: a podcast at 1.5× speed without the squeaky voices, a song in a different key at the same tempo, or a singer’s flat note nudged up without the note getting shorter.
This page starts with the sampler, and with why speeding up a recording also changes the character of a voice. Then it builds up, one method at a time, to changing the duration and the pitch independently. It leans on three earlier pages:
- Changing the sample rate, for reading a recording at any speed.
- Pitch detection, for finding the cycles of a voice.
- The Fourier transform, for the phase vocoder’s spinning arrows.
Every figure can use your own voice. Record a few seconds here, ideally with a note or two held steady, and choose your recording in any figure.
Nothing recorded yet.
Nothing is uploaded: the recording stays in this page, in your browser, and is gone when you leave it.
1 · A sampler: one recording, any pitch
Section titled “1 · A sampler: one recording, any pitch”A semitone is the step between neighbouring keys on a piano. Twelve of them make an octave, which doubles the frequency, so one semitone multiplies it by . To play a stored note semitones higher, a sampler reads through the recording faster, by a factor of
Up 7 semitones (a fifth), it moves on 1.498 stored samples for every sample it outputs. It keeps a running position, the phase accumulator, which usually lands between two stored samples:
position = 0.0for each output sample: output = read_between_samples(stored, position) position += r # may change on every sample: bends, vibrato, glidesHow to read_between_samples is the whole question, and it’s the question of the
resampling page, with one twist: the ratio isn’t fixed. A pitch bend or
vibrato changes it on every output sample. The answer from that page’s polyphase section still works,
though. A table of finely spaced sub-filters lets each output sample pick the one for its own fractional
position, whatever the ratio.
A stored note played back at another pitch. The default is a sparse, bright tone: C5, with 42 harmonics 523 Hz apart, all equally loud, up to 22 kHz. Top: a close-up of the stored samples (grey), the curve each method reads between them (blue), and where the output samples fall (orange). Bottom: the output’s spectrum. Blue is energy at the note’s harmonics, which belongs there. Red is everything else. The readout gives the red energy relative to the blue.
- Drop-sample takes the stored sample at or before the position, a staircase. At +7 semitones the unwanted energy is −1.6 dB, almost as loud as the note itself.
- Linear draws straight lines between samples: −6.0 dB.
- Windowed sinc (Kaiser-windowed, 32 zero crossings each side): −101.6 dB.
Now try +12. Drop-sample and linear both measure 0.0 dB, because linear interpolation can’t help with this kind of damage. Only the damage plays just the red part: the output with the note’s harmonics filtered out, turned up, so you hear exactly what the method added. Listen to the glide, and watch the red lines move the wrong way as the pitch rises. Its damage button plays the glide minus the windowed sinc’s glide, since its harmonics move too much to filter out.
Listen for beating, too. When an alias lands close to one of the real harmonics, the two take turns adding up and cancelling, so the sound throbs at their difference frequency. In the glide, the harmonics rise while the aliases fall, so pairs keep crossing, and at each crossing the throb sweeps from fast to slow and back. Towards the top more harmonics fold over at once, and it becomes a warbling siren.
The dense synth note (a C3 sawtooth with 168 harmonics) suffers the same aliasing, but it’s much harder to hear. Its harmonics get weaker as they go up, so the aliases are weaker too: −26.9 dB at +7 with drop-sample. And they land among many loud harmonics, which hide them, the effect called masking on the MP3 page.
Two different things go wrong, depending on the direction:
- Pitching up is decimating. Reading twice as fast doubles every frequency in the recording. Harmonics that end up above the output’s Nyquist frequency (half its sample rate, 22.05 kHz here) can’t be represented, and fold back down as aliases. That’s why they move downwards as the pitch rises. A straight line between samples does nothing to stop them, so the windowed sinc lowers its cutoff in step with the pitch: at +12 semitones it cuts off at half the usual frequency, which takes a filter twice as long, and twice the work per sample.
- Pitching down is interpolating. The output needs samples between the stored ones, and a staircase or straight lines leave the spectral images from the resampling page’s zero-stuffing section. They’re heard as a metallic fizz on low notes.
For both notes, the sinc keeps both below −98 dB at every setting of the slider. On the sparse tone, drop-sample never does better than −10 dB, and linear never better than −16 dB. Even on the dense note, they never get past −33 and −42 dB. Real samplers also have cheaper tricks. A multisample library records a note every few semitones, so nothing is pitched far. Copies of a sound can be stored already filtered, an octave apart, like the band-limited wavetables on the sampling page, and the player picks one by pitch. Some early samplers avoided the maths altogether by giving each voice its own converter, running at a variable clock rate.
2 · Why that isn’t enough
Section titled “2 · Why that isn’t enough”Speeding a recording up raises its pitch, but it also does two other things.
The sound gets shorter. That’s harmless for a single synth note. It’s not acceptable for a melody, whose rhythm changes, or for a song, whose tempo changes.
A voice changes character. Your voice starts as a buzz from the vocal folds, rich in harmonics. It then passes through the throat, mouth and nose, which resonate at a few frequencies set by their shape: the formants. The formants are what make an “ah” an “ah” and an “oo” an “oo”, and they’re part of what makes a voice sound like a particular person. They depend on the shape of the vocal tract, not on the pitch. Sing “ah” on a low note and a high note, and the harmonics move but the formants stay. Speed the recording up, though, and everything moves.
The sung “ah”, played 7 semitones higher by resampling (with the windowed sinc). Top: the original and the sped-up version, on the same time axis. 2.00 s becomes 1.33 s. Bottom: the spectral envelope, the smooth shape that runs along the tops of the harmonics, so that its bumps are the formants. The whole shape slides up: measured, the formants moved ×1.48, along with the pitch’s ×1.498. That’s the chipmunk voice. Going down 7 semitones moves them ×0.67, and gives the slow, heavy “giant”. The sung phrase shows the same: ×1.46 and ×0.67.
This is why sample libraries for pianos and voices record nearly every note rather than stretching a few, and it sets the plan for the rest of the page. Suppose we can make a sound longer without changing its pitch. Then we can shift the pitch without changing the length, in two steps:
So the next four sections are about time stretching. Formants are dealt with in sections 5 and 7.
3 · Time stretching, the naive way: overlap-add
Section titled “3 · Time stretching, the naive way: overlap-add”Here’s the simplest possible idea. Cut the sound into short pieces, called grains. To make it 1.5 times longer, lay them down 1.5 times further apart. Each grain is a perfectly good copy of a short stretch of the original, with its own pitch, so the pitch should be unchanged.
The grains are cut every samples from the input (the analysis hop), and laid down every samples in the output (the synthesis hop).
Done literally, with grains butted end to end, every join is a jump in the waveform, and jumps click. The fix is the one used on the FIR and MP3 pages: windows. Each grain fades in and out with a Hann window, and grains overlap by half, so that the windows add up to exactly 1 and each join is a crossfade. That’s overlap-add (OLA).
To judge the result, the figures from here on use a measure that only works on a steady sound whose contents we know exactly. The sung “ah” contains only the harmonics of D3, plus a little breath noise. The chord contains only the harmonics of its three notes. A perfect stretch would still contain exactly those frequencies, so energy anywhere else is damage. The readout gives that energy relative to the energy at the notes. The original “ah” measures −28.6 dB, which is its breath noise. The chord measures −102.7 dB.
The sung “ah” stretched to 1.5 times its length. Top: three grains (46 ms each), where they’re cut from the input. Middle: where they land, and their sum, which is the output. Bottom: the output’s spectrum, with energy away from the harmonics in red.
- Chopped grains (no window, no overlap): −6.0 dB, and you can hear the clicks.
- Windowed and overlapping: +2.7 dB. There’s now more energy away from the harmonics than on them, and it sounds rough and warbling.
In the middle panel, the grains no longer line up with each other: one grain’s peaks fall on its neighbour’s troughs, and the sum partly cancels. Longer grains (100 ms) measure −14.0 dB on this steady note, but on the phrase they smear the changes, and a stretched voice sounds as if it’s in an echoey room.
The trouble is that the grains are cut at arbitrary points in the waveform’s cycle. In the original, the grain that followed this one started exactly one hop later, so its cycles continued seamlessly. After stretching, the next grain is cut from a point that’s further on in the input but laid down at a point that isn’t. So its cycles start partway through, out of step with what’s already there.
4 · Lining the grains up: WSOLA
Section titled “4 · Lining the grains up: WSOLA”The fix: don’t cut each grain from exactly where the timetable says. Look nearby (within a few milliseconds) for the place where the input looks most like what should come next, and cut it from there instead.
What should come next is easy to say. It’s whatever followed the previous grain in the input, its natural continuation, because that’s what would join on seamlessly. So, for every candidate position in the search range, compare the candidate with the natural continuation by multiplying them sample by sample and adding up: the correlation from the Fourier page, and the same idea as autocorrelation pitch detection. Then take the best match. This is WSOLA, waveform-similarity overlap-add.
The same as before, with a search. The new panel shows how well each shift of the middle grain matches its natural continuation (1 = a perfect match), and the shift chosen (orange).
- With a search of ±7 ms, the “ah” stretched 1.5 times measures −29.4 dB, as clean as the original’s own breath noise (−28.6 dB), and the grains in the middle panel now line up.
- Search range: at ±2 ms it still measures −11.8 dB; from ±3 ms it’s −29.3 dB. The “ah“‘s period is 6.8 ms, and the search needs to span nearly a whole period to be sure of finding the right point in the cycle.
- The chord is where WSOLA struggles: −23.0 dB at 1.5×, and −7.8 dB at 0.75×, against the original’s −102.7 dB. The three notes have different periods, so no single shift lines all of them up.
WSOLA and its relatives are simple, cheap and good for speech and single instruments, which makes them a common choice for playing speech faster or slower. For chords and full mixes, we need something that can treat each frequency separately. That’s the phase vocoder, in section 6. First, though, there’s a way to use the grain idea to change the pitch directly, and keep the formants where they are.
5 · PSOLA: one grain per cycle
Section titled “5 · PSOLA: one grain per cycle”A voiced sound is a series of pulses: each puff of air through the vocal folds sets the vocal tract ringing, and the ring dies away before (or soon after) the next puff. The ring’s shape is the formants. The spacing of the puffs is the pitch.
So, cut the voice into grains one pulse at a time. Each grain is two periods long, centred on a pulse, with a Hann window, so it holds one complete ring. Then:
- Lay the grains down closer together, and there are more pulses per second: the pitch goes up. Further apart, and it goes down.
- Each grain keeps its own shape, so the ring and its resonances are untouched: the formants stay put.
- To change the duration, use some grains twice, or skip some, while keeping the new spacing.
That’s PSOLA, pitch-synchronous overlap-add. It needs to know where every pulse is: the pitch marks. They come from the pitch detection page. YIN’s pitch track says how long each period is. The first mark of a voiced stretch goes on the biggest peak of its first cycle. Each later mark goes about one period on, wherever the cycle around it best matches the cycle around the previous mark (searching a quarter of a period either way). That keeps every mark at the same point of its cycle, even when the peaks are flat or there are two of similar height. Where the sound is unvoiced (“s”, breath), there are no pulses, and the grains are just copied at a fixed 10 ms spacing.
Top: the input, its pitch marks (green), and two grains (blue, orange). Middle: the output, with grains laid down at the new spacing. Bottom: the spectral envelope before and after.
- Up 5 semitones, the “ah“‘s pitch measures 146.8 → 195.8 Hz (×1.333, within 2 cents of the ×1.335 asked). The duration is unchanged, and the formants moved ×1.01. Compare resampling, which moved them ×1.48 for 7 semitones in section 2. Listen to both.
- Stretch changes the length on its own: at ×1.5, 2.00 s becomes 3.00 s at the same pitch.
- The sung phrase, up 5 semitones: pitch ×1.335 and formants ×1.04, from 943 pitch marks (and 112 fixed marks in the unvoiced parts).
PSOLA has been a standard voice tool since the late 1980s, when it was developed for speech synthesis. Its weaknesses come from its assumptions:
- It needs one clear pitch, so it can’t handle chords.
- A misplaced pitch mark gives a rough, jittery sound, which makes it only as good as the pitch detection.
- Copying the same noise grains to stretch an “s” can leave a faint buzz at the copying rate.
- Very large shifts sound unnatural, because a real voice’s pulses also change shape with pitch.
Try your own voice. A clearly voiced, steady recording works best.
6 · The phase vocoder
Section titled “6 · The phase vocoder”The phase vocoder works on the spectrum instead of on the waveform. Cut the sound into short, overlapping, windowed frames, as before, and take the FFT of each. That’s a short-time Fourier transform (STFT), and it’s what a spectrogram shows. Here, frames are 2048 samples (46 ms) long, every 256 samples.
Each FFT bin is a spinning arrow: its length is how much of that frequency is in the frame, and its angle (phase) is where that sinusoid is in its cycle. To stretch, rebuild the sound from the frames laid down further apart: inverse FFT each one, window it again, and overlap-add.
Step 1 of the figure further down does exactly that, and the result is a mess: +6.1 dB away from the harmonics on the “ah”. Each frame’s arrows are at the angles they had in the input, and the input moved on by one analysis hop between frames. The output moves on by a longer hop, so every sinusoid has turned too little for the time that has passed, and the joins don’t fit. It’s the same problem OLA had, now one frequency at a time. The fix is to work out how far each arrow should turn over the longer hop. That needs each component’s true frequency, and the bins don’t give it directly.
A bin’s true frequency, from its phase
Section titled “A bin’s true frequency, from its phase”FFT bins are apart: 21.5 Hz here. A sinusoid at 1050 Hz falls between bins 48 (1033.6 Hz) and 49 (1055.1 Hz). Its magnitude shows up in both, and the magnitude alone can’t say exactly where it is. The phase can. Between two frames samples apart, a sinusoid at exactly a bin’s centre frequency would turn that bin’s arrow by a predictable angle. A sinusoid slightly off-centre turns it by a little more or a little less, and the difference gives its true frequency:
where is the bin’s centre frequency, and is how much further the arrow turned than alone would have turned it (brought into the range −180° to +180°).
Left: bin 49’s arrow in the first frame (grey), where a sinusoid at the bin’s centre would have turned it to by the second frame (orange), and where it actually is (blue). Right: the frequency worked out the same way from each of the 11 bins around the peak. With a hop of 256 samples, the 8 bins from 45 to 52 all give 1050.0 Hz. With 512, only the 4 nearest do. With 1024, only 2. With 64, all 11.
The catch is in “brought into the range”. An angle can’t tell one turn from two, so a bin only gives the right answer if its arrow’s extra turn is less than half a cycle either way. The further a bin is from the true frequency, and the longer the hop, the bigger that extra turn. It’s aliasing again, this time of the phase. That’s why phase vocoders use hops of a quarter of a frame or less: here, an eighth.
Rebuilding with the right phases
Section titled “Rebuilding with the right phases”Now each output frame can get the right phases. Each bin’s arrow is advanced from where it was in the previous output frame by its true frequency × the synthesis hop. Every component then keeps turning at its own speed across the joins. That’s step 2.
Plain propagation has two known artefacts. Bins near the same peak are each advanced on their own, so they drift out of their original relationship, which sounds “phasey” and distant. And a sharp attack, a drum hit, is spread across the frames that contain it. Phase locking (Laroche and Dolson, 1999) fixes part of this. Only the bins at spectral peaks are advanced on their own, and the bins around each peak keep the same phase offsets from it that they had in the input. That’s step 3.
Top: a close-up of the output (for the drum loop: the second kick’s attack, before in grey, after in blue). Bottom: the spectrum, with energy away from the notes in red. All at a stretch of 1.5.
- The chord, which WSOLA couldn’t fix: step 1 measures −0.5 dB, step 2 −29.0 dB (WSOLA: −23.0 dB). At 0.75×, step 2 measures −43.3 dB, against WSOLA’s −7.8 dB.
- The “ah”: step 2 measures −31.0 dB, as clean as the original’s breath noise.
- The drum loop: its kick drums’ attacks (10% to 90% of the peak) average 2.4 ms in the original, 25.4 ms after step 2, and 16.7 ms after step 3. WSOLA keeps them at 2.8 ms.
- On the chord, step 3 is slightly worse (−26.9 dB). Some of its partials are closer together than a bin is wide, for example C4’s 5th harmonic (1308 Hz) and E4’s 4th (1318 Hz). They then share one peak, and locking forces them to keep a single phase relationship.
Commercial time-stretchers combine these ideas. A common approach is to detect attacks and treat them separately: reset the phases there, or copy the attack across unstretched. Others mix in WSOLA-style alignment.
7 · Keeping formants in place
Section titled “7 · Keeping formants in place”The phase vocoder stretches without changing pitch, so with a resampler after it, it shifts pitch without changing duration, as planned in section 2. But resampling still moves the formants, so on its own this gives the chipmunk again, just at the right length.
The fix works one frame at a time. Split each frame’s spectrum into two parts. The envelope is the smooth shape, and is the formants. The fine structure is the harmonics. Then reshape the envelope before resampling, so that the resampling moves it back to where it belongs.
The cepstrum separates the two. Keeping only its low-quefrency end (liftering) gives the envelope. One refinement turned out to matter. A plain cepstral envelope follows the average of the log spectrum, and that includes the noise in the valleys between harmonics. On the “ah”, it dragged the envelope down to a flat line above about 1.5 kHz. So, first, each point of the log spectrum is raised to the highest value within half a harmonic spacing either side. That fills in the valleys, and the smoothed envelope then runs along the tops of the harmonics, which is where the formants really are. (The “true envelope” method in the further reading does this more carefully.)
If the envelope is and the pitch is to be shifted by , every frequency is about to be multiplied by . To end up with the formants moved by instead (with to keep them in place), each frame’s spectrum is multiplied by before resampling.
The phase vocoder (with phase locking), envelope reshaping, then the windowed-sinc resampler. Dashed: the original envelope. Green dots: where it was asked to go. Blue: the result.
- Up 7 semitones with the formants kept in place, the “ah” measures 146.8 → 220.0 Hz (×1.498), formants ×1.00. With the formants moved along with the pitch (+7, +7), it’s the chipmunk again: formants ×1.48.
- Formants alone, pitch unchanged: +5 semitones (asked ×1.33) measures ×1.33, a smaller head. −5 (asked ×0.75) measures ×0.76.
- A giant: pitch −7 and formants −4: pitch ×0.667, formants ×0.80 (asked ×0.79).
The same split, a smooth filter and a source of buzz or hiss, is the basis of how phones code speech. The voice-coder page (coming next) will find the envelope a different way, with linear prediction.
8 · In the real world
Section titled “8 · In the real world”Pitch correction puts the pitch detection page and this one together:
- Detect the pitch (YIN).
- Work out how far each moment is from the nearest note.
- Shift it there (PSOLA).
The retune speed sets how quickly the correction catches up. Slow, and the singer’s scoops into notes and natural vibrato survive. Instant, and every slide snaps from note to note. That’s the robotic, stepped effect heard on Cher’s “Believe” (1998), which made the Auto-Tune plug-in famous.
An out-of-tune singer: four notes sung 25 to 40 cents flat or sharp, with a scoop up into each and a slow drift. Grey: the detected pitch before correction. Blue: after, detected again from the corrected sound. Gridlines are at every note. With a retune speed of 50 ms, the average distance from the nearest note drops from 34 cents to 9. At instant, it’s 3 cents, and the scoops become steps.
Watch the last note. It’s meant to be C4, sung 40 cents flat, but the drift takes it past 50 cents flat for a while. There, B3 is the nearest note, and the correction pulls it down a semitone (24 frames land on B3). Snapping to the nearest note can only guess what the singer meant. Real tools let you set the song’s key, or draw in the intended notes. Try your recording, singing a few held notes.
The same building blocks show up in many places:
- Harmonisers add shifted copies of a voice, a third or a fifth above.
- Key lock on a DJ mixer keeps a track’s pitch while its tempo is changed to match another.
- Speed controls in podcast and video players keep voices natural at 1.5× or 2×.
- Voice changers move formants on their own, to change apparent age or size.
Which method to use is a trade-off:
| Method | Good for | Weak at | Delay it needs |
|---|---|---|---|
| Resampling (section 1) | Synth notes, small shifts | Changes length and formants | A few samples |
| WSOLA | Speech, solo instruments | Chords, full mixes | One grain, plus the search |
| PSOLA | Voices: formants kept | Anything not one clear pitch | A couple of periods |
| Phase vocoder | Chords, full mixes | Attacks, “phasiness” | One frame (here 46 ms) |
Summary
Section titled “Summary”- A sampler reads a stored sound faster or slower, by for semitones. Reading between samples is a resampling problem. A windowed sinc whose cutoff follows the pitch keeps aliases (pitching up) and images (pitching down) below −98 dB, where drop-sample and linear interpolation never do better than −33 and −42 dB, or −10 and −16 dB on a tone with sparse, loud harmonics.
- Resampling also changes the duration, and moves the formants (the chipmunk voice). The plan: stretch the duration without changing the pitch, then resample.
- OLA stretches by spacing out windowed grains, but misaligned cycles partly cancel. WSOLA searches for the best-matching position, which is good for one voice and poor for chords.
- PSOLA uses one grain per pitch period, re-spaced: pitch and duration change separately, and the formants stay put. It needs good pitch marks.
- The phase vocoder measures each bin’s true frequency from its phase advance, and advances it over the new hop. It handles chords. Phase locking reduces phasiness and smearing.
- Formant preservation reshapes each frame’s envelope (from the cepstrum) before resampling. Pitch correction combines detection, snapping to notes, and PSOLA.
Further reading
Section titled “Further reading”- J. L. Flanagan and R. M. Golden, “Phase vocoder”, Bell System Technical Journal 45 (1966): where it started.
- E. Moulines and F. Charpentier, “Pitch-synchronous waveform processing techniques for text-to-speech synthesis using diphones”, Speech Communication 9 (1990): PSOLA.
- W. Verhelst and M. Roelands, “An overlap-add technique based on waveform similarity (WSOLA) for high quality time-scale modification of speech”, ICASSP 1993.
- J. Laroche and M. Dolson, “Improved phase vocoder time-scale modification of audio”, IEEE Transactions on Speech and Audio Processing 7 (1999): phase locking.
- A. Röbel and X. Rodet, “Efficient spectral envelope estimation and its application to pitch shifting and envelope preservation”, DAFx 2005: the “true envelope”.
- J. O. Smith, Digital Audio Resampling Home Page (online): the sinc-table interpolation used by the sampler in section 1.