Harmonic Formant Locking — User Guide

Source-filter coupling effect: snaps formant frequencies to the nearest harmonics of F0, creating bell-like, metallic, or synthetic vocal timbres through harmonic alignment.

Author: Shai Cohen Version: 1.2 (2025) Technique: Harmonic Alignment + LPC Resynthesis Application: Praat scripting language
Contents:

What this does

This script implements Harmonic Formant Locking — a source-filter coupling effect that snaps formant frequencies to the nearest harmonics of the fundamental frequency (F0). Unlike natural speech where formants are independent of pitch, this effect forces harmonic alignment between the source spectrum and vocal tract resonances, creating bell-like, metallic, or synthetic vocal timbres.

Key Features:

🎵 What is Harmonic Formant Locking?

In natural speech, formants (vocal tract resonances) are independent of pitch. A vowel maintains its identity regardless of whether you sing it high or low. This independence is what gives speech its flexibility.

Harmonic Formant Locking breaks this independence by forcing formants to align with harmonics of F0:

  • F1 is pulled toward the nearest harmonic (n × F0)
  • F2 is pulled toward its nearest harmonic
  • F3, F4, F5 similarly "lock" onto the harmonic grid

The result: A coupling between source and filter that creates bell-like, metallic, or synthetic timbres — sounds that seem to "ring" at harmonically related frequencies, like a struck metal plate or a synthesizer with fixed formants.

Technical Implementation: (1) Analysis: Extract F0 (pitch), intensity, and formants (LPC) with formant path tracking. (2) Stabilization: Median filter F0 to reduce octave jumps; smooth formant trajectories. (3) Harmonic Calculation: For each formant, compute harmonic number = round(formant_freq / F0). (4) Locking: Blend original and harmonic-locked frequencies based on lock_strength. (5) Resynthesis: Rebuild formant grid with locked frequencies and scaled bandwidths; perform LPC resynthesis from source excitation. (6) Visualization: Show original vs. locked formant trajectories overlaid on harmonic grid.

Quick start

  1. In Praat, select exactly one Sound object (speech/voice recommended).
  2. Run script… → select Harmonic_Formant_Locking.praat.
  3. Choose Preset (2-6 for specific intensities, 1 for custom).
  4. Adjust lock strength and bandwidth scale as desired.
  5. Configure stability options (keep default ON for most material).
  6. Set snap mode and harmonic range if using custom mode.
  7. Enable Draw_visualization to see formant trajectories.
  8. Click OK — processor analyzes, locks formants, resynthesizes.
Quick tip: Start with Subtle Shimmer preset (35% lock) on a sustained vowel. Enable visualization — you'll see original formants (grey dotted) and locked formants (colored solid) converging toward harmonic grid lines. Listen for the subtle "shimmer" or "ring" added to the voice. For more dramatic effects, try Moderate Bell (60%) or Strong Metal (85%). The output appears as "original_HarmonicLock_PresetName" in the Objects window.
Important: PITCH ACCURACY is critical — F0 must be tracked reliably. Use recordings with clear voicing (sustained vowels, singing). Unvoiced material (whispers, noise, silence) is gated by intensity threshold. LPC ORDER (20) works for most voices but may need adjustment for very high/low pitches. BANDWIDTH SCALING < 0.7 can cause harsh, whistling resonances. LOCK STRENGTH > 80% may produce robotic, unnatural timbres. STABILITY OPTIONS (F0 stabilization, smoothing, jump limiting) are highly recommended — keep them ON unless you want artifacts.

Harmonic Formant Theory

The Locking Equation

For each formant at frequency f_formant, with fundamental frequency F0: 1. Calculate floating harmonic number: h_float = f_formant / F0 2. Snap to integer harmonic based on mode: • Nearest: h_target = round(h_float) • Upward: h_target = ceil(h_float) • Downward: h_target = floor(h_float) • Octave: h_target = 2^round(log2(h_float)) 3. Clamp to allowed range: h_target = max(min_harmonic, min(h_target, max_harmonic)) 4. Compute target frequency: f_target = F0 × h_target 5. Apply weighted blend: f_locked = f_formant × (1 - w) + f_target × w where w = lock_strength × formant_weight[fn] Formant weights: F1=0.5, F2=1.0, F3=1.0, F4=0.75, F5=0.5

Harmonic Grid

📐 The Harmonic Series

A harmonic series consists of integer multiples of the fundamental:

h₁ = F0 (fundamental)
h₂ = 2 × F0 (octave)
h₃ = 3 × F0 (octave + fifth)
h₄ = 4 × F0 (two octaves)
h₅ = 5 × F0 (two octaves + major third)
h₆ = 6 × F0 (two octaves + fifth)
h₇ = 7 × F0 (≈ harmonic seventh)
h₈ = 8 × F0 (three octaves)

Example with F0 = 200 Hz:

HarmonicFrequencyMusical Interval
2400 HzOctave
3600 HzOctave + fifth
4800 HzTwo octaves
51000 HzTwo octaves + major third
61200 HzTwo octaves + fifth
71400 Hz≈ minor seventh
81600 HzThree octaves

Snap Modes Explained

Snap Mode: Nearest h_target = round(f_formant / F0) • Most natural sounding • Formants move to closest harmonic • Minimal pitch-dependent shift Snap Mode: Upward h_target = ceil(f_formant / F0) • Formants always shift upward • Creates brighter, more "metallic" timbre • May push formants beyond natural range Snap Mode: Downward h_target = floor(f_formant / F0) • Formants always shift downward • Creates darker, more "hollow" timbre • Risk of formants dropping too low Snap Mode: Octave h_target = 2^round(log2(f_formant / F0)) • Snaps to powers of two (octave harmonics) • Creates organ-like, Pythagorean tuning • Most artificial, extreme effect

Stability Mechanisms

🛡️ Preventing Artifacts

F0 Stabilization (median filter): Replaces each F0 value with median of neighboring 7 frames. Reduces octave jumps and pitch tracking errors that would cause sudden formant shifts.

Jump Limiting: Restricts harmonic changes to ±2 harmonics per frame. Prevents "zipper noise" — audible steps when formants jump between harmonics.

Formant Smoothing (5-frame moving average): Smooths locked formant trajectories. Reduces graininess and creates more natural transitions.

Intensity Gating: Only applies locking when intensity > min_intensity_dB. Prevents processing in unvoiced regions, silence, or background noise where F0 is unreliable.

Bandwidth Scaling

Bandwidth controls the sharpness of formant resonances: bandwidth_locked = original_bandwidth × bandwidth_scale Effects: • 1.5× : Wide, smooth, natural (Safe Start) • 1.2× : Moderate width, subtle (Subtle Shimmer) • 1.0× : Original bandwidth, balanced (Moderate Bell) • 0.8× : Narrow, metallic, ringing (Strong Metal) • 0.7× : Very narrow, synthetic, harsh (Extreme Synth) Narrow bandwidths (<0.7) create sustained ringing at each harmonic, potentially causing whistling or feedback-like tones.

Preset Strategies

Preset 2: Safe Start (20% lock, wide bands)

🛡️ Conservative Starting Point

Lock strength: 20%

Bandwidth scale: 1.5× (very wide, smooth)

Time step: 0.012 s

Character: Minimal locking, wide bandwidths — subtle effect, safe for any material

Use on: Testing, unfamiliar material, first explorations

Preset 3: Subtle Shimmer (35%)

✨ Gentle Harmonic Enhancement

Lock strength: 35%

Bandwidth scale: 1.2× (slightly wide)

Time step: 0.010 s

Character: Noticeable but not extreme — adds a subtle "shimmer" or "ring" to voices

Use on: Vocals, speech, any material needing gentle enhancement

Preset 4: Moderate Bell (60%)

🔔 Bell-like Resonance

Lock strength: 60%

Bandwidth scale: 1.0× (original bandwidth)

Time step: 0.010 s

Character: Strong coupling — voice takes on bell-like, resonant quality

Use on: Singing, sustained vowels, creating "singing bowl" effects

Preset 5: Strong Metal (85%)

⚙️ Metallic Transformation

Lock strength: 85%

Bandwidth scale: 0.8× (narrow)

Time step: 0.008 s (higher temporal resolution)

Character: Strong harmonic locking with narrow bandwidths — metallic, ringing timbre

Use on: Sound design, industrial textures, robot voices

Preset 6: Extreme Synth (100%)

🎛️ Synthetic Maximum

Lock strength: 100%

Bandwidth scale: 0.7× (very narrow)

Time step: 0.008 s

Snap mode: Octave

Character: Full locking to octave harmonics with very narrow bandwidths — purely synthetic, organ-like timbre

Use on: Experimental synthesis, extreme transformations

Parameters & Controls

Main Controls

ParameterTypeDefaultDescription
Lock_strength_(%)real350% = original, 100% = fully locked to harmonics
Bandwidth_scalereal1.2Multiplier for formant bandwidths (0.5-2.0 typical)

Stability Options

ParameterTypeDefaultDescription
Stabilize_F0boolean1Median filter F0 to reduce octave jumps
Smooth_formant_transitionsboolean15-frame moving average on locked formants
Gate_weak_unvoicedboolean1Skip processing when intensity below threshold
Min_intensity_dBreal-25Intensity threshold for gating
Limit_harmonic_jumpsboolean1Restrict harmonic changes to ±2 per frame
Max_harmonic_jump_per_frameinteger2Maximum allowed harmonic change

Timing

ParameterTypeDefaultDescription
Time_step_spositive0.010Analysis frame interval (seconds)

Advanced Options

ParameterTypeDefaultDescription
Snap_modeoptionNearestHow formants align to harmonics
Min_harmonicinteger2Lowest allowed harmonic (1 = fundamental)
Max_harmonicinteger20Highest allowed harmonic
Show_diagnosticsboolean1Display pitch tracking statistics

Output

ParameterTypeDefaultDescription
Draw_visualizationboolean1Generate formant trajectory plot
Play_resultboolean1Audition after processing

Visualization & Analysis

Visualization Panels

Harmonic Formant Locking Visualization: Panel 1: TITLE • Script name, preset, lock strength, stability status Panel 2: ORIGINAL WAVEFORM (LEFT) • Gray waveform of input • Label: "Original" Panel 3: PROCESSED WAVEFORM (RIGHT) • Green waveform of output • Label: "Locked" • X-axis: Time (s) Panel 4: FORMANT TRAJECTORIES WITH HARMONIC GRID • Light gray background • Gray horizontal lines = harmonic grid (F0×n at sample mid-point) • Dotted gray lines = original formants (F1, F2, F3) • Solid colored lines = locked formants: - Blue = F1 - Orange = F2 - Green = F3 • Legend in lower left • X-axis: Time, Y-axis: Frequency (0-4000 Hz) Panel 5: ORIGINAL SPECTROGRAM (LEFT) • 0-4000 Hz spectrogram of input Panel 6: PROCESSED SPECTROGRAM (RIGHT) • 0-4000 Hz spectrogram of output • Shows harmonic alignment visually Panel 7: INFO PANEL (BOTTOM) • Lock strength, bandwidth scale, time step • Snap mode, harmonic range • Stability settings status • Locked points count

Reading the Formant Trajectory Plot

What to look for:
  • Gray dotted lines: Original formant paths — may cross harmonic grid lines independently
  • Colored solid lines: Locked formants — should follow harmonic grid lines (horizontal)
  • Convergence: Where colored lines align with gray horizontals = strong locking
  • Divergence: Where colored lines drift = weaker locking or transition between harmonics
  • Step patterns: In extreme locking, formants may jump between harmonics (visible as vertical steps)
  • Smoothness: With smoothing enabled, transitions between harmonics are gradual

Diagnostic Output

When Show_diagnostics is enabled, the Info window displays:
  • Pitch range: Estimated F0 floor/ceiling from quantile analysis
  • Pitch issues: Count of unvoiced frames and octave jumps before/after stabilization
  • Locked points: Number of successfully locked formant points
  • Gated frames: Frames skipped due to low intensity
  • Jump-limited transitions: Number of times jump limiting prevented excessive harmonic shifts
  • Listening checklist: Troubleshooting guide for common artifacts

Applications

Voice Transformation & Special Effects

Use case: Creating robot voices, metallic characters, or synthetic vocal timbres

Technique: Strong Metal or Extreme Synth presets

Workflow:

Bell and Metal Synthesis

Use case: Transforming any sound into bell-like or metallic timbres

Technique: Moderate Bell preset with narrow bandwidth

Settings:

Result: Source takes on bell-like resonance — each partial aligns with harmonic series, creating "singing" quality

Musical Timbral Design

Use case: Creating evolving timbral textures for electronic music

Technique: Moderate lock strength with varying bandwidth

Applications:

Research & Education

Use case: Demonstrating source-filter theory and harmonic relationships

Technique: Enable visualization, compare presets on sustained vowels

Learning outcomes:

Practical Workflow Examples

🎤 Robot Voice Effect

Goal: Transform spoken phrase into robotic, synthetic voice

Settings:

  • Preset: Strong Metal (85% lock)
  • Bandwidth: 0.8× (moderate ringing)
  • Snap mode: Nearest (natural harmonic alignment)
  • Stabilize F0: ON (reduces warbles)
  • Source: Clear speech with varied intonation

Result: Voice takes on metallic, robotic character while retaining intelligibility

🔔 Bell from Piano Note

Goal: Transform piano note into bell-like tone

Settings:

  • Preset: Moderate Bell (60% lock)
  • Bandwidth: 0.75× (narrow for ringing)
  • Snap mode: Nearest
  • Source: Single piano note with clear decay

Result: Piano's inharmonic partials are pulled to harmonic series — creates bell-like, ringing tone

🎚️ Vocal Warmth Enhancement

Goal: Add subtle harmonic richness to vocal recording

Settings:

  • Preset: Subtle Shimmer (35% lock)
  • Bandwidth: 1.2× (slightly wide, smooth)
  • Stabilize F0: ON
  • Smooth transitions: ON
  • Gate weak: ON (preserves breaths)

Result: Vocals gain subtle harmonic "shimmer" without obvious processing

Troubleshooting Common Issues

Problem: Output has warbles/yodels (pitch instability)
Cause: F0 tracking errors or octave jumps
Solution: Ensure Stabilize_F0 is ON, reduce lock strength, check recording quality
Problem: Buzzing/granular "zipper noise"
Cause: Formants jumping too quickly between harmonics
Solution: Enable Limit_harmonic_jumps, increase time_step_s, reduce lock strength
Problem: Ringing/whistling tones
Cause: Bandwidth too narrow for lock strength
Solution: Increase bandwidth_scale (1.0-1.5), reduce lock strength
Problem: Hollow/phasey sound
Cause: LPC resynthesis artifacts or formant smoothing too aggressive
Solution: Reduce lock strength, increase bandwidth, check LPC order
Problem: Unprocessed sections (silence/gaps)
Cause: Intensity gating threshold too high
Solution: Reduce min_intensity_dB (-30 to -40 dB) or disable gating

Advanced Techniques

Custom harmonic ranges:
  • Bass emphasis: min_harmonic = 1, max_harmonic = 8 (focus on low harmonics)
  • Treble emphasis: min_harmonic = 8, max_harmonic = 30 (focus on high harmonics)
  • Odd harmonics only: Modify script to force odd numbers (2n-1) — creates clarinet-like timbre
  • Prime harmonics: Force to prime numbers (2,3,5,7,11,13,17,19) — creates unusual inharmonicity
Formant weighting exploration:
  • F1 emphasis: Increase formant_weights#[1] to 1.0 — stronger locking on first formant
  • F2 emphasis: Keep F2 at 1.0, reduce others — focus on vowel frontness
  • Equal weights: Set all to 1.0 — uniform locking across all formants
  • High formants only: Zero out F1,F2 — lock only high frequencies (airy, shimmering)