Non-Linear Frequency Folding — User Guide
Spectral mirroring & folding: applies frequency‑domain reflections (folding) combined with sinusoidal modulation to create complex harmonic intermodulation, spectral knots, and alien‑like transformations through non‑linear frequency remapping.
What this does
This script implements non‑linear frequency folding — a spectral processing technique that "folds" high frequencies back into lower ranges through mirror‑like reflections, creating complex intermodulation products and harmonic relationships. Unlike traditional pitch‑shifting or harmonizing, which preserve linear frequency relationships, folding creates non‑linear mappings where frequencies are reflected around multiple "mirror points" (folding_period intervals) and modulated by sinusoidal gain patterns. The result is a dense, often metallic or alien‑sounding transformation that preserves rhythmic and textural qualities while radically altering spectral content.
Key Features:
- 5 Themed Presets — Default, Tight Knots, Loose Knots, High Preservation, Fast Modulation
- Intelligent Optimization — Automatic downsampling, chunked processing for long files
- Dual‑Layer Processing — Frequency folding + sinusoidal amplitude modulation
- Threshold Protection — Low frequencies (< low_freq_threshold) preserved unchanged
- FFT‑Based Processing — True spectral‑domain manipulation (not time‑domain tricks)
- Memory‑Efficient Design — Chunking prevents memory overload on long sounds
- Non‑Destructive Workflow — Original preserved, output named with "_spectral_knots" suffix
- Mirror reflection: Frequency f is reflected around multiples of folding_period
- Mathematical form: f → |f - 2 × round(f/folding_period) × folding_period|
- Effect: High frequencies become lower but with complex relationships to original
- Modulation layer: Folded spectrum multiplied by (sin + cos)² gain pattern
- Result: Creates "spectral knots" — dense clusters of harmonically related components
Technical Implementation: The script operates in the frequency domain: (1) Convert to Spectrum via FFT (fast_fourier option). (2) Apply folding formula to each frequency bin: frequencies below low_freq_threshold pass unchanged; higher frequencies are folded via reflection formula and multiplied by modulation pattern. (3) Convert back to Sound via inverse FFT. Optimization features include: optional downsampling to processing_sample_rate (default 22050 Hz) for speed, and chunked processing (divide long sounds into chunk_duration segments) for memory management. The formula is built once then applied to the entire spectrum (or each chunk).
Quick start
- In Praat, select exactly one Sound object to process.
- Run script… →
nonlinear_frequency_folding.praat. - Choose a Preset (Default, Tight Knots, Loose Knots, etc.) or keep Default.
- Enable use_downsampling (recommended for speed) and set processing_sample_rate (22050 Hz default).
- Enable use_chunking for sounds >10 seconds (prevents memory issues).
- Adjust folding parameters if desired (folding_period, modulation divisors).
- Set scale_peak (0.88 default) and play_after_processing.
- Click OK — script converts, processes spectrum, converts back.
- Output appears as:
originalName_spectral_knots. - Watch Info window for progress (downsampling, chunking, processing steps).
Frequency Folding Theory
The Mirror Folding Operation
🪞 Mathematical Folding Formula
Core reflection equation:
Example with P=1000 Hz:
Visualizing the Folding Pattern
📊 Frequency Mapping Diagram
Original Frequency (Hz) Folded Frequency (Hz)
0─P (0‑1000) → 0‑1000 (unchanged)
P─2P (1000‑2000) → 1000‑0 (mirrored down)
2P─3P (2000‑3000) → 0‑1000 (folded up then down)
3P─4P (3000‑4000) → 1000‑0 (etc.)
Pattern repeats every 2P (2000 Hz):
[0, P] → [0, P] (identity)
[P, 2P] → [P, 0] (mirror)
[2P, 3P] → [0, P] (fold)
[3P, 4P] → [P, 0] (mirror)
etc.
Effectively creates "spectral origami" — folding spectrum onto itself.
Why absolute value? Ensures folded frequency is always positive (negative frequencies would be complex conjugate in real signal, but we work with magnitude spectrum).
Sinusoidal Modulation Layer
📈 Amplitude Modulation Pattern
Modulation formula: (sin(f/sine_divisor) + cos(f/cosine_divisor))²
Component analysis:
Effect on spectrum: Creates amplitude "ripples" across frequency — alternating bands of boost and cut. The squared operation ensures all values are positive (no phase inversion).
Complete Signal Flow
🔄 Processing Pipeline
INPUT: Original sound (mono or stereo converted)
STEP 1: OPTIMIZATION PREPARATION
• Convert to mono if stereo (average channels)
• Downsample to processing_sample_rate if enabled
• Split into chunks if chunking enabled
FOR EACH CHUNK (or whole sound):
STEP 2: TIME → FREQUENCY DOMAIN
• To Spectrum: fast_fourier (FFT with Hann window)
• Result: complex spectrum (magnitude + phase)
STEP 3: APPLY FOLDING FORMULA
For each frequency bin f:
if f < low_freq_threshold:
output[f] = input[f] (preserve lows)
else:
folded_f = |f - 2*round(f/folding_period)*folding_period|
modulation = (sin(f/sine_divisor) + cos(f/cosine_divisor))^2
output[f] = input[folded_f] × modulation
STEP 4: FREQUENCY → TIME DOMAIN
• To Sound (inverse FFT)
• Overlap‑add reconstruction
STEP 5: RECONSTRUCTION
• Concatenate chunks if chunked
• Resample back to original sample rate if downsampled
• Scale peak to scale_peak
• Rename to originalName_spectral_knots
OUTPUT: Processed sound
The Core Formula Explained
Complete Formula Construction
Praat‑Specific Implementation Details
Mathematical Properties of the Formula
🔬 Analysis of Components
Folding function properties:
- Periodicity: folded_f repeats every 2×folding_period
- Symmetry: folded_f(f) = folded_f(2P - f) for f∈[P,2P]
- Idempotent: Applying twice doesn't change result (folded of folded = folded)
- Range: folded_f ∈ [0, folding_period]
Modulation function properties:
- Range: (sin+cos)² ∈ [0, 4] (sin and cos each ∈ [-1,1])
- Mean value: Average ≈ 1.0 (sin² avg=0.5, cos² avg=0.5, cross term avg=0)
- Periodicity: Components periodic with periods 2π·sine_divisor and 2π·cosine_divisor
- Always positive: No phase inversion from modulation
Combined effect: Creates frequency‑dependent amplitude modulation on already‑folded spectrum. The modulation's frequency (in Hz⁻¹ space) creates "beating" patterns in spectral domain.
Alternative Interpretation: Spectral Convolution View
🎛️ Time‑Domain Equivalent
Folding in frequency domain corresponds to convolution in time domain:
Thus, the spectral processing creates effects similar to complex delay networks or comb filters, but with mathematical precision in frequency domain.
Preset Configurations
Preset 1: Default
⚙️ Balanced Settings
Parameters:
- folding_period: 1000 Hz
- sine_modulation_divisor: 300
- cosine_modulation_divisor: 150
- low_freq_threshold: 100 Hz
Folding behavior: Mirrors around 1000 Hz intervals. Frequencies 1000‑2000 Hz fold down to 1000‑0 Hz; 2000‑3000 Hz fold to 0‑1000 Hz, etc.
Modulation behavior: Sine period = 2π×300 ≈ 1885 Hz cycle, cosine period = 2π×150 ≈ 942 Hz cycle. Combined creates complex interference pattern.
Sonic character: Balanced between folding and modulation effects. Creates noticeable spectral transformation without extreme density.
Preset 2: Tight Knots
🎗️ Dense Spectral Clustering
Parameter change: folding_period = 500 Hz (half of default)
Effect: More frequent folding — spectrum folds every 500 Hz instead of 1000 Hz. Creates denser "knots" as more frequency ranges are compressed into 0‑500 Hz band.
Mathematical impact: With P=500, frequency range 0‑2000 Hz undergoes 4 fold segments (0‑500, 500‑1000, 1000‑1500, 1500‑2000) instead of 2 segments with P=1000.
Sonic character: Denser, more metallic, more extreme transformation. Higher frequencies get folded more times, creating complex intermodulation.
Best for: Extreme sound design, creating metallic textures, complete spectral reconstruction.
Preset 3: Loose Knots
🎗️ Open, Harmonically Rich
Parameter change: folding_period = 2000 Hz (double default)
Effect: Less frequent folding — spectrum folds every 2000 Hz. More frequencies pass through unchanged or undergo simpler transformations.
Mathematical impact: With P=2000, frequency range 0‑4000 Hz has only 2 fold segments (0‑2000, 2000‑4000). More spectral space between folds.
Sonic character: More open, less dense, retains more of original harmonic structure while still applying folding. Good for subtle‑to‑moderate effects.
Best for: Harmonic enhancement, adding complexity without overwhelming original, musical applications.
Preset 4: High Preservation
🎵 Protect Low Frequencies
Parameter change: low_freq_threshold = 500 Hz (5× default)
Effect: Frequencies below 500 Hz pass completely unchanged (no folding, no modulation). Only frequencies >500 Hz are processed.
Rationale: Bass frequencies often carry fundamental pitch and rhythm; preserving them maintains some connection to original while transforming higher harmonics.
Sonic character: Maintains bass/beat structure while transforming mid/high frequencies. More musically useful for rhythm‑based material.
Best for: Music processing where you want to keep bass/kick drum intact, vocal processing preserving low formants.
Preset 5: Fast Modulation
🌀 Rapid Amplitude Variations
Parameter changes:
- sine_modulation_divisor = 150 (half default)
- cosine_modulation_divisor = 75 (half default)
Effect: Modulation pattern cycles twice as fast across frequency axis. Creates more rapid alternation of boost/cut bands.
Mathematical impact: Modulation periods: sine = 2π×150 ≈ 942 Hz cycle, cosine = 2π×75 ≈ 471 Hz cycle. More cycles per octave.
Sonic character: Brighter, more detailed modulation effect. Folding combined with fast modulation creates intricate spectral patterns.
Best for: Adding fine‑grained texture, creating "shimmering" effects, detailed sound design.
Preset Comparison Table
| Preset | folding_period | sine_divisor | cosine_divisor | low_freq_threshold | Character |
|---|---|---|---|---|---|
| Default | 1000 | 300 | 150 | 100 | Balanced |
| Tight Knots | 500 | 300 | 150 | 100 | Dense, metallic |
| Loose Knots | 2000 | 300 | 150 | 100 | Open, harmonic |
| High Preservation | 1000 | 300 | 150 | 500 | Bass‑preserving |
| Fast Modulation | 1000 | 150 | 75 | 100 | Detailed, shimmering |
Optimization Features
Downsampling for Speed
📉 Intelligent Sample Rate Reduction
When enabled (use_downsampling=1):
- Original sound resampled to processing_sample_rate (default 22050 Hz)
- All processing (FFT, folding, modulation) occurs at lower rate
- Result resampled back to original sample rate
Why 22050 Hz?
- Nyquist frequency = 11025 Hz — covers most audible content
- FFT size halves compared to 44100 Hz → 4× speed improvement
- Frequency resolution still adequate for folding effects
- Human hearing sensitivity decreases above 10 kHz anyway
Mathematical impact:
When to disable: When processing high‑frequency content >11 kHz is critical, or for very short sounds where FFT overhead dominates.
Chunked Processing for Memory Management
🧩 Divide & Conquer Large Files
When enabled (use_chunking=1) and duration > chunk_duration:
- Sound divided into chunks of chunk_duration seconds (default 10 s)
- Each chunk processed independently (FFT → formula → inverse FFT)
- Processed chunks concatenated back together
Benefits:
- Memory: FFT requires memory ~2×N samples; chunking reduces peak memory
- Stability: Prevents Praat crashes on very long files
- Progress feedback: Shows chunk‑by‑chunk progress in Info window
- Flexibility: Can adjust chunk_duration based on available memory
Chunk size recommendations:
| Sound Duration | Recommended chunk_duration | Why |
|---|---|---|
| <10 s | Disable chunking (process whole) | Overhead outweighs benefits |
| 10‑60 s | 10 s | Balanced memory/time |
| 1‑5 min | 20 s | Fewer chunks, faster concatenation |
| >5 min | 30 s | Minimize number of chunks |
Formula Pre‑Building Optimization
⚡ Formula Construction Once
Key optimization in script:
Why this matters:
- Performance: String concatenation done once, not per‑bin
- Memory: Single formula string reused for all chunks
- Accuracy: Ensures identical formula across entire processing
- Debugging: Can print formula$ to verify correctness
Alternative (slower) approach: Re‑build formula for each frequency bin → O(N²) string operations.
Parameters Explained
Folding Parameters
| Parameter | Type | Default | Range | Description |
|---|---|---|---|---|
| folding_period | positive | 1000 | 10‑10000 | Frequency interval for folding (Hz). Lower = denser knots. |
| low_freq_threshold | positive | 100 | 0‑5000 | Frequencies below this pass unchanged (Hz). |
| sine_modulation_divisor | positive | 300 | 10‑1000 | Divisor for sin(f/divisor) in modulation. |
| cosine_modulation_divisor | positive | 150 | 10‑1000 | Divisor for cos(f/divisor) in modulation. |
| fast_fourier | boolean | yes | yes/no | Use FFT for spectral conversion (faster). |
Optimization Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| use_downsampling | boolean | 1 | Downsample to processing_sample_rate before processing. |
| processing_sample_rate | positive | 22050 | Target sample rate for processing (Hz). |
| use_chunking | boolean | 1 | Process in chunks for memory management. |
| chunk_duration | positive | 10 | Duration of each chunk (seconds). |
Output Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| scale_peak | positive | 0.88 | Peak amplitude scaling (0‑1). 0.88 prevents clipping. |
| play_after_processing | boolean | 1 | Automatically play result after processing. |
Parameter Interaction Tips
- folding_period vs low_freq_threshold: If low_freq_threshold > folding_period, folding won't affect frequencies below threshold (good for preserving bass).
- sine_divisor vs cosine_divisor: Ratio affects modulation pattern. Equal divisors create simpler pattern; different divisors create complex interference.
- processing_sample_rate vs folding_period: Ensure folding_period < processing_sample_rate/2 (Nyquist). With default 22050 Hz, keep folding_period < 11025 Hz.
- chunk_duration vs memory: Larger chunks use more memory but fewer concatenation operations.
Sonic Applications
Creative Sound Design
🎨 Transform Ordinary Sounds
Vocal processing: Apply Tight Knots preset to spoken word — creates robotic, alien vocal effects with metallic resonances.
Percussion transformation: Process drum loops with High Preservation — maintains beat integrity while adding spectral complexity to hi‑hats and cymbals.
Ambient textures: Use Loose Knots on field recordings — creates evolving, harmonically rich pads from environmental sounds.
Synth processing: Apply Fast Modulation to simple synth tones — adds intricate spectral movement and "shimmer".
Musical Applications
🎵 Harmonic Reconstruction
Chord transformation: Process piano chords with Default preset — creates complex harmonic clusters with intermodulation products.
Melodic processing: Apply to monophonic instruments — generates artificial harmonics and sidebands that follow the melody.
Rhythmic effects: Use High Preservation on rhythmic material — maintains groove while adding spectral interest.
Texture building: Layer folded version with original — creates rich, evolving textures with beating patterns.
Experimental Techniques
🔬 Advanced Processing Chains
Iterative folding: Process sound, then process result again with different parameters — creates extremely dense, complex spectra.
Selective frequency ranges: Use Praat's filtering before folding — isolate specific frequency bands for targeted transformation.
Parallel processing: Process same sound with different presets, then mix — creates multi‑dimensional spectral effects.
Time‑varying parameters: Process in sections with different folding_period values — creates evolving spectral transformations.
Practical Workflow Examples
👽 Alien Voice Effect
Goal: Create robotic, alien vocal effect from speech
Settings:
- Preset: Tight Knots
- folding_period: 400 Hz (even denser than preset)
- low_freq_threshold: 50 Hz (preserve vocal fundamentals)
- use_downsampling: yes (22050 Hz)
- scale_peak: 0.95 (louder output)
Result: Speech becomes metallic, robotic, with complex harmonic resonances.
🎶 Pad from Field Recording
Goal: Transform environmental sound into musical pad
Settings:
- Preset: Loose Knots
- folding_period: 1500 Hz (open, harmonic)
- low_freq_threshold: 200 Hz (preserve some low texture)
- use_chunking: yes (chunk_duration=20 s)
- Add reverb after processing (external)
Result: Environmental sound becomes harmonically rich, evolving pad texture.
🥁 Complex Drum Processing
Goal: Add spectral complexity to drum loop while keeping beat
Settings:
- Preset: High Preservation
- low_freq_threshold: 300 Hz (preserve kick and snare fundamentals)
- folding_period: 800 Hz
- sine_divisor: 200, cosine_divisor: 100 (fast modulation)
- Mix 50% folded with 50% original
Result: Drum loop maintains punch while gaining complex hi‑hat and cymbal textures.
Troubleshooting & Tips
Causes: Too low folding_period, extreme modulation divisors, insufficient low_freq_threshold
Solutions: Increase folding_period, use more moderate modulation divisors, raise low_freq_threshold
Causes: Long file without chunking, high sample rate without downsampling
Solutions: Enable use_chunking, enable use_downsampling with 22050 Hz
Causes: Low scale_peak, folding concentrates energy in fewer frequencies
Solutions: Increase scale_peak to 0.95‑1.0, normalize after processing
Causes: Extreme folding (low folding_period), no low frequency preservation
Solutions: Use Loose Knots preset, increase low_freq_threshold, mix with original
Advanced Usage Notes
- Start subtle: Begin with Loose Knots or High Preservation before trying extreme settings
- Use monitoring: Enable play_after_processing to immediately hear results
- Experiment iteratively: Process, listen, adjust parameters, process again
- Combine with effects: Add reverb, delay, or filtering after folding for enhanced results
- Document settings: Note successful parameter combinations for reuse
- Consider context: Folded sounds work well as background textures or special effects