IRCAM Partial Stretch — User Guide

SPEAR‑style partial manipulation for electroacoustic composition. Analyses a selected sound with PM2 (partial tracking engine), then applies frequency‑dependent time operations to individual partial tracks and resynthesises via additive synthesis. Five modes: Spectral Stretch, Band Stretch, Freeze, Partial Thin, Spectral Blur.

Author: Shai Cohen Affiliation: Department of Music, Bar‑Ilan University, Israel Version: 1.1 (2026) License: MIT License Repo: GitHub
Contents:

What this does

Partial Stretch implements SPEAR‑style partial manipulation for electroacoustic composition. The pipeline:

  1. Analyse the input sound with PM2 (McAulay–Quatieri sinusoidal tracking) to extract partial tracks (time, frequency, amplitude, phase).
  2. Apply a mode‑specific transformation to the partial tracks:
    • Spectral Stretch – stretch upper partials only, leave lower partials intact.
    • Band Stretch – three independent stretch factors for low/mid/high frequency bands.
    • Freeze – sustain a spectral snapshot as a drone.
    • Partial Thin – keep only every Nth partial above a frequency threshold.
    • Spectral Blur – smooth amplitude envelopes over time.
  3. Resynthesise via additive synthesis (sum of sinusoids) with block‑normalised gain.
Key features v1.1:
  • Stratified track selection – picks top partials from each frequency band, ensuring upper partials are not drowned out by low‑frequency energy.
  • Dual sub‑frame parsing – correctly handles PM2’s two overlapping sub‑frames per time step.
  • Block‑normalised resynthesis – prevents amplitude pumping and maintains consistent loudness.
  • Frequency‑adaptive processing – stretch factors apply to individual tracks based on their mean frequency.

Quick start

  1. Install PM2 (McAulay–Quatieri partial tracking engine) and set the pm2Dir$ variable in the Praat script to point to its bin folder.
  2. Place the Python helper script partial_stretch.py in the plugin_AudioTools/py/ folder.
  3. In Praat, select exactly one Sound object (mono or stereo).
  4. Run script…Partial_Stretch.praat.
  5. Choose a Mode:
    • Spectral Stretch, Band Stretch, Freeze, Partial Thin, Spectral Blur
  6. Adjust mode‑specific parameters (split frequency, stretch factors, freeze time, etc.).
  7. Set Max_partials (number of partial tracks to keep).
  8. Click OK. Praat exports WAV, calls Python, which runs PM2 analysis, processes partials, resynthesises, and imports the result as originalname_ps_modename.
Tip: For sustained sounds (pads, strings, organ), Spectral Blur creates evolving textures. For percussive material, Partial Thin can create sparse, spectral “sieve” effects.
Important: PM2 is a separate command‑line tool (McAulay–Quatieri partial tracking). The script expects pm2.exe in the specified folder. Processing time depends on the number of partials and sound duration – for a 10‑second sound with 200 partials, analysis takes 5–15 seconds.

PM2 partial tracking

🎛️ McAulay–Quatieri sinusoidal modelling

PM2 (Partial Modelling 2) implements the classic McAulay–Quatieri algorithm for sinusoidal analysis. It decomposes a sound into a set of partial tracks – each track is a sinusoid that evolves over time with its own frequency, amplitude, and phase trajectory.

The analysis parameters:

  • Window size – determines frequency resolution (default 46.44 ms, ≈ 2048 samples at 44.1 kHz).
  • Hop size – time resolution (default 5 ms).
  • Max partials – maximum number of simultaneous sinusoids per frame (default 200).

PM2 outputs a text file with frames (time) and partial data (index, frequency, amplitude, phase). This script parses the output, merges the two sub‑frames that PM2 generates, and selects a stratified subset of tracks (by frequency band) to keep the most salient partials across the spectrum.

Stratified track selection: Instead of selecting the top N tracks by amplitude (which tends to pick only low‑frequency partials), the script divides the spectrum into 7 bands (0–300, 300–600, 600–1000, 1000–2000, 2000–4000, 4000–8000, 8000–20000 Hz) and picks the top few from each band. This guarantees that upper partials are represented in the resynthesis.

Operation modes (5)

band_lo_hz), mid (band_mid_hz), and high bands.。
ModeDescriptionKey parameters
Spectral Stretch
Band Stretch
Freeze
Partial Thin
Spectral Blur

All modes preserve the original frequencies of partials (pitch is unchanged unless the time stretch indirectly affects pitch – which it does not, as time stretching a partial track changes its duration but not its frequency).

Parameters & defaults

Mode‑specific parameters

ModeParameterRangeDefaultDescription
Spectral Stretchsplit_frequency_Hz50–100001000
upper_stretch_factor1.0–10.03.0
Band Stretchband_lo_hz, band_mid_hz50–10000500, 2000
band_lo_stretch, band_mid_stretch, band_hi_stretch0.5–10.01.0, 2.0, 4.0
Freezefreeze_time0–10.5
freeze_duration0.1–605.0
Partial Thinthin_above_hz100–100001000
thin_every_n2–102
Spectral Blurblur_window_ms10–1000100

Analysis parameters

ParameterRangeDefaultDescription Max_partials10–500200。 Analysis_window_ms10–20046.44。 Hop_ms1–505.0。

Additive resynthesis

Additive synthesis formula:
y(t) = Σi Ai(t) · sin(2π·fi(t)·t + φi(t))
where Ai(t) and fi(t) are linearly interpolated between analysis frames.

The resynthesis engine:

For the Freeze mode, the resynthesis uses the frozen partials directly – frequencies are constant, amplitudes follow a fade‑in/fade‑out envelope.

Visualization (Praat picture)

When Draw_visualization = 1, the script draws a 5‑panel figure:

Tip: Compare the input and output spectrograms to see how the partial manipulation changed the spectral evolution. For Spectral Stretch, upper partials should appear stretched in time; for Freeze, the output should be a steady drone.

FAQ / troubleshooting

“pm2.exe not found”

Update the pm2Dir$ variable in the Praat script to point to your PM2 installation folder (the one containing pm2.exe). PM2 can be downloaded from the McAulay–Quatieri partial tracking repository or from the SPEAR website.

Analysis produces 0 tracks / all tracks silent

Check that the sound has enough energy and is not silent. Increase Max_partials (e.g., to 300) and reduce Analysis_window_ms (e.g., to 30 ms) for better time resolution. The PM2 output may still be parsed correctly – the diagnostic output in the Python log shows how many frames and tracks were found.

Resynthesis sounds noisy / has clicks

The additive resynthesis uses linear amplitude interpolation and block‑normalised gain. If clicks persist, increase Hop_ms (smoother transitions) or reduce Analysis_window_ms (better time resolution). The block normalisation may also cause sudden gain changes – the script applies a 0.1 s smoothing kernel to the gain envelope to mitigate this.

Stratified track selection

Without stratification, the top 200 partials by amplitude are almost always the 200 strongest low‑frequency sinusoids. The stratified method divides the spectrum into 7 bands and selects top partials from each band, ensuring that high‑frequency partials are preserved even if their amplitude is lower. This is essential for spectral stretch and band stretch modes to work correctly on high partials.

Time stretching vs. pitch shifting

Partial Stretch does not change the frequency of partials – it only changes their duration. Stretching a partial track makes it last longer, but the frequency contour is preserved. This means the overall pitch of the sound stays the same, but the temporal evolution of spectral components is altered. This is analogous to “freezing” or “smearing” the spectral content without changing its harmonic relationships.

PM2 dual sub‑frames

PM2 outputs two interleaved sub‑frames per time step (to track both sinusoids and noise). The parser correctly merges these sub‑frames so that all partials are considered together. Track IDs are not reused across sub‑frames, so tracks are identified by their ID number only.