HPSS Phase Vocoder — v2.0 User Guide

High‑quality time‑stretching via Harmonic‑Percussive Source Separation (HPSS) + phase vocoder. Harmonic content is stretched with the phase vocoder; percussive/transient content is resampled – no metallic smearing.

Author: Shai Cohen Affiliation: Department of Music, Bar‑Ilan University, Israel Version: 2.0 (2025) – Distribution‑ready License: MIT License Repo: GitHub
Contents:

What this does

HPSS Phase Vocoder performs time‑stretching that preserves the clarity of transients. Traditional phase vocoders smear attacks, producing metallic artefacts when stretching percussive material. This engine first separates the signal into harmonic (sustained tones) and percussive (transients) components using median‑filtering HPSS. The harmonic part is stretched with a high‑quality phase vocoder (instantaneous frequency accumulation), while the percussive part is resampled directly, preserving attack sharpness. The two are recombined into a clean, artefact‑free stretched result.

Why HPSS + phase vocoder? The percussive resampling path avoids the vocoder’s phase‑locking on transients, which causes smearing. The harmonic path uses a vocoder with instantaneous frequency estimation for smooth, natural‑sounding tonal stretching. The result is time‑stretched audio that sounds far more natural, especially for music, speech with plosives, or any sound with strong attacks.

Quick start

  1. In Praat, select exactly one Sound object (mono or stereo).
  2. Run script…HPSS_Phase_Vocoder.praat.
  3. Choose a Preset:
    • Gentle (x1.3), Medium (x1.5), Extreme (x2.0), Half speed (x2.0, large window), Compress (x0.75), Fast preview (small window)
  4. For custom mode (preset = Custom), set:
    • Stretch_factor – ratio (0.1–10, <1 = compress, >1 = stretch)
    • FFT_size – STFT window size (256–8192)
    • HPSS_margin – separation sharpness (1–10)
  5. Click OK. Praat exports WAV, runs Python engine, and imports the result as originalname_hpss_xN.NN.
Tip: For material with strong transients (drums, percussion), use a larger FFT size (4096 or 8192) and a moderate margin (3.0). For speech, the default settings work well. Half speed preset uses a larger window for cleaner stretching at x2.0.
Important: Python dependencies: numpy, scipy, soundfile. No librosa required. The engine uses a custom STFT/ISTFT implementation with Hann window and overlap‑add normalisation.

The 6 presets (+ Custom)

PresetStretchFFT sizeMarginDescription
Gentle (x1.3)1.340963.0Mild stretch, good for speech.
Medium (x1.5)1.540963.0Moderate stretch, balanced.
Extreme (x2.0)2.040963.0Double speed – obvious but clean.
Half speed (x2.0, large window)2.081924.0Double length, large FFT for smoother harmonics.
Compress (x0.75)0.7540963.0Shorten duration while preserving pitch.
Fast preview (small window)1.520482.5Smaller FFT for quicker processing (lower quality).

Pipeline — HPSS + phase vocoder

Stage 1 – STFT – forward STFT with Hann window, hop = FFT_size / 8.
Stage 2 – HPSS (median filtering) – separate magnitude spectrogram into harmonic (horizontal smoothing) and percussive (vertical smoothing).
Stage 3 – Masks – soft Wiener‑style masks with margin exponent p: mask_H = H^p / (H^p + P^p).
Stage 4 – Harmonic path – phase vocoder with instantaneous frequency estimation; stretch factor applied.
Stage 5 – Percussive path – inverse STFT of percussive spectrogram → waveform, then resample to target length (preserves transients).
Stage 6 – Recombine – add harmonic and percussive waveforms, normalise to input peak, write output.

HPSS details

Phase vocoder details

Parameters & defaults

Custom parameters (when Preset = Custom)

ParameterRangeDefaultDescription
Stretch_factor0.1–101.5Ratio of output duration to input. <1 = compress, >1 = stretch.
FFT_size256–81924096STFT window size. Larger = better frequency resolution, slower.
HPSS_margin1–103.0Separation sharpness. Higher = more aggressive HPSS masks.

Output

ParameterDefaultDescription
Draw_visualizationyesShow waveforms, spectrograms, and summary in Praat picture.
Play_resultyesAuto‑play after processing.

Visualization (Praat picture)

When Draw_visualization = 1, the script draws:

Tip: The H/P ratio (harmonic RMS / percussive RMS) gives a quick sense of the source material. High ratio = tonal, low ratio = noisy/percussive.

FAQ / troubleshooting

“Python not found” or missing packages

Install: pip install numpy scipy soundfile. On Windows, the script uses py (Python launcher).

Output has metallic artefacts / transients still smeared

Try increasing HPSS_margin (e.g., 4.0 or 5.0) to separate harmonic/percussive more aggressively. Also ensure FFT_size is large enough (4096 or 8192) to capture low‑frequency detail. For very percussive material, the percussive resampling path should preserve attacks – if not, check that the HPSS masks are capturing transients correctly (the hp_ratio stat gives a clue).

Output is clipped or distorted

The engine normalises the output to the input peak level. If the stretched signal has higher instantaneous peaks due to phase alignment, clipping may occur. Reduce the input level slightly before processing.

Processing is slow

The phase vocoder and HPSS median filters are the main cost. Reduce FFT_size for faster processing (at the cost of quality). The “Fast preview” preset uses FFT=2048 for quicker iteration.

Stats file

The stats file (temp_hpss_stats.txt) contains detailed information: stretch factor, FFT size, hop, margin, durations, RMS values (input, output, harmonic, percussive), output peak, and H/P ratio. This is used in the visualisation and can be inspected for quality assessment.

How the HPSS margin works

The margin parameter p appears in the mask formula: mask_H = H^p / (H^p + P^p). When p=1, it's a simple ratio; as p increases, the mask becomes a “hard” decision: if H > P, mask_H → 1; if H < P, mask_H → 0. This gives sharper separation but may introduce artefacts. The default 3.0 is a good balance.