Formant Chord Player — v0.2 User Guide

Re‑analyses the selected sound, extracts F1–F4 per segment, and renders each segment as a 4‑voice additive chord using a mellow multi‑partial waveform (soft organ/cello tone) shaped by a piano ADSR envelope. Produces both a MusicXML score (printed to the Info window) and an audio rendering.

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

What this does

Formant Chord Player is the audio companion to the Formant_to_MusicXML_Chord_Converter. It takes the same source sound, segments it, extracts the first four formant frequencies (F1–F4) per segment, and synthesises a 4‑voice additive chord for each segment. The synthesis uses:

MusicXML output: The script prints a complete MusicXML score to the Info window, showing each segment as a measure containing a chord of the four formant notes (transposed to the nearest MIDI pitch with microtonal alterations). You can copy this XML into a notation program (e.g., MuseScore, Finale, Sibelius) to see the score.

Quick start

  1. In Praat, select exactly one Sound object (mono or stereo).
  2. Run script…Formant_to_MusicXML_Chord_Converter.praat (or the player script).
  3. Set Number_of_segments – how many time segments to analyse (should match the Converter’s setting).
  4. Adjust synthesis parameters:
    • Transpose_semitones – global pitch shift for the rendered chords (default -24 to bring formants into playable range).
    • Note_duration_s – length of each chord (seconds).
    • Attack_s, Decay_s, Sustain_level, Release_s – piano ADSR envelope.
    • Stagger_s – delay between successive voices (F1→F2→F3→F4).
    • Num_harmonics – number of partials in the additive waveform (1–8).
  5. Click OK. The script extracts formants, prints MusicXML to the Info window, synthesises chords, concatenates them, and creates a new Sound object named formant_chords_originalname.
Tip: For a soft, organ‑like texture, use Num_harmonics = 3–5, Attack = 0.02–0.05 s, Release = 0.3–0.5 s. For a more percussive piano sound, set attack to 0.01 s and decay to 0.1 s.
Important: This effect is implemented entirely in Praat – no Python required. The synthesis uses Create Sound from formula with a sum of sinusoids. For many segments (e.g., 32) and many harmonics (e.g., 8), synthesis can be slow. Increase Note_duration_s to hear longer chords, but processing time scales linearly.

Synthesis engine

Additive synthesis formula:
wave(t) = Σk=1N Ak · sin(2π·k·f·t)
where Ak = (1/k) · exp( –(k‑1)² / (2·σ²) ) · gain
with σ = 2.0 (Gaussian rolloff) and gain per voice (F1=1.00, F2=0.80, F3=0.60, F4=0.45).

Per‑voice processing

  1. Register correction – transposes the formant frequency by octaves until it falls within C2 (65 Hz) and C5 (523 Hz).
  2. Global transpose – applies the user‑defined Transpose_semitones shift.
  3. Waveform generation – creates a num_harmonics‑partial additive tone at the corrected frequency.
  4. Onset stagger – the voice starts at (voice_index‑1) × stagger_s seconds after the segment start.
  5. ADSR envelope – applied in four stages:
    • Attack: linear rise from 0 to 1 over attack_s seconds.
    • Decay: fall from 1 to sustain_level over decay_s seconds.
    • Sustain: hold at sustain_level until the release point.
    • Release: linear fall from sustain_level to 0 over release_s seconds.
  6. Mix – all four voices are summed into a single chord buffer per segment.

After all segments are synthesised, they are concatenated into a single output sound. The MusicXML output shows the target pitches (before register correction), not the synthesised octave.

Parameters & defaults

Analysis

To Formant parameter).
ParameterRangeDefaultDescription
Number_of_segments≥18
Max_formant_Hz500–80005500

Pitch & timing

ParameterRangeDefaultDescription
Transpose_semitones-36–36-24
Note_duration_s0.1–101.2

ADSR envelope

ParameterRangeDefaultDescription
Attack_s0–10.025
Decay_s0–10.20
Sustain_level0–10.50
Release_s0–10.35

Voice articulation

ParameterRangeDefaultDescription
Stagger_s0–0.20.018
Num_harmonics1–83

Output

ParameterDefaultDescription Normalize_outputyes。 Play_resultyes。 Draw_visualizationyes。

Visualization (staff‑notation style)

When Draw_visualization = 1, the script draws a staff‑notation visualisation:

Tip: The visualisation uses the register‑corrected pitches (the actual synthesised notes) for staff placement, but annotates them with the original formant frequencies (Hz). This matches the Converter’s output and helps you see how formants map to the piano keyboard.

FAQ / troubleshooting

MusicXML output is missing / not well‑formed

The script prints MusicXML directly to the Info window. Copy the entire output (starting from <?xml version="1.0"...> to </score-partwise>) and paste it into a text file with a .musicxml extension. Then import into MuseScore, Finale, or any MusicXML‑compatible notation software.

Synthesised chords sound out of tune / register‑corrected awkwardly

The register correction moves formant frequencies by octaves into the C2–C5 range. If a formant is 110 Hz (A2), it stays at 110 Hz. If it’s 880 Hz (A5), it is halved to 440 Hz (A4). This can produce unexpected intervals. Adjust Transpose_semitones globally, or edit the regLow and regHigh variables in the script (lines near the top).

Processing is very slow for many segments / many harmonics

Each voice is synthesised with a Create Sound from formula call that builds a sum of sinusoids. For 32 segments × 4 voices × 8 harmonics = 1024 sinusoids, each formula is evaluated across thousands of samples. This can take tens of seconds. Reduce Num_harmonics to 2–3, or increase Note_duration_s to reduce the number of segments.

Register correction and transpose

The synthesis path: original formant (Hz) → register correction (octave shifts into C2–C5) → add transpose_semitones → generate additive tone. The MusicXML output uses the original formant pitch (after register correction but before transpose), so the score matches the rendered audio’s register.

Voice gains

Gain factors are fixed: F1=1.00, F2=0.80, F3=0.60, F4=0.45. These are hardcoded in the script (line with fGain[1] = 1.00 etc.). You can edit them to emphasise higher or lower formants.