This script implements a parametric autoencoder hybrid system for speech analysis, transformation, and resynthesis. It extracts fundamental speech parameters (pitch, formants, intensity), compresses them into a low-dimensional latent space via neural autoencoders, applies creative transformations in that latent space, and resynthesizes audio using Praat's KlattGrid source-filter model. The system produces multiple variations of the input audio through controlled manipulations of the learned latent representation, enabling creative audio transformations while preserving speech-like qualities.
Key Features:
Dual Autoencoder Architecture — Separate encoder/decoder networks for precise control
Visual Network Analysis — Automatic topology and weight visualization
Parameter Bottleneck — User-controllable compression ratio (3-10 dimensions)
Why Parametric Autoencoders for Audio Transformation? Traditional audio effects apply transformations directly to waveforms, which can degrade quality or produce unnatural artifacts. This system takes a parametric approach: (1) Analysis: Extract perceptually relevant features (F0, formants, intensity). (2) Compression: Train autoencoders to learn efficient latent representations. (3) Transformation: Apply mathematical operations in latent space. (4) Resynthesis: Use KlattGrid for high-quality vocoding. Benefits: (1) Preserves speech quality: Formant structure maintained. (2) Controllable transformations: Each latent operation has predictable effect. (3) Creative exploration: Generate multiple variations automatically. (4) Efficient: Works on parameters not raw audio. The hybrid approach combines neural networks with traditional speech synthesis for robust, musical results.
Technical Implementation: (1) Feature extraction: Pitch (AC method), 5 formants (Burg), intensity at configurable time steps. (2) Normalization: Scale all parameters to 0-1 range per parameter type. (3) Autoencoder training: Train feedforward networks to compress parameters to bottleneck size. (4) Latent extraction: Extract compressed representation from encoder. (5) Decoder training: Train separate network to reconstruct parameters from latent space. (6) Latent transformations: Apply 8 different mathematical operations. (7) KlattGrid synthesis: Convert parameters back to audio with source-filter model. (8) Visualization: Draw network topology and weight matrices. The complete pipeline runs within Praat using built-in neural and synthesis capabilities.
Quick start
In Praat, select exactly one Sound object (mono recommended).
Run script… → parametric_autoencoder_hybrid.praat.
Choose Preset_selection: "Clean - Dynamic Amplitude" for speech, "Glitch - Constant Drone" for experimental.
Set Time_step: 0.01s (10ms) for detailed analysis, 0.02s for faster processing.
Set Bottleneck_size: 3-5 for high compression, 8-10 for better reconstruction.
Set Epochs: 150 for good training, 300+ for optimal results.
Set Num_variations: 7 for all 8 operations (including original).
Set synthesis: Bandwidth_fraction (0.1 for natural, 0.2 for robotic).
For Clean preset: Set Aspiration_during_unvoiced (20dB typical).
Enable Draw_network to visualize autoencoder architecture.
Click OK — analysis, training, transformation, and synthesis will run.
Quick tip: Start with "Clean - Dynamic Amplitude" preset for speech processing. For musical/experimental results, use "Glitch - Constant Drone". The bottleneck size controls compression: lower values (3-5) create more abstract transformations, higher values (8-10) preserve more details. Time_step affects temporal resolution: 10ms for detailed speech, 20ms for faster processing. Processing stages: (1) Feature extraction (5-30 seconds), (2) Autoencoder training (30-90 seconds), (3) Latent transformation, (4) KlattGrid synthesis. For best results, use clean speech recordings 2-10 seconds long. The network visualization helps understand compression behavior. All 8 variations are generated automatically with descriptive names.
Important:MONO INPUT REQUIRED: Stereo converted to mono for analysis. PROCESSING TIME: Training autoencoders takes time (60-180 seconds). PARAMETER EXTRACTION: Requires Praat's pitch, formant, intensity analyses. VOICED/UNVOICED: Works best on clearly voiced speech. LATENT SPACE SIZE: Bottleneck must be ≤ number of parameters (5 or 6). KLATTGRID LIMITATIONS: Fixed 4 formant synthesis, no nasal coupling. PRESET DIFFERENCES: v0.6 uses dynamic amplitude, v0.4 uses constant drone. NOISE LEVELS: High latent_noise values may create unstable results. TEMPORAL RESOLUTION: Very short time_step with long files creates large matrices. VISUALIZATION: Draw_network creates multiple viewports.
Training: Two-phase: autoencoder then decoder-only
Activation: Sigmoid throughout for [0,1] constraints
Loss: Mean squared error (MSE) for parameter regression
Network Implementation Details
# DUAL NETWORK IMPLEMENTATION
# PHASE 1: AUTOENCODER TRAINING
# Train full autoencoder to learn compression
Create FFNet: "Autoencoder", nparams, nparams, bottleneck_size, 0
# Architecture: nparams → bottleneck_size → nparams
# Training data:
To Pattern: train_matrix # nparams × N_frames → Pattern object
To ActivationList: train_matrix # Target activations
Learn: epochs, 0.001, "Minimum-squared-error"
# PHASE 2: ENCODER EXTRACTION
# Extract latent representations from trained autoencoder
To ActivationList: 1 # Get hidden layer activations
# Result: bottleneck_size × N_frames latent matrix
# PHASE 3: DECODER TRAINING
# Train separate decoder network
Create FFNet: "Decoder", bottleneck_size, nparams, 0, 0
# Architecture: bottleneck_size → nparams (no hidden layer)
# Training data:
To Pattern: hidden_matrix # Latent representations as input
To ActivationList: train_matrix # Original parameters as target
Learn: epochs, 0.001, "Minimum-squared-error"
# NETWORK VISUALIZATION:
IF draw_network = 1:
# Left panel: Encoder topology
Draw topology: "Autoencoder"
# Right panel: Decoder topology
Draw topology: "Decoder"
# Weight visualizations:
Draw weights: 1, "yes" # Show weight matrices
# Layout: Two networks side by side
# Encoder: Shows compression mapping
# Decoder: Shows reconstruction mapping
# WEIGHT INTERPRETATION:
# Encoder weights W_enc: nparams × bottleneck_size
# - Shows which parameters contribute to each latent dimension
# - Large absolute values = strong contribution
# - Pattern reveals feature combinations
# Decoder weights W_dec: bottleneck_size × nparams
# - Shows how latent dimensions reconstruct parameters
# - Reveals which parameters are coupled in reconstruction
# SIGMOID ACTIVATION PROPERTIES:
σ(x) = 1 / (1 + e^{-x})
- Output range: (0, 1)
- Smooth, differentiable
- Natural for normalized parameters
- Prevents extreme values
Training Parameters & Convergence
Optimization & Stability
# TRAINING PARAMETERS & CONVERGENCE
# EPOCHS: Number of training iterations
# Typical: 150-300 epochs
# Effect: More epochs = better reconstruction but longer training
# Tradeoff: Diminishing returns after ~200 epochs
# LEARNING RATE: 0.001 (fixed)
# Small enough for stable convergence
# Large enough for reasonable training speed
# No adaptive learning rate (simple SGD)
# BATCH SIZE: Entire dataset (batch gradient descent)
# Praat's Learn function uses all patterns each iteration
# Stable but memory intensive for large datasets
# LOSS FUNCTION: Minimum-squared-error (MSE)
L = 1/N Σ_{i=1}^N Σ_{j=1}^{nparams} (x_{ij} - x̂_{ij})²
# CONVERGENCE CRITERIA (empirical):
1. Loss decreases monotonically (check Praat Info window)
2. Reconstruction visually matches original parameters
3. Latent space values stay within [0, 1] range
4. No NaN or extreme values in weights
# TROUBLESHOOTING TRAINING:
PROBLEM: Loss not decreasing
SOLUTION: Increase epochs, check data normalization
PROBLEM: Reconstruction too smooth/bland
SOLUTION: Increase bottleneck_size, decrease compression
PROBLEM: Training too slow
SOLUTION: Increase time_step, reduce N_frames
PROBLEM: Unstable/oscillating loss
SOLUTION: Data may be too noisy, increase voicing_threshold
# VISUAL CONVERGENCE CHECK:
# After training, compare:
# 1. Original vs. reconstructed pitch contours
# 2. Original vs. reconstructed formant tracks
# 3. Latent space visualization (if draw_network=1)
# Good convergence: Reconstructions follow originals closely
# Poor convergence: Reconstructions flat or erratic
Visualization System
Network Analysis & Debugging
📊 Multi-Panel Network Visualization
Topology plots: Show network architecture
Weight matrices: Display learned connections
Layout: Encoder left, decoder right
Information: Preset, parameters, bottleneck size
Purpose: Debugging, education, analysis
Latent Space Operations
8 Transformation Types
🎨 Creative Latent Manipulations
Original: Baseline reconstruction (no transformation)
Noise: Gaussian noise injection in latent space
Scale: Multiply first latent dimension
Invert: Mirror second dimension around mean
Smooth: Temporal smoothing for legato effect
Warp: Non-linear time distortion
Swap: Exchange latent dimensions
Interp: Move toward latent centroid
Transformation Mathematics
# LATENT SPACE TRANSFORMATIONS
# Input: Z ∈ ℝ^{bottleneck × N_frames} (latent matrix)
# Each transformation produces Z' for resynthesis
# 1. ORIGINAL (Var0): Baseline
Z' = Z # No change
# 2. NOISE (Var1): Gaussian noise injection
noise_amt = latent_noise × latent_range × 0.3
FOR each element z_ij in Z:
z'_ij = z_ij + N(0, noise_amt) # Add Gaussian noise
# 3. SCALE (Var2): Scale first dimension
FOR each time frame j:
z'_{1j} = z_{1j} × 1.3 + 0.1 # Scale and shift
# Other dimensions unchanged
# 4. INVERT (Var3): Mirror second dimension
IF bottleneck_size ≥ 2:
d2_mean = mean(Z[2,:]) # Mean of second dimension
FOR each time frame j:
z'_{2j} = 2 × d2_mean - z_{2j} # Mirror around mean
# 5. SMOOTH (Var4): Temporal smoothing
FOR each dimension i:
FOR each time frame j from 2 to N_frames-1:
z'_ij = (z_{i,j-1} + z_{ij} + z_{i,j+1}) / 3 # 3-point average
# 6. WARP (Var5): Non-linear time distortion
warp_factor = 1.5 # Warp exponent
FOR each time frame j:
# Non-linear mapping of time indices
warp_idx = round(1 + (N_frames-1) × ((j-1)/(N_frames-1))^warp_factor)
warp_idx = clamp(warp_idx, 1, N_frames)
FOR each dimension i:
z'_ij = z_{i, warp_idx} # Sample from warped position
# 7. SWAP (Var6): Exchange dimensions
IF bottleneck_size ≥ 2:
FOR each time frame j:
z'_{1j} = z_{2j} # Dimension 1 gets dimension 2
z'_{2j} = z_{1j} # Dimension 2 gets dimension 1
# Other dimensions unchanged
# 8. INTERP (Var7): Move toward centroid
FOR each dimension i:
d_mean = mean(Z[i,:]) # Dimension mean
FOR each time frame j:
z'_ij = 0.6 × z_{ij} + 0.4 × d_mean # Interpolate toward mean
# CLAMPING: Ensure values stay in [0, 1]
FOR all elements z'_ij in Z':
IF z'_ij < 0: z'_ij = 0
IF z'_ij > 1: z'_ij = 1
# TRANSFORMATION STRENGTH CONTROLS:
latent_noise: Controls noise amplitude (0.1-0.3)
latent_range: Auto-calculated from data
bottleneck_size: Affects which transformations available
# EXPECTED AUDIO EFFECTS:
- Noise: Adds breathiness/instability
- Scale: Changes vocal character
- Invert: Creates spectral mirroring
- Smooth: Legato, connected speech
- Warp: Time-stretching/compression
- Swap: Alters feature relationships
- Interp: Homogenizes, reduces variation
Latent Space Interpretation
Understanding Learned Representations
🔍 Interpreting Latent Dimensions
Dimension 1: Often corresponds to overall spectral tilt or voice quality
Dimension 2: Frequently related to F0/pitch contour
Dimension 3: May capture formant structure or vowel space
Higher dimensions: Capture finer details or noise characteristics
Visual clues: Weight matrices show parameter contributions
KlattGrid Synthesis System
Source-Filter Resynthesis
🔊 Formant-Based Speech Synthesis
Source: Voiced/unvoiced excitation with dynamic amplitude
Filter: 4-formant vocal tract model
Parameters: F0, F1-F4 frequencies & bandwidths
Amplitude: Dynamic (v0.6) or constant (v0.4)
Aspiration: Controlled unvoiced excitation
KlattGrid Implementation
# KLATTGRID SYNTHESIS IMPLEMENTATION
# CREATE KLATTGRID:
Create KlattGrid: name$, start_time, end_time, 4, 0, 0, 0, 0, 0, 0
# Parameters: 4 formants, no nasal, no tracheal, etc.
# 1. PITCH CONTOUR (F0):
Remove pitch points between: start_time, end_time
FOR each frame i at time t_i:
f0_val = reconstructed_f0[i]
IF f0_val > pitch_floor AND f0_val < pitch_ceiling × 1.5:
Add pitch point: t_i, f0_val # Add voiced pitch point
# Fallback if no voiced frames:
IF no_pitch_points_added:
Add pitch point: start_time, 120 # Default 120Hz
Add pitch point: end_time, 120
# 2. FORMANT TRACKS (F1-F4):
FOR each formant f from 1 to 4:
Remove oral formant frequency points: f, start_time, end_time
Remove oral formant bandwidth points: f, start_time, end_time
FOR each frame i at time t_i:
f_val = reconstructed_formant[f][i]
# Per-formant clamping to prevent crossovers:
IF f = 1: f_val = clamp(f_val, 200, 1000)
IF f = 2: f_val = clamp(f_val, 500, 3000)
IF f = 3: f_val = clamp(f_val, 1500, 4000)
IF f = 4: f_val = clamp(f_val, 2500, 5000)
# Bandwidth calculation:
bw = f_val × bandwidth_fraction
bw = clamp(bw, 50, 500) # Minimum 50Hz
Add oral formant frequency point: f, t_i, f_val
Add oral formant bandwidth point: f, t_i, bw
# 3. AMPLITUDE CONTROL (two presets):
# PRESET v0.6: CLEAN - Dynamic Amplitude
IF preset = "Clean":
FOR each frame i at time t_i:
f0_val = reconstructed_f0[i]
int_val = reconstructed_intensity[i]
# Normalize intensity to dB scale:
amp = 90 × (int_val - int_min) / int_range
amp = clamp(amp, 0, 90)
IF f0_val > pitch_floor: # Voiced
Add voicing amplitude point: t_i, amp
Add aspiration amplitude point: t_i, 0
ELSE: # Unvoiced
Add voicing amplitude point: t_i, 0
Add aspiration amplitude point: t_i, aspiration_during_unvoiced
# PRESET v0.4: GLITCH - Constant Drone
ELSE:
Add voicing amplitude point: start_time, 90
Add voicing amplitude point: end_time, 90
Add aspiration amplitude point: start_time, 0
Add aspiration amplitude point: end_time, 0
# 4. SYNTHESIZE:
To Sound # Convert KlattGrid to Sound object
# 5. NORMALIZE OUTPUT:
Scale peak: 0.95 # Prevent clipping
# KLATTGRID PARAMETERS EXPLANATION:
# - 4 formants: Sufficient for intelligible speech
# - Bandwidth fraction: 0.1 = natural, 0.2 = robotic
# - Aspiration during unvoiced: Adds breathiness
# - Voicing amplitude: Controls loudness of voiced parts
# - Aspiration amplitude: Controls breath noise level
# QUALITY CONSIDERATIONS:
# Strengths: Precise formant control, efficient synthesis
# Limitations: Fixed formant count, no nasal coupling
# Best for: Speech transformation, vocal effects
# Less suitable: Natural singing, complex phonetics
Preset-Specific Synthesis
Clean vs. Glitch Synthesis Modes
# PRESET-SPECIFIC SYNTHESIS DIFFERENCES
# === PRESET v0.6: CLEAN - Dynamic Amplitude ===
# Designed for natural speech transformation
# Parameters: 6 (F0, F1-F4, intensity)
# Amplitude: Dynamic, follows intensity contour
# Voicing: Gated by F0 (pitch detection)
# Aspiration: Added during unvoiced regions
# Use cases: Speech processing, vocal effects, text-to-speech
# Workflow:
1. Extract intensity contour from original
2. Normalize intensity 0-1 across utterance
3. Reconstruct intensity from latent space
4. Convert to dB scale (0-90 dB)
5. Apply voicing gate: voiced = intensity, unvoiced = 0
6. Add aspiration during unvoiced regions
# Result: Natural amplitude modulation, breathy unvoiced regions
# === PRESET v0.4: GLITCH - Constant Drone ===
# Designed for experimental/ musical effects
# Parameters: 5 (F0, F1-F4 only) - NO intensity
# Amplitude: Constant 90 dB throughout
# Voicing: Always on (drone mode)
# Aspiration: Always off
# Use cases: Drone music, glitch art, experimental composition
# Workflow:
1. Ignore intensity parameter
2. Set constant 90 dB voicing amplitude
3. Set 0 dB aspiration amplitude
4. All frames treated as voiced
# Result: Continuous drone, no amplitude modulation
# === PARAMETER DIFFERENCES ===
v0.6 (Clean): [F0, F1, F2, F3, F4, Intensity] (6 params)
v0.4 (Glitch): [F0, F1, F2, F3, F4] (5 params)
# === SYNTHESIS QUALITY TRADEOFFS ===
Clean preset:
+ More natural amplitude dynamics
+ Better unvoiced/voiced transitions
+ Requires accurate intensity extraction
- More parameters to learn (6 vs 5)
Glitch preset:
+ Simpler, more stable training (5 params)
+ Creates interesting drone effects
+ Good for musical applications
- No amplitude dynamics
- Always voiced (may sound unnatural)
# === CHOOSING A PRESET ===
Choose CLEAN (v0.6) when:
- Processing speech for natural results
- Need amplitude dynamics
- Working with clear voiced/unvoiced regions
Choose GLITCH (v0.4) when:
- Creating musical/experimental effects
- Want constant drone texture
- Original has poor intensity extraction
- Prioritizing stability over naturalness
Parameters & Specifications
Preset Selection
Parameter
Type
Default
Description
Preset_selection
option
Clean - Dynamic Amplitude
v0.6 (6 params) for speech, v0.4 (5 params) for drone
Analysis Parameters
Parameter
Type
Default
Range
Description
Time_step
positive
0.01
0.005 - 0.05
Temporal resolution in seconds (10ms typical)
Pitch_floor
positive
60
50 - 200
Minimum F0 for pitch detection (Hz)
Pitch_ceiling
positive
500
200 - 1000
Maximum F0 for pitch detection (Hz)
Voicing_threshold
positive
0.4
0.1 - 0.9
AC pitch voicing threshold (higher = stricter)
Network Architecture
Parameter
Type
Default
Range
Description
Bottleneck_size
positive
3
2 - 10
Latent space dimensionality (must be ≤ nparams)
Epochs
positive
150
50 - 500
Training iterations for autoencoder
Transformation Parameters
Parameter
Type
Default
Range
Description
Num_variations
positive
7
1 - 10
Number of latent transformations to generate
Latent_noise
positive
0.15
0.0 - 0.5
Strength of Gaussian noise injection
Synthesis Parameters
Parameter
Type
Default
Range
Preset
Description
Bandwidth_fraction
positive
0.1
0.05 - 0.3
Both
Formant bandwidth as fraction of frequency
Aspiration_during_unvoiced
positive
20
0 - 60
Clean only
Aspiration amplitude during unvoiced regions (dB)
Visualization
Parameter
Type
Default
Description
Draw_network
boolean
1 (yes)
Generate network topology and weight visualizations
Performance Characteristics
Characteristic
Typical Value
Dependence
Notes
Processing time
60-180 seconds
File length, epochs, bottleneck
Mostly neural training time
Memory usage
O(N×nparams)
Linear in duration × parameters
Parameter matrix storage
Reconstruction quality
85-95% MSE
Bottleneck size, epochs
Lower bottleneck = more loss
Latent operations
8 types
Bottleneck size
Some require bottleneck ≥ 2
Output variations
1-11 sounds
Num_variations setting
Including original reconstruction
Network Architecture Details
Component
v0.6 (Clean)
v0.4 (Glitch)
Description
Input parameters
6
5
F0, F1-F4, (intensity for v0.6)
Bottleneck range
2-6
2-5
Must be ≤ input parameters
Encoder layers
6 → bottleneck
5 → bottleneck
Single hidden layer
Decoder layers
bottleneck → 6
bottleneck → 5
No hidden layer (direct)
Activation
Sigmoid
Sigmoid
All layers, output [0,1]
Loss function
MSE
MSE
Mean squared error
Learning rate
0.001
0.001
Fixed for all training
Applications
Speech Processing & Voice Transformation
Use case: Creative voice effects for audio production
Recommended preset: v0.6 (Clean) with bottleneck 3-4
Typical workflow:
Use "Noise" variation for breathy voice effect
Use "Smooth" for legato, connected speech
Use "Warp" for time-stretching effects
Combine with reverb for atmospheric vocals
Experimental Music & Sound Design
Use case: Generating drone textures and glitch art
Recommended preset: v0.4 (Glitch) with bottleneck 2-3
For speech clarity: bottleneck ≥ 4, bandwidth_fraction = 0.1-0.12
For abstract effects: bottleneck = 2-3, bandwidth_fraction = 0.15-0.2
Training stability: epochs = 150-200, learning_rate = 0.001 fixed
Temporal quality: time_step = 0.01s for speech, 0.02s for music
Transformation strength: latent_noise = 0.1-0.2 for noticeable effects
Always monitor Praat Info window for training progress
Troubleshooting Common Issues
Problem: No pitch points detected Cause: Voicing_threshold too high, or input has no clear pitch Solution: Lower voicing_threshold to 0.3, check pitch range settings
Problem: Training doesn't converge (loss high) Cause: Bottleneck too small, or epochs too few Solution: Increase bottleneck_size, increase epochs to 200+
Problem: Synthesized audio sounds robotic Cause: Bandwidth_fraction too high, or formant clamping too restrictive Solution: Reduce bandwidth_fraction to 0.08-0.12, adjust formant ranges
Problem: Variations sound too similar Cause: Latent_noise too low, or bottleneck too large Solution: Increase latent_noise to 0.2-0.3, reduce bottleneck_size
Problem: Processing time extremely long Cause: Very long audio file with small time_step Solution: Increase time_step to 0.02s, or process shorter segments