8‑Channel Speed Deviations

Introduce subtle (or extreme) per‑channel playback‑rate variations to an octo (8‑channel) sound. Model independent tape/wow/flutter behavior, ensemble detune, or spatial chorus—while keeping the system phase‑aware and time‑aligned.

Author: Shai Cohen Affiliation: Department of Music, Bar‑Ilan University, Israel Version: 0.1 (2025) Praat
Contents:

What this does

The script varies the instantaneous playback speed of each of the eight channels around unity (1.0×). By default it uses high‑quality resampling with fractional‑delay interpolation. You can drive the speed by constants, LFOs, random walks, or imported envelopes—either independently per channel or linked in groups (e.g., front pair, rear pair).

Typical uses: ensemble detune in surround, tape wow/flutter, spatial chorus/diffusion, peri‑channel drift to reduce combing in downmixes.

Quick start

  1. In Praat, select an 8‑channel Sound (octophonic bed).
  2. Run script…8-channel speed deviations.praat.
  3. Choose mode (Constant, LFO, RandomWalk, Envelope).
  4. Set depth (±% or cents) and rate_hz if applicable.
  5. Select coupling (Linked pairs / Quads / Independent) and duration_policy.
  6. Enable normalize if desired. Click OK.

Concepts

Varispeed vs. Time‑Stretch

Varispeed factor r(t): changes both pitch and duration.
Time‑stretch aims to change duration with minimal pitch shift (phase‑vocoder).

For musical chorus‑like spread, varispeed is usually preferred. For film beds that must stay in tune, use pitch‑preserving mode.

Deviation Units

Deviation Modes

🎛️ Constant

Fixed per‑channel factor (e.g., small spreads like ±5 cents).

🌊 LFO

Sinusoidal or triangle modulation around 1.0×: r_i(t) = 1 + d_i · sin(2π f_i t + φ_i).

🎲 Random Walk

Low‑rate wander with step size and bound; optionally filtered (1/f) for tape‑like drift.

📈 Envelope

Use user‑defined breakpoint functions (time, factor) per channel or copied across a group.

Parameters

ParameterTypeDefaultDescription
unitoptionpercentpercent | cents | ppm
modeoptionLFOConstant | LFO | RandomWalk | Envelope
depthreal0.5Peak deviation in chosen units (global default)
rate_hzreal0.6LFO/Flutter rate (per‑channel overridable)
waveoptionsinesine | triangle | random‑hold
rand_stepreal0.02Random‑walk step (units/sec)
rand_boundreal1.0Max absolute deviation (units)
pv_time_stretchbooleannoPitch‑preserving mode (phase‑vocoder)
duration_policyoptionend_lockedfree_run | end_locked
interpoptioncubiclinear | cubic | sinc (if available)
normalizebooleanyesPeak‑normalize to norm_target
norm_targetreal0.99Peak target
seedinteger00 = auto; otherwise reproducible deviations
reportbooleannoPrint per‑channel factors over time and headroom

Per‑Channel Controls

ParameterTypeDefaultDescription
depth_chCSV""Override depth per channel (8 values)
rate_chCSV""Override LFO rate per channel
phase_ch_degCSV""Initial phase per channel
envelopesText/CSV""For Envelope mode: list of (t,r) pairs per channel

Blank CSVs inherit the global setting. Use “copy L→R” helpers to mirror values within pairs.

Coupling & Groups

Define how channels relate. For an octo bed (L, R, C, LFE, Ls, Rs, Lrs, Rrs) you might:

ParameterTypeDefaultDescription
couplingoptionpairspairs | quads | independent | custom
pair_phase_degreal180Phase offset within each pair
custom_matrixtext""8×8 coupling matrix (0..1) for correlation between channels

Presets

🎻 Ensemble detune (musical)

unit=cents, mode=Constant, depth_ch= -7,-3,0,+3,+7,-5,+2,-2; pv_time_stretch=no; normalize=yes

📼 Tape wow/flutter (film bed)

unit=percent, mode=LFO, rate=0.6, depth=0.2, wave=sine; coupling=pairs with 180°; pv_time_stretch=yes (to preserve pitch)

🌬️ Spatial chorus wide

unit=cents, mode=LFO, rate_ch=0.2,0.21,0.23,0.19,0.31,0.29,0.27,0.25; depth=6; coupling=independent

🧭 Slow drift (installation)

mode=RandomWalk, rand_step=0.002, rand_bound=0.6 (percent), seed=1234; end_locked; normalize=0.99

Workflow & QA

  1. Channel order: Verify your octo order. Mis‑ordered beds will image incorrectly downstream.
  2. Set duration policy: For sync‑critical work, use end_locked. For creative drift, free_run.
  3. Gain staging: Enable normalize and leave 1–2 dB headroom when combining with other beds.
  4. Mono/downmix check: If downmixing to stereo later, prefer pair/quad coupling to reduce comb filtering.
  5. Render notes: Export with the original sample rate to minimize resampling cascades.

Edge Cases & Safeguards

Math

Speed Factor & Pitch Relation

Percent: r = 1 + d/100. Cents: r = 2^{(c/1200)}. PPM: r = 1 + p·10^{-6}.
Instantaneous time map: τ_i(t) = ∫_0^t r_i(u) du. Output y_i(t) = x_i(τ_i(t)).

End‑Locked Warping

Let T be original length. Compute τ_i(t) then affine‑normalize: τ̂_i(t) = τ_i(t)·(T / τ_i(T)) so τ̂_i(T)=T.

Random Walk

Δr_i[n] ~ 𝒩(0, σ^2); r_i[n] = clip(r_i[n-1] + Δr_i[n], 1-d_max, 1+d_max).
Optionally low‑pass filter r_i for tape‑like drift.

Phase‑Vocoder Stretch (pitch‑preserving)

Analyze STFT X(k,n). For target rate r_i(t), resample phase increments Δφ and magnitudes with phase unwrapping; synthesize via overlap‑add. (Heavier CPU.)

Performance Notes