Search guides and the APICtrl K
  1. API reference
  2. DSP

phase_vocoder.h

The phase vocoder: pitch shifting without the grain.

#include <sonore/phase_vocoder.h>
On this page

Design notes

pitch.h's PitchShifter is two read heads crossfading on a delay line, and it sounds like it -- a faint tremolo at the crossfade rate, a comb when the two heads carry the same partial. The phase vocoder does the job in the frequency domain, where every partial can be moved on its own and resynthesised with a phase advanced by exactly what its new frequency needs, so there is no crossfade to hear.

The method is Laroche & Dolson's ("Improved phase vocoder time-scale modification of audio", IEEE TSAP 1999), and specifically two of its ideas together:

PEAK SHIFTING. The naive route is time-stretch by the ratio, then read the stretched signal back faster. It needs a resampler, its synthesis hop is a non-integer that has to be dithered, the overlap-add level moves with the ratio and -- the part that matters to a host -- the latency depends on the ratio HISTORY, because a reader lagging the writer by a fixed distance in the stretched signal lags it by distance/ratio in input time. Instead each spectral peak's REGION is moved along the frequency axis by the ratio and resynthesised at the same hop it was analysed with: no resampler, an exact overlap-add, and a latency of exactly Size at every ratio, which is what the plugin reports.

IDENTITY PHASE LOCKING. The bins around a peak are not each given their own freely-running phase -- that is where the classic "phasiness" comes from -- but keep the phase RELATIONSHIP they had to the peak in the analysis frame. The peak carries the propagation, advanced by its true frequency times the ratio; the neighbours ride with it. Regions are split at the magnitude minimum between adjacent peaks, found once per frame in a single pass rather than re-searched per bin.

The overlap-add is normalised the way stft.h does it -- the summed squared window at each position within a hop -- so the identity ratio gives the input back and every other ratio comes out at the level it went in.

Included by dsp.h. Depends on Fft<> from fft.h.

Types 1

template <size_t Size = 2048, size_t Overlap = 4> class PhaseVocoder

SIZE: about 120 KB at the defaults (a 2048 FFT with its tables, the rings and the per-bin phases). A member of the plugin, never a local. 2048 / 4 at 48 kHz: 43 ms frames, 11 ms hop, 43 ms latency. Overlap 8 costs twice the FFTs and buys smoother phase tracking on large upward shifts.

↑↓ to move↵ to openEvery public name in the headers, and every guide