Spectral Freeze with Decay & Glissando — User Guide

Spectral analysis and resynthesis with dynamic partial tracking: creates frozen, evolving, and pitch-shifting textures through peak detection, decay modeling, and glissando control.

Author: Shai Cohen Affiliation: Department of Music, Bar-Ilan University, Israel Version: 0.1 (2025) License: MIT License Repo: https://github.com/ShaiCohen-ops/Praat-plugin_AudioTools
Contents:

What this does

This script implements Spectral Freeze with Decay and Glissando — an advanced spectral processing technique that analyzes audio in short frames, tracks the strongest harmonic partials, and resynthesizes them with controlled decay and pitch evolution. The effect creates ethereal frozen textures, evolving pads, and dynamic spectral transformations that maintain the harmonic character of the source while introducing temporal and pitch manipulation.

Key Features:

What is spectral freeze? Traditional freeze effects simply loop or sustain audio. Spectral freeze analyzes the frequency content of sound and sustains only the most prominent harmonic components, allowing for independent control of amplitude decay and pitch evolution. This creates textures that are simultaneously familiar (retaining source character) and transformed (evolving in time and pitch). The technique is particularly effective for creating pads from percussive sounds, transforming vocals into ethereal textures, and generating evolving soundscapes from any audio source.

Technical Implementation: (1) Parameter Setup: Apply preset values or custom parameters, convert time units. (2) Input Preparation: Convert stereo to mono if needed, add silent tail for decay. (3) Frame-Based Analysis: Process audio in short overlapping windows, extract spectral peaks. (4) Partial Tracking: Track top K partials across frames, applying decay and glissando. (5) Snapshot Storage: Store per-frame frequency and amplitude values for all tracked partials. (6) Additive Resynthesis: Reconstruct sound from stored partial data using sinusoidal oscillators. (7) Stereo Enhancement: Apply optional channel differentiation and delays. (8) Final Processing: Normalize levels, apply light filtering, clean up intermediate objects. The core innovation is the combination of peak-based analysis with independent control of amplitude decay and pitch evolution, creating complex evolving textures from simple audio sources.

Quick start

  1. In Praat, select exactly one Sound object.
  2. Run script…apply_spectral_freeze.praat.
  3. Choose Preset (9 options from Classic Freeze to Complex Evolutions).
  4. For custom settings, adjust analysis parameters (frame step, window size, frequency range).
  5. Set Top_partials_(K) (number of harmonic components to track).
  6. Adjust Decay_factor and Glissando for custom textures.
  7. Set Tail_duration for natural fade-out length.
  8. Enable Create_stereo_output for spatial effects.
  9. Configure output options (target peak, filtering, auto-play).
  10. Click OK — effect applied, result named "originalname_freeze".
Quick tip: Start with presets to understand different effect characters. Use Freeze for sustained textures, Gentle decay for natural fade-outs, Rising/Falling shimmer for pitch-evolving pads, and Ghostly rise/Deep dive for dramatic transformations. Higher Top_partials values capture more harmonic detail but increase processing time. Use stereo output with moderate delay (8-15ms) for spacious effects. The effect works particularly well on harmonic sources like vocals, strings, and sustained instruments.
Important: SPECTRAL TRANSFORMATION — significantly alters temporal and spectral characteristics. Very high Decay_factor values (>0.95) create near-infinite sustains that may require manual stopping. Extreme Glissando values (>0.5 octaves/sec) create rapid pitch changes that may sound artificial. Analysis_window should be 2-3 times Frame_step for proper overlap. The effect works best on harmonic or noise-based sources — highly transient or percussive material may produce less musical results. Processing time increases with more partials and longer audio files. Mono conversion occurs internally for analysis regardless of stereo output setting.

Spectral Freeze Theory

Spectral Analysis Fundamentals

Frame-Based Processing

Time-frequency analysis:

Frame parameters: dt = frame_step / 1000 (seconds per frame) windowDuration = analysis_window / 1000 (analysis window) numberOfFrames = floor(duration / dt) Analysis process: FOR each frame (1 to numberOfFrames): tCenter = (frame - 0.5) * dt Extract window: [tCenter - windowDuration/2, tCenter + windowDuration/2] Apply Hanning window Compute FFT spectrum Find top K spectral peaks Update tracked partials

Why Frame-Based Analysis?

Temporal resolution trade-offs:

Partial Tracking System

Peak Detection Algorithm

Finding dominant spectral components:

Peak detection process: 1. Compute magnitude spectrum up to max_frequency 2. Find largest peak in current spectrum 3. Store frequency and amplitude 4. Zero out peak and neighboring bins (±2 bins) 5. Repeat for K peaks Example: Top_partials = 10 Finds 10 strongest spectral peaks per frame Excludes peaks above max_frequency Prevents duplicate detection of same peak

Accumulator Update Logic

Tracking partials across frames:

For each tracked partial i (1 to K): DECAY application: a_amp_'i' = a_amp_'i' * d_frame where d_frame = decay_factor ^ dt GLISSANDO application: a_freq_'i' = a_freq_'i' * gliss_ratio where gliss_ratio = 2 ^ (glissando * dt) PEAK REPLACEMENT: IF current_peak_amp ≥ tracked_amp AND current_peak_freq > 0: tracked_amp = current_peak_amp tracked_freq = current_peak_freq This creates: - Natural amplitude decay when no stronger peaks detected - Continuous pitch evolution (glissando) - Peak replacement when louder components appear

Decay and Glissando Mathematics

Exponential Decay Model

Frame-based decay calculation:

Decay per second: decay_factor Decay per frame: d_frame = decay_factor ^ dt Examples: decay_factor = 0.5, dt = 0.01s d_frame = 0.5^0.01 ≈ 0.9931 (0.69% decay per frame) decay_factor = 0.9, dt = 0.01s d_frame = 0.9^0.01 ≈ 0.9989 (0.11% decay per frame) Interpretation: decay_factor = 0.5: 50% amplitude reduction per second decay_factor = 0.9: 10% amplitude reduction per second decay_factor = 0.999: 0.1% amplitude reduction per second (near freeze)

Glissando Pitch Evolution

Continuous pitch shifting:

Glissando rate: glissando (octaves per second) Per-frame ratio: gliss_ratio = 2 ^ (glissando * dt) Examples: glissando = 0.1, dt = 0.01s gliss_ratio = 2^(0.1*0.01) ≈ 1.000693 (up 0.069% per frame) glissando = -0.2, dt = 0.01s gliss_ratio = 2^(-0.2*0.01) ≈ 0.998614 (down 0.139% per frame) After 1 second: glissando = 0.1 → 2^(0.1) = 1.07177 (up ~7.2%) glissando = -0.2 → 2^(-0.2) = 0.87055 (down ~13%)

❄️ Spectral Transformation Visualization

Freeze (decay_factor = 0.999, glissando = 0):

Peaks sustained nearly indefinitely, no pitch change

Creates frozen, static texture from source


Rising shimmer (decay_factor = 0.3, glissando = 0.15):

Rapid amplitude decay + upward pitch drift

Creates evaporating, lifting texture


Ghostly rise (decay_factor = 0.15, glissando = 0.3):

Very fast decay + strong upward glissando

Creates transient ghost tones that rise and disappear

Resynthesis Technique

Additive Synthesis from Peaks

Sine wave reconstruction:

FOR each frame (1 to numberOfFrames): FOR each partial i (1 to K): IF f_freq_'frame'_'i' > 0 AND f_amp_'frame'_'i' > 0: Add to output: amp * sin(2π * freq * time) Windowed overlap-add: Each partial multiplied by raised cosine window: window = 0.5 - 0.5*cos(2π*(time - frame_start)/dt) This ensures smooth transitions between frames Prevents clicking at frame boundaries

Stereo Enhancement

Spatial processing:

IF create_stereo_output: Channel 1 (left): Original synthesis Channel 2 (right): Delayed version delayTime = stereo_delay / 1000 seconds Additional processing: Right channel gets subtle high-frequency emphasis: self + 0.08*(self - self(x - 1/sampleRate)) Slight attenuation: self * 0.99 Creates: - Time delay for spaciousness - Spectral difference for width - Level difference for directionality

Parameters

Analysis Parameters

ParameterTypeDefaultDescription
Frame_step_(ms)positive10Time between analysis frames (milliseconds)
Analysis_window_(ms)positive35Duration of analysis window (milliseconds)
Max_frequency_(Hz)positive8000Highest frequency to analyze
Top_partials_(K)integer10Number of spectral peaks to track

Spectral Transformation Parameters

ParameterTypeDefaultDescription
Decay_factor_(d)positive0.2Amplitude decay rate per second (0-1)
Glissando_(octaves_per_sec)real0.1Pitch change rate (positive=up, negative=down)
Tail_duration_(seconds)positive2Silent tail added for natural decay

Output Parameters

ParameterTypeDefaultDescription
Create_stereo_outputboolean1Generate stereo instead of mono
Stereo_delay_(ms)positive8Delay between channels for stereo width
Target_peak_(dB)real-1Output normalization level
Apply_light_filteringboolean0Apply gentle bandpass filtering
Play_after_processingboolean1Auto-play result

Preset Details

⛄ Freeze (classic hold)

Character: Sustained spectral snapshot

Settings:

  • Decay_factor: 0.999
  • Glissando: 0

Use for: Creating frozen textures, infinite sustains

🍃 Gentle decay (slow fade)

Character: Natural amplitude decay

Settings:

  • Decay_factor: 0.5
  • Glissando: 0

Use for: Smooth fade-outs, natural reverberation

✨ Rising shimmer (decay + up)

Character: Fading upward drift

Settings:

  • Decay_factor: 0.3
  • Glissando: 0.15

Use for: Evaporating textures, uplifting pads

🌊 Falling shimmer (decay + down)

Character: Fading downward drift

Settings:

  • Decay_factor: 0.3
  • Glissando: -0.15

Use for: Descending textures, sinking effects

👻 Ghostly rise (strong decay + up)

Character: Rapid fade with strong upward shift

Settings:

  • Decay_factor: 0.15
  • Glissando: 0.3

Use for: Transient ghost tones, dramatic rises

🌊 Deep dive (strong decay + down)

Character: Rapid fade with strong downward shift

Settings:

  • Decay_factor: 0.15
  • Glissando: -0.3

Use for: Plunging effects, sub-bass transformations

💎 Crystalline (minimal decay + micro-up)

Character: Nearly frozen with subtle brightening

Settings:

  • Decay_factor: 0.9
  • Glissando: 0.05

Use for: Sparkling textures, subtle evolution

🌑 Submerge (minimal decay + micro-down)

Character: Nearly frozen with subtle darkening

Settings:

  • Decay_factor: 0.9
  • Glissando: -0.05

Use for: Darkening textures, subtle descent

Processing Pipeline

Complete Algorithm

SETUP: Select Sound object, get: soundName$, duration, sampleRate Apply preset parameters or use custom values Convert: dt = frame_step/1000, windowDuration = analysis_window/1000 INPUT PREPARATION: IF stereo input: Convert to mono for processing Create silent tail of tail_duration seconds Concatenate original + tail → extendedSound INITIALIZATION: Initialize K accumulator arrays for frequencies and amplitudes numberOfFrames = floor(total_duration / dt) ANALYSIS LOOP (frame = 1 to numberOfFrames): tCenter = (frame - 0.5) * dt Extract windowed segment around tCenter Compute FFT spectrum Find top K spectral peaks (up to max_frequency) FOR each partial i (1 to K): # Apply decay to tracked amplitude a_amp_'i' = a_amp_'i' * (decay_factor ^ dt) # Apply glissando to tracked frequency IF a_freq_'i' > 0: a_freq_'i' = a_freq_'i' * (2 ^ (glissando * dt)) IF a_freq_'i' > max_frequency: clamp to max_frequency # Replace if current peak is stronger IF current_peak_amp ≥ a_amp_'i' AND current_peak_freq > 0: a_amp_'i' = current_peak_amp a_freq_'i' = current_peak_freq # Store snapshot for this frame f_freq_'frame'_'i' = a_freq_'i' f_amp_'frame'_'i' = a_amp_'i' RESYNTHESIS: Create output sound (mono or stereo) FOR frame = 1 to numberOfFrames: FOR partial i = 1 to K: IF stored_freq > 0 AND stored_amp > 0: Add sine wave: stored_amp * sin(2π * stored_freq * time) Apply raised cosine window for smooth transitions IF stereo output: Create delayed right channel Apply subtle HF boost to right channel Apply slight attenuation to right channel FINAL PROCESSING: IF apply_light_filtering: Apply bandpass filter Normalize to target_peak dB Clean up intermediate objects IF play_after_processing: Play result

Processing Characteristics

Computational Complexity

Performance considerations:

Quality vs Speed Trade-offs

Frame Step Guidelines:

Fine (5-10ms): High temporal resolution Smooth amplitude and pitch evolution Increased processing time Recommended for most applications

Medium (10-20ms): Balanced performance Good for general use Slight stepping in rapid changes

Coarse (20-50ms): Faster processing Noticeable stepping in evolution Good for slow, evolving textures only

Analysis Window: Typically 2-4× frame step for proper overlap

Partial Count Guidelines

Top Partials (K) Selection:

Low (5-8 partials): Fast processing Captures only strongest harmonics Sparse, minimalist textures Good for bass, fundamental emphasis

Medium (10-15 partials): Balanced detail/performance Captures harmonic richness Recommended for most sources Preserves tone character

High (20-30 partials): Slower processing Captures subtle harmonics and noise Rich, complex textures Good for detailed source analysis

Very High (>30 partials): Significant processing time Diminishing returns on quality May capture noise as "partials" Special applications only

Applications

Pad and Texture Creation

Use case: Transforming short sounds into evolving pads

Technique: Use Freeze or Gentle decay on percussive sources

Example: Apply to drum hits, vocal phrases, or instrument stabs

Vocal Transformation

Use case: Creating ethereal vocal textures

Technique: Use Rising/Falling shimmer on vocal phrases

Example: Transform spoken word into evolving background textures

Sound Design for Media

Use case: Creating magical, supernatural sound effects

Technique: Use Ghostly rise/Deep dive with stereo enhancement

Example: Spell effects, magical auras, supernatural phenomena

Ambient Music Production

Use case: Generating evolving background textures

Technique: Use Crystalline/Submerge with long tail duration

Example: Create endless evolving pads from field recordings

Instrument Processing

Use case: Adding sustain and evolution to short notes

Technique: Use Gentle decay with subtle glissando

Example: Extend piano or guitar notes into evolving pads

Practical Workflow Examples

🎹 Piano Pad Transformation

Goal: Create evolving pad from piano note

Settings:

  • Preset: Rising shimmer
  • Top_partials: 12
  • Tail_duration: 4 seconds
  • Create_stereo_output: Yes
  • Stereo_delay: 12ms

Result: Piano note transforms into shimmering, rising pad

🎤 Vocal Etherializer

Goal: Transform vocal into ghostly texture

Settings:

  • Preset: Ghostly rise
  • Top_partials: 8
  • Tail_duration: 3 seconds
  • Max_frequency: 5000 Hz
  • Apply_light_filtering: Yes

Result: Vocal phrase becomes evaporating, rising ghost tone

🥁 Drum Texture Generator

Goal: Create textured sustain from drum hit

Settings:

  • Preset: Freeze
  • Top_partials: 15
  • Tail_duration: 2 seconds
  • Frame_step: 15ms
  • Analysis_window: 50ms

Result: Drum transient extended into complex noisy texture

Advanced Techniques

Source material optimization:
  • Harmonic sources (vocals, strings): Use medium partial counts (10-15)
  • Noise-based sources (drums, rain): Use higher partial counts (15-25)
  • Transient-rich material: Use longer analysis windows (40-60ms)
  • Sustained tones: Use shorter frame steps (5-10ms) for smooth evolution
  • Complex polyphonic material: May produce less predictable results
Creative parameter combinations:
  • Very high decay_factor (0.99+) + subtle glissando: Slowly evolving frozen textures
  • Medium decay_factor (0.3-0.6) + strong glissando: Dramatic pitch-shifting decays
  • Low decay_factor (0.1-0.2) + no glissando: Rapid fade with stable pitch
  • Custom decay/glissando curves: Modify script for non-linear evolution
  • Extreme stereo delays (20-30ms): Creates distinct left/right perception

Troubleshooting Common Issues

Problem: Output sounds noisy or distorted
Cause: Too many partials capturing noise components
Solution: Reduce Top_partials, increase Max_frequency limit
Problem: Effect sounds "steppy" or granular
Cause: Frame step too large for smooth evolution
Solution: Decrease Frame_step to 5-10ms
Problem: No audible freeze effect
Cause: Decay_factor too low, source too quiet
Solution: Increase Decay_factor to 0.9+, ensure strong input signal
Problem: Processing very slow
Cause: Too many partials or very short frame step
Solution: Reduce Top_partials, increase Frame_step to 15-20ms
Problem: Stereo effect too extreme or phasey
Cause: Stereo_delay too long for content
Solution: Reduce Stereo_delay to 5-15ms range