Introduction

Play a recording at half speed and the voice drops an octave — that eerie, slowed-down growl beloved by horror films. Speed it up and everyone sounds like a chipmunk. For decades, changing duration and changing pitch were inseparably coupled: sample rate was destiny.

The phase vocoder breaks that link. By transforming a signal into the frequency domain using the Fast Fourier Transform, it separates when each frequency happens from what that frequency is. You can then resynthesise the signal at any speed you choose, keeping every pitch exactly where it was.

The trick is subtle and elegant: instead of repeating or dropping raw audio samples, the algorithm tracks the instantaneous phase of each frequency component across successive analysis frames and advances it at exactly the right rate for the new tempo. The result is smooth, natural-sounding time-stretched audio — the same technology in every professional DAW, music-education app, and video-game engine that needs to play back audio at variable speeds.

Try It: Stretch a Tone

The demo below synthesises a short chord, runs it through a simplified phase vocoder, and lets you choose how much to stretch or compress it. The waveform display shows both the original and the time-scaled output.

<!-- {{c_html_intro}} -->
<p class="hint">{{hint_para}}</p>
<div class="controls">
  <label>{{label_stretch}} <strong id="stretchVal">1.0×</strong>
    <input type="range" id="stretchSlider" min="0.25" max="2.0" step="0.05" value="1.0">
  </label>
</div>
<div class="canvas-wrap">
  <div class="canvas-label">{{label_original}}</div>
  <canvas id="origCanvas" width="560" height="100"></canvas>
  <div class="canvas-label">{{label_output}}</div>
  <canvas id="outCanvas" width="560" height="100"></canvas>
</div>
<div class="status" id="status">{{status_idle}}</div>
<div class="btns">
  <button id="btnRun" type="button">{{btn_run}}</button>
  <button id="btnPlay" type="button" class="ghost" disabled>{{btn_play}}</button>
  <button id="btnReset" type="button" class="ghost">{{btn_reset}}</button>
</div>
/* {{c_css_intro}} */
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; padding: .5rem; }
.hint { font-size: .88rem; color: #444; margin: 0 0 .7rem; line-height: 1.45; }
.controls { margin-bottom: .6rem; }
label { display: flex; flex-direction: column; gap: .25rem; font-size: .9rem; font-weight: 600; }
input[type=range] { width: 100%; max-width: 400px; cursor: pointer; }
.canvas-wrap { display: flex; flex-direction: column; gap: .25rem; margin: .5rem 0; }
.canvas-label { font-size: .78rem; font-weight: 700; color: #1d3557; text-transform: uppercase; letter-spacing: .04em; }
canvas { width: 100%; height: 100px; border-radius: 8px; background: #e8eef3; display: block; }
.status { font-size: .95rem; font-weight: 600; min-height: 1.4em; margin: .4rem 0; color: #1d3557; }
.status.ok { color: #0a7d33; }
.status.bad { color: #c92f3c; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem;
         border: 1px solid #1d3557; background: #1d3557; color: #fff;
         border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
button:disabled { opacity: .45; cursor: not-allowed; }
// Code not found

Notice that the pitch stays constant even when the duration changes dramatically. The phase vocoder achieves this by advancing each frequency bin's phase by exactly the amount needed to maintain phase coherence — no more, no less. Compare this with what a naive approach (simply repeating chunks) would sound like: you would hear audible clicks at the boundaries between repeated blocks.

How It Works

The phase vocoder has three stages: analysis, manipulation, and synthesis.

Analysis — slicing into frames

The input signal x[n]x[n] is windowed into overlapping frames of length NN with a hop size HaH_a (analysis hop). Each frame is transformed by the DFT to give a complex spectrum XkX_k with magnitude Xk|X_k| and phase ϕk\phi_k.

Phase advance — the core trick

Between two successive analysis frames separated by HaH_a samples, the expected phase advance for bin kk is

Δϕk=2πkHaN\Delta\phi_k = \frac{2\pi k H_a}{N}

The actual measured advance Δϕ^k\Delta\hat{\phi}_k will differ by a small deviation δk\delta_k (the "instantaneous frequency error"). The instantaneous frequency of bin kk is

ωk=2πkN+δkHa\omega_k = \frac{2\pi k}{N} + \frac{\delta_k}{H_a}

To synthesise at a stretch factor α\alpha (e.g.\ α=0.5\alpha = 0.5 for half-speed), the synthesis hop is Hs=αHaH_s = \alpha H_a. The output phase for each bin is accumulated as

ψkψk+ωkHs\psi_k \leftarrow \psi_k + \omega_k \cdot H_s

The output frame is reconstructed by inverse DFT using the original magnitudes Xk|X_k| but the new accumulated phase ψk\psi_k. Overlap-add reassembles the frames into the final signal.

Why this preserves pitch

Pitch depends only on frequency, and the frequencies ωk\omega_k are unchanged — only the rate at which frames are spaced changes. Doubling α\alpha doubles the duration while the signal's spectral content remains identical.

Artefacts and improvements

The basic algorithm introduces phasiness on transients and harmonic sounds because different partials of the same harmonic are advanced independently, scrambling their relative phases. Refinements such as phase locking (Laroche & Dolson, 1999) and transient detection (mark transients, skip phase accumulation, copy frames verbatim) produce the clean results heard in professional tools.

Where It Matters

The ability to decouple duration from pitch turns up in almost every corner of modern audio:

  • Music production: DJ software, DAWs (Ableton, Logic, Pro Tools) use phase vocoders to synchronise loops to the project tempo without retiming the original recording.
  • Film and podcast post-production: dialogue replacement, ADR, and podcast speed-up (listen at 1.5× without the chipmunk effect) all rely on time-scale modification.
  • Music education and transcription apps: slow a guitar solo to 50% speed so a student can follow each note while the pitch stays in the original key.
  • Game engines: adaptive music systems stretch cues to fill scenes of variable length; speech in cut-scenes can be stretched to match dubbed-language timing.
  • Hearing aids and accessibility tools: real-time time-dilation lets wearers slow incoming speech without pitch distortion.
  • Scientific analysis: bioacoustics researchers slow ultrasonic bat calls into the audible range — the phase vocoder keeps harmonic relationships intact for species identification.

The same STFT machinery also underlies pitch shifting (change the bin indices without changing hop size), robot-voice effects, and the auto-tune family of algorithms that correct vocal pitch after recording.

Conclusion

The phase vocoder is a beautiful illustration of what happens when you take a signal apart into its frequency components: dimensions that seem inseparable in the time domain — how long a sound lasts versus how high it is — become fully independent handles you can turn at will.

Next time you listen to a slowed-down guitar solo on a music app, or a podcast at 1.5× without anyone sounding like a chipmunk, you are hearing the phase vocoder at work: carefully accumulating phase bin by bin so that every frequency arrives at exactly the right moment, stretched smoothly across whatever duration you choose. It is the Fast Fourier Transform doing its most musical trick.

Share this article

Pick a channel — or use your device's native share sheet.

Comments

Loading comments...

https://www.kipuhub.com/en/article/phase-vocoder/Content licensed under CC BY-NC 4.0.