Fast Spectral Swirl — Multi‑Channel

An STFT‑based effect that circularly rotates and/or permutes spectral bins over time to create shimmering, time‑varying timbres. Designed for speed and for coherent multi‑channel processing.

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

What this does

Per frame, the spectrum is taken via STFT. Bins are circularly shifted and/or phase‑advanced with a rate that can be constant or modulated. The result is a swirling timbre that preserves overall energy while redistributing partials. Multi‑channel handling keeps imaging stable when desired—or purposely decorrelated for wide, spacious effects.

Output: Channel count matches input; use with stereo/5.1/7.1 objects. For downmixing, see the dedicated guide.

Quick start

  1. In Praat, select a mono or multi‑channel Sound.
  2. Run script…fast_spectral_swirl_multi_channel.praat.
  3. Pick a preset (e.g., “Subtle shimmer”).
  4. Adjust rate, depth, and banding as needed.
  5. Choose link_channels = yes for stable imaging, no for wide/decorrelated swirl.
  6. Set mix (dry/wet) and normalize if needed. Press OK.

Concepts

STFT & Bin Rotation

STFT: X(k,n) = Σ_t x(t) w(t-nH) e^{-j2πkt/N}
Swirl via circular shift S bins: X'(k,n) = X((k - S(n)) mod K, n)
Alternative phase advance: X'(k,n) = X(k,n) · e^{j φ(k,n)}

Rotation re‑orders magnitudes across frequency; phase advance simulates spectral shearing. Both reconstruct via overlap–add.

Swirl Modes

🎛️ Constant Shift

Fixed S bins per frame; gentle chorus‑like shimmer.

🌊 LFO‑Modulated

S(n) = S0 + Sd · sin(2π f_LFO nH/Fs + φ) for periodic swirl.

🎲 Random Walk

Per frame, S jitters within bounds; seedable for repeatability.

🧩 Banded

Apply different shifts per band (low/mid/high) or per Bark/ERB groups for tone‑aware results.

Parameters

ParameterTypeDefaultDescription
fft_sizeoption2048Power of two; resolution vs latency
hopinteger (samples)N/4Smaller hop → smoother, higher CPU
windowoptionHannHann/Blackman/Hamming
modeoptionLFOConstant, LFO, Random, Banded
shift_binsinteger2Base circular shift per frame
rate_hzreal0.6LFO rate for modulated mode
depth_binsinteger6LFO/random amplitude (bins)
phase_shearreal0.0Additional linear phase advance per bin
bandstext""CSV edges in Hz (e.g., 0,300,3000,Nyq)
band_shiftstext""CSV shifts per band (bins)
link_channelsbooleanyesUse same shifts for all channels
stereo_offsetinteger0Extra shift for R (or even channels) to widen
random_seedinteger00=auto; otherwise reproducible
dry_wetreal0.50=dry, 1=wet
normalizebooleanyesNormalize peak to norm_target
norm_targetreal0.99Peak amplitude target
formant_keepbooleannoReduce shifts near vocal formants (experimental)
reportbooleannoPrint effective shifts per frame/band

Presets

✨ Subtle shimmer

fft=2048, hop=N/4, mode=LFO, shift=1, depth=3, rate=0.4, link_channels=yes, dry_wet=0.3

🌪️ Fast swirl

fft=1024, hop=N/4, mode=LFO, shift=2, depth=8, rate=2.0, stereo_offset=+1

🧊 Frozen highs

bands=0,300,4000,Nyq; band_shifts=0,0,2; formant_keep=yes

🎲 Grainy random

mode=Random, depth=10, random_seed=42, link_channels=no, dry_wet=0.6

Multi‑Channel Strategies

Tips & Pitfalls

Watch out: Very large shifts at small FFT sizes can sound noisy; increase FFT or reduce depth.

Math

Bin Rotation & Phase Shear

Circular shift by S(n): X'(k,n) = X((k - S(n)) mod K, n)
Phase shear: φ'(k,n) = φ(k,n) + α·k ⇒ X'(k,n) = |X| e^{j φ'(k,n)}
Inverse STFT via OLA reconstructs y(t).

LFO Mapping

Let u = nH/Fs (seconds). S(n) = S0 + Sd · sin(2π f_LFO u + φ).
For banded swirl, use S_b(n) per band b and apply within band edges.