Advanced Chaotic Granular Synthesis — User Guide

Chaos-theory-driven granular synthesis: uses mathematical chaotic systems (Logistic, Hénon, Lorenz) to control grain timing and frequency for complex, evolving textures with deterministic yet unpredictable behavior.

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 chaos-based granular synthesis — generating complex sonic textures using mathematical chaotic systems to control grain parameters. Three chaotic systems available: (1) Logistic Map: Simple 1D chaotic recurrence for frequency modulation. (2) Hénon Map: 2D chaotic system for more complex frequency patterns. (3) Lorenz System: 3D continuous-time chaotic attractor for atmospheric textures. Process: (1) Pre-generates grain parameters using chaotic evolution, (2) Splits synthesis into manageable chunks to avoid formula limits, (3) Creates grains with frequencies derived from chaotic state variables, (4) Combines multiple layers with different chaotic trajectories, (5) Applies spatial processing for stereo effects.

Key Features:

What is chaotic granular synthesis? Traditional granular synthesis: random or regular grain timing/frequency. Chaotic granular synthesis: uses mathematical chaotic systems to control grain parameters. Chaotic systems exhibit: (1) Deterministic: Follow exact mathematical rules (no randomness). (2) Sensitive to initial conditions: Tiny changes lead to completely different outcomes. (3) Bounded but aperiodic: Stays within limits but never repeats exactly. (4) Complex evolution: Creates rich, evolving patterns. In this script: chaotic state variable → grain frequency. Result: grains follow complex frequency trajectories that sound "alive" and evolving. Different chaotic systems create different sonic characters: Logistic = wild fluctuations, Hénon = complex patterns, Lorenz = smooth atmospheric evolution.

Technical Implementation: (1) Parameter pre-generation: For each layer, calculate total grains = duration × density. For each grain: generate random time (uniform), evolve chaotic system, derive frequency from chaotic state, store parameters in arrays. (2) Chunking: Split duration into 2-second chunks. For each chunk: build formula string with grains whose times fall in chunk, limit to max_grains_per_chunk (30) to avoid formula limits. (3) Chunk synthesis: Create Sound from formula for each chunk. (4) Concatenation: Concatenate chunk sounds into layer. (5) Layer mixing: Combine all layers into final sound. (6) Spatial processing: Apply stereo effects if requested. Key innovations: Pre-generation avoids recomputing chaos during formula building. Chunking avoids Praat's formula length limits. Deterministic chaos ensures reproducibility.

Quick start

  1. In Praat, ensure no objects selected (generates from scratch).
  2. Run script…advanced_chaotic_granular.praat.
  3. Choose preset (Logistic Sparse recommended for first try).
  4. Or select Custom and adjust parameters manually.
  5. Set Duration (sec) for output length.
  6. Choose Synthesis_mode for chaotic system type.
  7. Set Grain_density for texture density.
  8. Choose Spatial_mode for stereo image.
  9. Click OK — chaotic synthesis runs with progress updates.
  10. Output named "chaotic_presetname" appears in Objects window.
  11. Output automatically played when complete.
Quick tip: Start with Logistic Sparse preset to hear clear chaotic evolution. Try Hénon Texture for more complex patterns. Use Lorenz Atmospheric for smooth, evolving textures. Duration affects generation time — 5-10 seconds good for testing. Base_frequency sets overall pitch range — 100-200Hz for bass/mid textures. Grain_density controls texture density — 5-10 grains/sec for sparse, 15-25 for dense. Number_of_layers adds complexity — each layer has independent chaotic evolution. Enable Randomize_parameters for variation between runs. Use Stereo Wide spatial mode for immersive chaotic textures.
Important: CHAOTIC SYSTEMS ARE DETERMINISTIC — same parameters produce same output (unlike random). INITIAL CONDITIONS MATTER — tiny parameter changes create completely different results. GRAIN LIMIT PER CHUNK — limited to 30 grains per 2-second chunk for performance. DENSE TEXTURES may exceed grain limit → some grains skipped. CHAOTIC BEHAVIOR may produce extreme frequencies — check output range. REPRODUCIBILITY enabled — same settings = same sound (good for composition). PERFORMANCE — chunking adds overhead but prevents crashes. EXPERIMENT SYSTEMATICALLY — small parameter changes can have large effects.

Chaos Theory Foundations

What is Chaos?

Mathematical Definition

Key properties of chaotic systems:

🌀 Core Chaotic Properties

1. Deterministic: Follows exact mathematical rules (no randomness)

2. Sensitive to initial conditions: "Butterfly effect" — small changes → large differences

3. Topologically mixing: Evolves to explore entire state space

4. Dense periodic orbits: Contains periodic solutions arbitrarily close to any point

5. Bounded: Stays within finite region of state space

6. Aperiodic: Never exactly repeats (infinite period)

Chaos vs Randomness

Critical distinction:

RANDOM PROCESS:
- Truly unpredictable
- No underlying pattern
- Independent events
- Example: White noise
- Audio: static, hiss

CHAOTIC PROCESS:
- Appears random but deterministic
- Complex underlying patterns
- Dependent evolution
- Example: Weather system
- Audio: evolving, structured textures

FOR SYNTHESIS:
Chaos offers:
- Reproducibility (same seed = same output)
- Rich structure (mathematical patterns)
- Control parameters (tweak chaos behavior)
- Evolution (time-dependent changes)

Chaotic Systems in Synthesis

Why Chaos for Sound?

Musical advantages of chaotic systems:

🎵 Chaotic Sound Characteristics

Natural evolution: Sounds "alive", not static

Complex patterning: Rich internal structure

Controlled unpredictability: Wild but bounded

Parameter sensitivity: Small tweaks → new textures

Reproducibility: Compositional control

Mathematical foundation: Deep structure to explore

Mapping Chaos to Audio Parameters

How chaotic variables become sound:

General mapping strategy: chaotic variable x ∈ [a, b] → audio parameter p ∈ [c, d] Linear mapping: p = c + (d - c)·(x - a)/(b - a) In this script: chaotic x → grain frequency f For Logistic Map (x ∈ [0,1]): f = base_frequency·(0.3 + 1.4·x)·layer_scale For Hénon Map (x ∈ [-1.5, 1.5]): f = base_frequency·(0.5 + x)·layer_scale For Lorenz (x ∈ [-20, 20]): f = base_frequency·(0.5 + 0.5·(x/20 + 0.5))·layer_scale Where layer_scale = 1 + (layer-1)·scale_factor Creates frequency spread across layers

Mathematical Implementation

Chaotic Evolution Algorithm

PSEUDOCODE: Chaotic Grain Generation

Initialize chaotic system with parameters
total_grains = round(duration × density)

For grain = 1 to total_grains:
grain_time[grain] = randomUniform(0, duration-0.2)
grain_duration[grain] = 0.08 + 0.15×random()

# Evolve chaotic system
If Logistic Map:
x = r × x × (1 - x)
freq = base × (0.3 + 1.4×x) × layer_scale

If Hénon Map:
new_x = 1 - a×x² + y
y = b × x
x = new_x
freq = base × (0.5 + x) × layer_scale

If Lorenz System:
dx = σ×(y - x)×dt
dy = (x×(28 - z) - y)×dt
dz = (x×y - 2.667×z)×dt
x = x + dx; y = y + dy; z = z + dz
freq = base × (0.5 + 0.5×(x/20 + 0.5)) × layer_scale

grain_frequency[grain] = freq
grain_amplitude[grain] = base_amp_scale
End For

Key insight: Chaotic evolution independent of grain time
Grains placed at random times, frequencies from chaotic sequence

Deterministic vs Stochastic Elements

What's deterministic vs random in this synthesis:

DETERMINISTIC (Chaos-driven):
- Grain frequency sequence
- Chaotic system evolution
- Layer frequency relationships
- Overall texture character

STOCHASTIC (Random):
- Grain timing (uniform random)
- Grain duration (random within range)
- Grain amplitude (fixed per layer)
- Parameter randomization (if enabled)

HYBRID APPROACH:
Chaos provides structured evolution
Randomness provides natural timing
Combination: structured yet organic textures

Chaotic Algorithms

System 1: Logistic Map

📈 Logistic Map (Discrete 1D Chaos)

Equation: xₙ₊₁ = r·xₙ·(1 - xₙ)

Parameters: r ∈ [0,4], x ∈ [0,1]

Chaotic regime: r ≈ 3.57-4.0

Script defaults: r = 3.7, x₀ = 0.5

Frequency mapping: f = base·(0.3 + 1.4·x)·layer_scale

Sonic character: Wild fluctuations, sudden jumps

Best for: Dramatic textures, unpredictable evolution

Logistic Map Behavior

Bifurcation diagram behavior: r < 1: converges to 0 1 < r < 3: converges to (r-1)/r 3 < r < 3.44949: period-2 oscillations 3.44949 < r < 3.54409: period-4 3.54409 < r < 3.56995: period doubling cascade r > 3.56995: chaos (with periodic windows) Script uses r ≈ 3.7: - Deep in chaotic regime - No periodicity - Sensitive to initial conditions - Bounded between approximately 0.3-0.9 Frequency range calculation: x range: ~0.3-0.9 f = base·(0.3 + 1.4·x) = base·(0.72 to 1.56) So frequencies vary by factor ~2.2

System 2: Hénon Map

🔄 Hénon Map (Discrete 2D Chaos)

Equations: xₙ₊₁ = 1 - a·xₙ² + yₙ, yₙ₊₁ = b·xₙ

Parameters: a = 1.4, b = 0.3 (canonical)

State: (x,y) ∈ ℝ², x ≈ [-1.5,1.5]

Script defaults: a = 1.4, b = 0.3, (x₀,y₀) = (0.1,0.1)

Frequency mapping: f = base·(0.5 + x)·layer_scale

Sonic character: Complex patterns, swirling evolution

Best for: Intricate textures, mathematical beauty

Hénon Map Characteristics

Hénon attractor properties: - Two-dimensional chaos - Fractal structure (strange attractor) - More complex than Logistic Map - Canonical parameters: a=1.4, b=0.3 - Creates famous "Hénon attractor" shape Script implementation: new_x = 1 - a*x*x + y y = b * x x = new_x State range: x ∈ approximately [-1.5, 1.5] y ∈ approximately [-0.4, 0.4] Frequency mapping: f = base·(0.5 + x)·layer_scale For x ∈ [-1.5, 1.5], f ∈ base·[-1.0, 2.0]·layer_scale Negative frequencies clamped? Actually produces: f ∈ base·[0, 2.0]·layer_scale (since 0.5+x ≥ -1.0) Frequency ratio: up to 4:1 between extremes

System 3: Lorenz System

🌪️ Lorenz System (Continuous 3D Chaos)

Equations: dx/dt = σ(y-x), dy/dt = x(ρ-z)-y, dz/dt = xy-βz

Parameters: σ=10, ρ=28, β=8/3 (canonical)

State: (x,y,z) ∈ ℝ³, butterfly attractor

Script defaults: σ=10, (x₀,y₀,z₀) = (0.1,0,0), dt=0.01

Frequency mapping: f = base·(0.5 + 0.5·(x/20 + 0.5))·layer_scale

Sonic character: Smooth evolution, atmospheric, flowing

Best for: Ambient textures, evolving drones, atmospheric beds

Lorenz System Details

Lorenz equations (simplified in script): dx = sigma*(y - x)*dt dy = (x*(28 - z) - y)*dt dz = (x*y - 2.667*z)*dt Where: sigma = σ (Prandtl number) = 10 in script ρ (Rayleigh number) = 28 (fixed) β = 8/3 ≈ 2.667 (fixed) dt = 0.01 (integration time step) Butterfly attractor: - Famous "Lorenz attractor" shape - Continuous-time chaos - Smooth evolution (unlike discrete maps) - Two "wings" of attractor State range: x ∈ approximately [-20, 20] y ∈ approximately [-30, 30] z ∈ approximately [0, 50] Frequency mapping: f = base·(0.5 + 0.5·(x/20 + 0.5))·layer_scale = base·(0.5 + 0.025·x + 0.25)·layer_scale = base·(0.75 + 0.025·x)·layer_scale For x ∈ [-20, 20], f ∈ base·[0.25, 1.25]·layer_scale Frequency ratio: 5:1 between extremes Smoother variation than discrete maps

Algorithm Comparison

SystemDimensionsTypeFrequency RangeEvolution CharacterSonic Result
Logistic Map1DDiscreteBase×[0.72,1.56]Sudden jumps, wild swingsDramatic, unpredictable
Hénon Map2DDiscreteBase×[0,2.0]Complex patterns, swirlingIntricate, mathematical
Lorenz System3DContinuousBase×[0.25,1.25]Smooth flows, atmosphericEvolving, ambient

Chunking Optimization

The Chunking Problem

Why Chunking is Necessary

⚡ Performance Challenge

Problem: Praat formula strings have length limits

Example: 10 seconds × 20 grains/sec × 3 layers = 600 grains

Per grain: ~300 characters in formula

Total: 600 × 300 = 180,000 characters

Praat limit: Approximately 1,000,000 characters practical

Risk: Formula too long → Praat error or crash

Solution: Split into manageable chunks

Chunking Strategy

CHUNKING ALGORITHM:

chunk_duration = 2.0 seconds
num_chunks = ceil(total_duration / chunk_duration)
max_grains_per_chunk = 30 (safety limit)

For each layer:
For chunk = 1 to num_chunks:
chunk_start = (chunk-1) × chunk_duration
chunk_end = min(chunk × chunk_duration, total_duration)
chunk_formula$ = "0"
grains_added = 0

For each grain in pre-generated list:
If grain_time in [chunk_start, chunk_end):
If grains_added < max_grains_per_chunk:
Add grain term to chunk_formula$
grains_added = grains_added + 1
Else:
Skip remaining grains (safety)

Create Sound from formula: chunk_formula$

Concatenate all chunk sounds → layer sound

Advantage: Each chunk has limited formula length
Trade-off: Some grains may be skipped in dense textures

Chunk Implementation Details

Grain Allocation to Chunks

Grain time assignment: grain_time = randomUniform(0, duration - 0.2) Chunk assignment: chunk_index = floor(grain_time / chunk_duration) + 1 Local time within chunk: local_time = grain_time - (chunk_index-1)×chunk_duration Grain formula term in chunk: " + if x >= local_time and x < local_end then amp×sin(2π×freq×x)×Hanning((x-local_time)/dur) else 0 fi" Important: sine phase uses absolute time (x), not local_time This ensures frequency continuity across chunk boundaries Hanning envelope uses local_time for proper fade in/out

Max Grains Per Chunk Limit

Grain skipping behavior:
Limit: max_grains_per_chunk = 30 grains
Reason: Prevent formula length overflow
Calculation: 30 grains × ~300 chars = ~9,000 chars (safe)
Effect: In dense textures, some grains skipped
Which grains: Later grains in chunk skipped (simple sequential)
Audible effect: Slightly less dense than expected
Workaround: Reduce grain_density or increase chunk_duration
Alternative: Manual adjustment for very dense textures

Concatenation Process

Layer Assembly

LAYER CONSTRUCTION PIPELINE:

Step 1: Generate all chunks
Create Sound L1C1, L1C2, ..., L1CN (for layer 1)
Each chunk: 2 seconds (except last)
Formula with ≤30 grains

Step 2: Concatenate chunks
selectObject: "Sound L1C1"
for i=2 to N: plusObject: "Sound L1Ci"
layer_sound = Concatenate
Renamed: "layer_1"

Step 3: Cleanup chunks
for i=1 to N: removeObject: "Sound L1Ci"

Step 4: Repeat for each layer
Creates layer_1, layer_2, ..., layer_N

Step 5: Mix layers
final = Copy of layer_1
for i=2 to N: Formula: "self + object(layer_i, x)"
Cleanup layers

Performance Benefits

AspectWithout ChunkingWith ChunkingImprovement
Formula LengthUnlimited (risky)≤ 9,000 charsAvoids crashes
Memory UsageLarge stringsSmaller stringsMore stable
Praat OverheadSingle huge formulaMany small formulasBetter error handling
Grain LimitTheoretical only30 per chunkControlled density
DebuggingDifficultPer chunk possibleEasier troubleshooting

Parameters & Effects

Core Synthesis Parameters

ParameterTypeDefaultRangeDescription
Duration (sec)positive101-60Total output length
Base frequency (Hz)positive12020-2000Center frequency for chaotic mapping
Grain density (grains/sec)positive81-50Average grains per second per layer
Number of layersinteger31-8Independent chaotic layers to combine
Randomize parametersboolean1 (yes)0/1Add variation to chaotic parameters
Fade time (sec)positive20-10Fade in/out duration at boundaries

Mode Selection Parameters

ParameterTypeOptionsDescription
Synthesis modeoptionmenuLogistic Map, Hénon Map, Lorenz SystemChaotic system controlling grain frequencies
Spatial modeoptionmenuMono, Stereo WideStereo processing and spatialization
Normalize outputboolean0/1Scale peak amplitude to 0.9
Play afterboolean0/1Auto-play result after processing

Preset Configurations

1 Custom

User-defined parameters

Use: Full manual control

2 Logistic Sparse

Duration: 10s, Density: 8

3 layers, Logistic Map

3 Hénon Texture

Duration: 12s, Density: 6

4 layers, Hénon Map, Stereo

4 Lorenz Atmospheric

Duration: 15s, Density: 5

3 layers, Lorenz System

Chaotic Parameter Ranges

Logistic Map parameters (when randomized):
  • r: 3.5 to 3.9 (chaotic regime)
  • Initial x: Fixed at 0.5
  • Layer density multiplier: 0.7 to 1.3× base density

r < 3.57: periodic or fixed point (not chaotic)

r > 3.9: potentially too extreme

Hénon Map parameters (when randomized):
  • a: 1.2 to 1.6
  • b: 0.2 to 0.4
  • Initial (x,y): Fixed at (0.1,0.1)
  • Layer density multiplier: 0.8 to 1.2× base density

Canonical values: a=1.4, b=0.3

Different parameters create different attractor shapes

Lorenz System parameters (when randomized):
  • σ (sigma): 8 to 12
  • ρ (rho): Fixed at 28 (critical value)
  • β (beta): Fixed at 8/3 ≈ 2.667
  • Initial (x,y,z): (0.1,0,0)
  • Layer density multiplier: 0.75 to 1.25× base density

ρ=28 is classical chaotic value

σ variation changes attractor dynamics

Performance Considerations

Grain density vs chunk limits:
Max grains per chunk: 30 grains
Chunk duration: 2.0 seconds
Max density per layer: 30/2 = 15 grains/sec
For multiple layers: Multiply by layer count
Example: 3 layers × 15 = 45 grains/sec total max
If exceeded: Grains skipped (later ones in chunk)
Solution: Reduce grain_density or increase chunk_duration in script
Warning sign: Info window shows "X grains" but texture seems sparse

Applications

Algorithmic Composition

Use case: Generate complex textures for contemporary music

Technique: Use different chaotic systems for different sections

Example: Logistic Map for intense sections, Lorenz for ambient bridges

Sound Design for Media

Use case: Create evolving textures for film, games, installations

Technique: Parameter exploration to match mood/scene

Workflow:

Scientific Sonification

Use case: Hear chaotic system behavior

Technique: Map chaotic variables directly to audio

Application: Education, research, data exploration

Generative Art

Use case: Create never-repeating sound installations

Technique: Long durations, parameter automation

Advantage: Deterministic yet always evolving

Psychoacoustic Research

Use case: Study perception of chaotic vs random textures

Technique: Controlled parameter variation

Benefit: Precise mathematical control over stimulus

Practical Workflow Examples

🎬 Film: Tense Undercurrent

Goal: Create unsettling, tense background for thriller scene

Settings:

  • Synthesis mode: Logistic Map
  • Base frequency: 90 Hz (uneasy low end)
  • Grain density: 12 grains/sec
  • Layers: 4
  • Randomize parameters: Yes (for variation between takes)
  • Spatial mode: Stereo Wide
  • Duration: Match scene length

Post-processing: Add subtle pitch modulation, light reverb

Result: Unpredictable, tense texture that never settles

🎵 Music: Evolving Ambient Pad

Goal: Create slowly evolving pad for ambient track

Settings:

  • Synthesis mode: Lorenz System
  • Base frequency: 220 Hz (A3)
  • Grain density: 6 grains/sec
  • Layers: 3
  • Randomize parameters: No (for consistency)
  • Spatial mode: Mono (for further processing)
  • Duration: 30 seconds

Integration: Process with reverb, delay, gentle filtering

Result: Smooth, evolving pad with mathematical beauty

🎮 Game: Magic Energy Field

Goal: Create complex magical energy texture

Settings:

  • Synthesis mode: Hénon Map
  • Base frequency: 350 Hz
  • Grain density: 8 grains/sec
  • Layers: 4
  • Randomize parameters: Yes (different for each spell type)
  • Spatial mode: Stereo Wide
  • Duration: 8 seconds (loop point)

Post-processing: Add spectral effects, volume envelope

Result: Intricate, complex magical energy sound

Advanced Techniques

Parameter automation through scripting:
  • Generate multiple sections: Different parameters for intro/body/outro
  • Crossfade manually: Blend between different chaotic states
  • Chaotic parameter modulation: Change r, a, σ over time via script
  • Hybrid systems: Switch between chaotic systems within one piece

Requires modifying script or running multiple times and combining

External control possibilities:
  • MIDI mapping: Map chaotic parameters to MIDI controllers
  • Real-time generation: Modify script for real-time parameter changes
  • Data-driven chaos: Use external data to seed chaotic parameters
  • Interactive installations: User input controls chaotic evolution

Advanced modifications enable interactive chaotic synthesis

Hybrid synthesis approaches:
  • Chaos + samples: Use chaotic frequency control on sampled grains
  • Multi-scale chaos: Different chaotic systems for different frequency ranges
  • Chaotic modulation: Use chaotic output to modulate other synthesis parameters
  • Feedback systems: Audio output feeds back into chaotic parameters

Chaotic synthesis as modulation source for other techniques

Troubleshooting Common Issues

Problem: Output too sparse or missing grains
Causes: Grain density too low, grains skipped due to chunk limit
Solutions: Increase grain_density, check chunk limit isn't exceeded
Problem: Chaotic behavior too extreme/unpleasant
Causes: Chaotic parameters in extreme regime, frequency range too wide
Solutions: Adjust chaotic parameters, reduce base_frequency range
Problem: Repetitive or periodic sounding
Causes: Chaotic system in periodic window, too few grains
Solutions: Change chaotic parameters, increase grain density
Problem: Processing very slow
Causes: High grain count, many layers, long duration
Solutions: Reduce parameters, be patient with chunking overhead
Problem: Clicks or artifacts at chunk boundaries
Causes: Grains crossing chunk boundaries, phase discontinuities
Solutions: Use shorter grains, ensure grains don't cross boundaries

Creative Parameter Explorations

ExplorationParameter SettingsExpected ResultCreative Use
Micro-chaosDuration: 1s, Density: 30, Layers: 1Intense chaotic burstPercussive chaotic hits
Harmonic chaosBase: 440Hz, Narrow frequency rangeChaotic variations around pitchDetuned chaotic tones
Dense chaotic cloudDensity: 20, Layers: 5, Short grainsThick chaotic textureChaotic noise beds
Sparse atmosphericDensity: 2, Layers: 3, Long grainsOccasional chaotic eventsAmbient punctuations
Parameter sweepGenerate multiple with changing r/a/σEvolving chaotic characterChaotic metamorphosis

Technical Implementation Details

Grain Formula Construction

Optimized Grain Formula

Simplified grain formula in chunks: " + if x >= start and x < end then amp * sin(2*pi*freq*x) * (1-cos(2*pi*(x-start)/dur))/2 else 0 fi" Key optimizations: 1. sin(2*pi*freq*x) uses absolute time x, not (x-start) - Maintains phase continuity across chunks - Simpler formula 2. Hanning envelope: (1-cos(2*pi*(x-start)/dur))/2 - Fades in/out within grain duration - Uses local time (x-start) for envelope 3. Condition: x >= start and x < end - Strict inequalities prevent overlap issues - end = start + dur (clamped to chunk boundary) Variables as strings: start$, end$, amp$, freq$, dur$ with fixed precision Prevents floating-point string conversion issues

Chaotic State Management

State Evolution Independent of Time

IMPORTANT DESIGN CHOICE:
Chaotic evolution independent of grain timing

Why:
Grains placed at random times (uniform)
Chaotic sequence evolves per grain count
NOT per time elapsed

Result:
Chaotic frequency sequence same regardless of:
- When grains occur in time
- Grain density
- Duration between grains

Alternative approach (not used):
Evolve chaos per time step
Map time to chaotic state
More complex, less flexible

Current approach advantage:
Simple, predictable chaotic sequence
Decouples timing from frequency evolution

Spatial Processing

Stereo Wide Implementation

Stereo processing steps: 1. Copy mono sound → "L" (left) 2. Copy mono sound → "R" (right) 3. Left channel: Formula: "self * 0.8" Filter (pass Hann band): 0, 4000, 100 - Passes 0-4000 Hz - Smooth transition: 100 Hz 4. Right channel: Formula: "self * 0.8" Filter (pass Hann band): 200, 8000, 100 - Passes 200-8000 Hz - Smooth transition: 100 Hz 5. Combine to stereo: left, right Effect: - Different frequency content per ear - Creates psychoacoustic width - Left: fuller low-mid range - Right: brighter, more high frequencies - 0.8 scaling prevents clipping when summed

Performance Optimization Details

Pre-generation vs On-the-fly

Why pre-generate all grain parameters?
  • Separation of concerns: Parameter calculation separate from synthesis
  • Performance: Compute chaos once, not during formula building
  • Flexibility: Can modify parameters before synthesis
  • Debugging: Can inspect parameter arrays
  • Memory efficiency: Arrays smaller than formula strings

Trade-off: Requires storing all parameters in memory (arrays)

Formula String Building Optimization

String concatenation optimization: chunk_formula$ = "0" for each grain: term$ = "+if x>=" + start$ + " and x<" + end$ + " then " + amp$ + "*sin(2*pi*" + freq$ + "*x)*" + "(1-cos(2*pi*(x-" + start$ + ")/" + dur$ + "))/2 else 0 fi" chunk_formula$ = chunk_formula$ + term$ String length estimate: Components: "+if x>=NNNNNN and x