Sympathetic Resonance — v1.0 User Guide

Virtual string physical model. Discovers the latent pitch collection embedded in a source sound, builds a bank of virtual resonant strings tuned to that discovered scale, and excites them with the source. The result is the sympathetic resonance aura: a glowing image of the sound as if it had excited a giant metallic, glassy, wooden, or airy resonant body.

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

What this does

Sympathetic Resonance creates the sound of a source audio signal exciting a bank of virtual resonant strings. Unlike reverb or simple filtering, this is a physical model: each string is a second-order digital resonator with a specific pitch, decay time, and bandwidth. The source signal excites all strings simultaneously, and the energy spreads between adjacent strings via sympathetic coupling (modelled as Gaussian blur across the frequency axis).

The key insight: The pitch collection of the resonators is discovered from the source itself. The engine analyses the source’s log‑frequency spectrum (Constant‑Q Transform), detects prominent spectral peaks, clusters them, and builds a set of fundamental pitches. It then expands each into a harmonic series (up to 20 partials, depending on character), creating a dense, body‑like resonance tuned to the source. The result is not a generic effect – it is the source’s own harmonic content “singing back” through a virtual instrument body.

Quick start

  1. In Praat, select exactly one Sound object (mono or stereo – stereo will be downmixed to mono for analysis).
  2. Run script…SympatheticResonance.praat.
  3. Choose a Preset:
    • Piano Frame, Metal Plate, Harp Body, Glass Chamber, Wood Box, Shimmer Cloud
  4. For custom mode (preset = Custom), set:
    • Character – Metallic, Glassy, Wooden, Airy
    • N_strings – number of resonators (4–96)
    • Decay_s – decay time in seconds (0.1–60 s)
    • Coupling – amount of sympathetic energy spread (0–2)
    • Wet_dry – 0 = 100 % resonance, 1 = 100 % dry original
  5. Click OK. Praat exports WAV, runs Python physical model, and imports the result as SR_originalname_preset (or SR_originalname_character for Custom).
Tip: Start with Piano Frame (metallic, 48 strings, long decay) to hear a shimmering, bell‑like resonance. For a more subtle, airy texture, try Harp Body (airy, 32 strings, short decay).
Important: Python dependencies: numpy, soundfile, scipy, librosa. The engine uses a true Constant‑Q Transform (CQT) for pitch discovery – librosa is required for optimal results. The rendering is done in the frequency domain (FFT) and is efficient even for hundreds of resonators.

The 6 presets (+ Custom)

PresetCharacterStringsDecay (s)CouplingDescription
Piano FrameMetallic488.00.35Rich, bell‑like resonance with moderate decay.
Metal PlateMetallic6414.00.50Long, shimmering metallic plate – like a giant gong.
Harp BodyAiry324.00.20Light, airy resonance – harpsichord‑like body.
Glass ChamberGlassy6420.00.60Very long, glassy, ethereal – a hall of glass strings.
Wood BoxWooden241.80.40Short, warm, woody resonance – like a small soundbox.
Shimmer CloudAiry569.00.70Dense, airy cloud with strong coupling – washes of resonance.

Each preset also sets internal character parameters: brightness, shelf_freq_hz, inharmonicity, n_harmonics, harm_rolloff, and src_tilt_db_oct.

Physical model – how it works

Digital resonator (second‑order IIR)

y[n] = 2·r·cos(ω)·y[n‑1] – r²·y[n‑2] + gain·x[n]

  • r (pole radius) determines both frequency selectivity and temporal decay. For a target -60 dB decay in T seconds: r = exp( –6.908 / (T·sr) ).
  • ω = 2π·freq / sr – the resonant frequency.
  • gain compensates for the resonator’s peak gain and applies source spectral tilt correction.

Pitch discovery

Resonator bank construction

Excitation & sympathetic coupling

Pipeline — six stages

Stage 1 – Load audio (Python) – mono float32, normalise.
Stage 2 – CQT analysis – compute Constant‑Q Transform (librosa) for log‑frequency representation.
Stage 3 – Spectral flatness – measure tonality vs. noise (used to modulate decay, bandwidth, coupling).
Stage 4 – Pitch discovery – peak detection + clustering + interpolation → fundamental frequencies.
Stage 5 – Build resonator bank – expand to harmonics, compute IIR coefficients, pan gains.
Stage 6 – FFT rendering – frequency‑domain excitation, coupling, shelf EQ, IFFT → stereo output.

Character‑dependent parameters

CharacterBrightness (dB)InharmonicityHarmonicsRolloffTilt (dB/oct)
Metallic+168e‑5200.57.0
Glassy+200.0240.48.0
Wooden-30.061.43.0
Airy+100.0160.66.0

Parameters & defaults

Custom parameters (when Preset = Custom)

ParameterRangeDefaultDescription
CharacterMetallic / Glassy / Wooden / AiryMetallicSets brightness, inharmonicity, harmonic count, rolloff, and source tilt compensation.
N_strings4–9632Number of virtual strings (after harmonic expansion and subsampling).
Decay_s0.1–60 s5.0Global decay time (‑60 dB point). Higher partials decay faster.
Coupling0–20.30Strength of sympathetic coupling between adjacent strings (blur in frequency‑response domain).
Wet_dry0–10.00 = 100 % wet resonance, 1 = 100 % dry original. In between mixes.

Output

ParameterDefaultDescription
Draw_visualizationyesShow waveforms, string bank plot, spectrogram, and summary in Praat picture.
Play_resultyesAuto‑play after processing.

Visualization (Praat picture)

When Draw_visualization = 1, the script draws:

Tip: The string bank plot gives an immediate visual of which frequencies are resonating. Tall bars indicate strong coupling or high gain. The spectral flatness value tells you how tonal (near 0) or noisy (near 1) the source is – this modulates the model’s behaviour.

FAQ / troubleshooting

“Python not found” or missing packages

Install: pip install numpy soundfile scipy librosa. On Windows, the script uses python.

Output is silent or has no resonance

Check the string count in the Info window. If n_strings is 0, pitch discovery may have failed – possibly because the source is very short or has no clear spectral peaks. Try a longer source, or increase the number of discovered pitches by raising N_strings (the engine will fill with interpolated pitches).

Resonance sounds dull / lacks high frequencies

The model includes source tilt compensation (src_tilt_db_oct) to boost high frequencies relative to low ones, compensating for speech’s natural rolloff. If your source is already bright, you may need to reduce brightness in the character preset (edit the Python script) or lower src_tilt_db_oct.

“CQT failed” warning and fallback to STFT

Librosa’s CQT may fail on very short files or certain sample rates. The engine falls back to a simple STFT‑based log‑spectrum, which is less precise but still works. For best results, ensure librosa is installed and use longer source files (≥2 s).

FFT rendering speed

The frequency‑domain renderer is efficient even for hundreds of resonators. For a 10‑second file with 64 resonators, processing takes about 1–2 seconds on a modern CPU.

Resonances CSV

The file temp_sr_resonances.csv contains the frequency and normalised gain of every resonator. It is used for the string bank visualisation and can be inspected for further analysis.