@audio/stretch [](https://github.com/audiojs/stretch/actions/workflows/test.yml) [](https://www.npmjs.com/package/@audio/stretch) [](https://github.com/audiojs/stretch/blob/main/LICENSE)

July 10, 2026 · View on GitHub

Time stretching algorithms — umbrella over @audio/stretch-* atoms.

AtomAlgorithmDomainQualityCPUBest for
@audio/stretch-wsolaWSOLAtime★★★lowspeech, real-time
@audio/stretch-psolaPSOLAtime★★★★mediumspeech, monophonic instruments
@audio/stretch-pvocplain phase vocoderfreq★★mediumeducational baseline
@audio/stretch-pvoc-lockphase-locked vocoderfreq★★★★mediumgeneral music
@audio/stretch-pghiphase-gradient vocoderfreq★★★★mediumvibrato, glides, chirps
@audio/stretch-transienttransient-aware vocoderfreq★★★★★mediummusic with percussion
@audio/stretch-hybridHPSS hybridfreq+time★★★★highfull mixes — drums over tonal
@audio/stretch-paulstretchPaulStretchfreqmediumextreme stretch (ambient, drones)
@audio/stretch-smsSinusoidal Modelingsinusoidal★★★★highharmonic / tonal material

For pitch shifting, see the @audio/shift-* family.

Usage

Install the umbrella (all atoms):

npm install @audio/stretch
import { transient, wsola } from '@audio/stretch'

let slower = transient(samples, { factor: 2 })          // 2× slower, same pitch
let fast   = wsola(samples, { factor: 0.75 })           // 1.33× faster

let write = transient({ factor: 1.5 })                  // real-time streaming
write(block1)
write(block2)
write()                                                  // → remaining samples

Or install just the atom you need — each is self-contained:

npm install @audio/stretch-transient
import transient from '@audio/stretch-transient'
let out = transient(samples, { factor: 2 })

Float32Array in/out; a channel array [L, R] (or Float64Array) is accepted and processed per channel — parity with @audio/shift. Output sizes may be variable — small or empty early chunks are normal in streaming.

Time domain

wsola@audio/stretch-wsola

Waveform Similarity Overlap-Add. Divides signal into overlapping frames and places them at new synthesis positions, but before placing each frame searches ±delta samples for the read position that maximizes cross-correlation with the natural progression of the previous grain through the input — eliminating the phase cancellation (flanging) of plain OLA. No FFT overhead.

import wsola from '@audio/stretch-wsola'

wsola(data, { factor: 1.5 })
wsola(data, { factor: 0.5, delta: 512 })
ParamDefault
factor1Time stretch ratio
frameSize2048Window size
hopSizeframeSize/4Hop between frames
deltaframeSize/4Search range (±samples)

Use when: Speech, real-time with tight CPU budgets, moderate ratios (0.5–2×).
Not for: Polyphonic music with sustained tones — frequency-domain methods handle harmonics better.

psola@audio/stretch-psola

Pitch-Synchronous Overlap-Add. Detects pitch period via autocorrelation, then windows grains at pitch cycle boundaries. Because grains align with the pitch cycle there are no phase discontinuities at overlaps — cleaner than WSOLA for monophonic pitched signals.

import psola from '@audio/stretch-psola'

psola(data, { factor: 1.5 })
psola(data, { factor: 0.75, sampleRate: 48000 })
psola(data, { factor: 2, minFreq: 100, maxFreq: 400 })  // male voice range
ParamDefault
factor1Time stretch ratio
sampleRate44100For pitch detection frequency range
minFreq80Lowest expected pitch (Hz)
maxFreq500Highest expected pitch (Hz)

Use when: Speech, solo vocals, monophonic instruments, factors 0.5–2×.
Not for: Polyphonic material — autocorrelation finds one pitch period so chords get mangled. Extreme ratios (>2×) cause gaps.

Frequency domain

pvoc@audio/stretch-pvoc

Plain phase vocoder. Each bin's phase advances at its instantaneous frequency independently. Magnitudes are preserved but incoherent inter-harmonic phase relationships give complex signals a diffuse, "underwater" quality.

import pvoc from '@audio/stretch-pvoc'
pvoc(data, { factor: 2 })
ParamDefault
factor1Time stretch ratio
frameSize2048FFT size (power of 2)
hopSizeframeSize/4Hop between frames

Use when: Educational baseline, simple tonal signals.
Not for: General music — use pvoc-lock or transient.

pvoc-lock@audio/stretch-pvoc-lock

Phase-locked vocoder (Laroche & Dolson, 1999). After propagating phases, locks non-peak bins to their nearest spectral peak's rotation. Restores harmonic phase coherence, eliminating phasiness.

import pvocLock from '@audio/stretch-pvoc-lock'
pvocLock(data, { factor: 2 })

Same options as pvoc.

Use when: General music — tonal/ambient material where transient resets aren't needed.
Not for: Percussive material where attacks matter — use transient.

pghi@audio/stretch-pghi

Phase Gradient Heap Integration — "Phase Vocoder Done Right" (Průša & Holighaus, 2017). Synthesis phase is integrated from the analysis phase gradients, visiting bins in magnitude order via a max-heap: no peak picking, no transient heuristics; chirps, vibrato and glides stay coherent by construction.

import pghi from '@audio/stretch-pghi'

pghi(data, { factor: 2 })
ParamDefault
factor1Time stretch ratio
frameSize2048FFT size (power of 2)
hopSizeframeSize/8Hop — gradient integration wants dense frames
tolerance1e-6Bins below tolerance×max get random phase

Use when: modulated material — vibrato, glissandi, pitch-unstable sources.
Not for: steady polyphony — pvoc-lock's identity locking reproduces intra-partial phases exactly where gradient integration only approximates them.

transient@audio/stretch-transient

Transient-aware phase-locked vocoder (Röbel, 2003). Measures spectral flux between frames; on a sharp onset it resets to the original analysis phase instead of propagating it, preserving attack sharpness on drums and plucks. Implies phase locking.

import transient from '@audio/stretch-transient'

transient(data, { factor: 2 })
transient(data, { factor: 1.5, transientThreshold: 2.0 })  // less sensitive detection
ParamDefault
factor1Time stretch ratio
frameSize2048FFT size (power of 2)
hopSizeframeSize/4Hop between frames
transientThreshold1.5Spectral flux threshold (higher = fewer resets)

Use when: The right default for most music — percussion, mixed sources.
Not for: Voice/speech — use psola. Extreme stretch — use paulstretch.

hybrid@audio/stretch-hybrid

Harmonic/percussive hybrid (Driedger & Müller). Median-filter HPSS splits the spectrogram into two layers; the harmonic layer goes through the phase-locked vocoder, the percussive layer through short-frame OLA — chords stay coherent and attacks stay sharp, where one algorithm must trade one for the other.

import hybrid from '@audio/stretch-hybrid'

hybrid(data, { factor: 2 })
ParamDefault
factor1Time stretch ratio
frameSize2048FFT size for HPSS + harmonic path
percFrame512OLA frame for the percussive layer
harmMedian17Median filter across time (frames)
percMedian17Median filter across frequency (bins)

Use when: full mixes — drums over tonal material.
Cost: separation + two stretches ≈ 4–6× the CPU of pvoc-lock alone.

paulstretch@audio/stretch-paulstretch

Extreme time stretching via phase randomization (Nasca, 2006). Preserves magnitudes but replaces all phases with random values, producing smooth, dreamlike textures. Designed for large factors.

import paulstretch from '@audio/stretch-paulstretch'

paulstretch(data, { factor: 8 })
paulstretch(data, { factor: 100, frameSize: 8192 })
ParamDefault
factor`8$\text{Time} \text{stretch} \text{ratio} (\text{best} >2 \times )
$frameSize`4096FFT size (larger = smoother)
seed0x1f123bb5PRNG seed (deterministic output)

Use when: Ambient music, sound design, drone generation, 8×–1000× stretch.
Not for: Small ratios (<2×) — sounds washed out. Not for preserving rhythm or transients.

Sinusoidal

sms@audio/stretch-sms

Sinusoidal Modeling Synthesis (Serra 1989, McAulay-Quatieri 1986). Decomposes audio into individually tracked sinusoidal partials and resynthesizes at the new time rate. Each partial's frequency and magnitude are interpolated independently — no phase spreading or bin-by-bin artifacts.

import sms from '@audio/stretch-sms'

sms(data, { factor: 2 })
sms(data, { factor: 0.5, maxTracks: 80 })
sms(data, { factor: 3, frameSize: 4096 })
ParamDefault
factor1Time stretch ratio
frameSize2048FFT frame size
hopSizeframeSize/4Hop between frames
maxTracks60Max simultaneous sinusoidal tracks
minMag1e-4Peak detection threshold (linear)
freqDev3Max frequency deviation (bins) for track continuation
residualMix1Stochastic residual blended into the sinusoidal output

Use when: Harmonic / tonal content — instruments, chords, vocals — where the phase vocoder introduces smearing. Default residualMix=1 blends breath, noise, and transient energy alongside the sinusoidal model.
Not for: Noise-dominated material.

Quality metrics — @audio/quality

Every atom is self-contained (framing/OLA helpers inlined; the phase-locking engine lives in @audio/spectral-pvoc). Output quality is evaluated with @audio/quality:

import { lsd, spectralSim, chordBalance, chordRetention, modulationDepth } from '@audio/quality'

lsd (log-spectral distance), spectralSim (cosine similarity), chordBalance, chordRetention, and modulationDepth (AM depth per partial) evaluate algorithm output against a reference.

Research & comparison

CommandWhat it does
node scripts/compare.jswrites compare.html — interactive waveforms, playback, internal-vs-external comparisons
node scripts/bench.jsthroughput and ×realtime numbers for batch and streaming
node scripts/diagnose.jstargeted diagnostics for specific algorithm behaviors

Demo for a lightweight browser listening matrix.

See also

References

  • Verhelst, W. & Roelands, M. (1993). "An overlap-add technique based on waveform similarity (WSOLA)." ICASSP.
  • Laroche, J. & Dolson, M. (1999). "Improved phase vocoder time-scale modification of audio." IEEE Trans. Speech Audio Processing.
  • Röbel, A. (2003). "A new approach to transient processing in the phase vocoder." DAFx.
  • Nasca, P. (2006). "PaulStretch — extreme time stretching." paulnasca.com.
  • Moulines, E. & Charpentier, F. (1990). "Pitch-synchronous waveform processing techniques for text-to-speech synthesis using diphones." Speech Communication, 9(5-6).
  • Driedger, J. & Müller, M. (2016). "A review of time-scale modification of music signals." Applied Sciences, 6(2).
  • Serra, X. (1989). "A System for Sound Analysis/Transformation/Synthesis Based on a Deterministic plus Stochastic Decomposition." PhD thesis, Stanford.
  • McAulay, R.J. & Quatieri, T.F. (1986). "Speech analysis/synthesis based on a sinusoidal representation." IEEE Trans. ASSP, 34(4).

MIT