Cellular Automata Synthesis — User Guide

Algorithmic audio generation: maps cellular automata (1D elementary rules, Game of Life, Brian's Brain) to sound—each active cell triggers a sine oscillator, creating evolving rhythmic/textural patterns from computational emergence.

Algorithm: Cellular Automata (CA) Implementation: Praat Script Category: Algorithmic Synthesis Version: 1.0 (2025) License: MIT License
Contents:

What this does

This script implements cellular automata synthesis — a technique that translates the discrete, grid‑based evolution of cellular automata into audio. Three CA families are supported: (1) Elementary CA (1D): Wolfram's 256 rules (e.g., Rule 30, 90, 110), where each cell's state depends on its left/center/right neighbors. (2) Game of Life (2D): Conway's classic rule (B3/S23) for birth/survival. (3) Brian's Brain (2D): A three‑state cyclic CA that produces moving gliders and chaotic patterns. Each CA generation becomes a time segment; every active ("live") cell in that generation triggers a sine‑wave oscillator whose frequency is determined by the cell's position. The result is a dense, evolving texture of pitched impulses that reflects the CA's emergent complexity.

Key Features:

What are cellular automata? Cellular automata are discrete computational models consisting of a grid of cells, each in one of a finite number of states. Time advances in discrete steps, and each cell's next state is determined by its current state and the states of its neighbors via a fixed rule. Despite their simplicity, CAs can produce astonishingly complex, emergent behavior—from chaos to self‑organization to universal computation. In audio, CA grids map naturally to time‑frequency representations: each generation becomes a time slice, each cell a possible frequency bin. Active cells "play" oscillators, turning visual patterns into sonic ones.

Technical Implementation: (1) CA Initialization: Elementary CA starts with a single center cell alive; 2D CAs use random initial densities. (2) Evolution: Each generation computed and stored in arrays. (3) Audio mapping: For each generation (time segment), each active cell adds a term to a massive additive‑synthesis formula: if x ≥ t_start and x < t_end then amp × sin(2π × freq × (x + global_offset)) .... (4) Chunked processing: To avoid Praat's formula‑length limits, the audio is built in chunks of 20 segments. (5) Final assembly: Chunks concatenated, peak‑normalized, and played. The method is "brute force" additive synthesis but optimized via formula chunking, making even large grids (40×40) and long durations tractable.

Quick start

  1. In Praat, ensure no objects are selected.
  2. Run script…cellular_automata_synthesis.praat.
  3. Choose a Preset (Rule 30 Classic, Rule 110 Complex, etc.) or select Custom.
  4. If Custom, adjust parameters: Grid_size, Rule_type, Rule_number (for Elementary CA), Segment_duration, Base_frequency, Frequency_spread.
  5. Set Play_after to yes/no (auto‑play when done).
  6. Click OK — script computes CA, generates audio, and outputs "ca_presetName".
  7. Watch the Info window for progress; final sound appears in Objects list.
Quick tip: Start with Rule 30 Classic to hear chaotic, asymmetric patterns—the "default" complex CA. Try Rule 90 Symmetric for fractal, mirrored textures. Rule 110 Complex yields more structured, almost melodic patterns (it's Turing‑complete!). For 2D textures, Game of Life Dense creates clusters of activity that evolve slowly; Brian's Brain Chaotic gives faster, glider‑like movements. Enable Play_after to hear immediately. Watch the Info window—it shows chunk‑by‑chunk progress. Larger grid sizes (e.g., 40) produce more overlapping frequencies (denser sound). Longer segment durations (e.g., 0.2 s) make each generation more distinct.
Important: COMPUTATIONALLY INTENSIVE — large grids (e.g., 50×50) × many generations (e.g., 100) = 250,000 cell checks. The script uses chunking to stay within Praat's formula limits, but very large settings may still cause slowdowns. Elementary CA Rule_number is 0–255; many rules produce boring (all‑0 or all‑1) patterns—stick to known interesting rules (30, 90, 110, 184, etc.). 2D CAs (Game of Life, Brian's Brain) store the entire history in a 3D array; long durations with large grids consume memory. Frequency_spread > 500 Hz can produce very wide pitch ranges that may sound chaotic; lower values (100–200) keep patterns more coherent. Segment_duration < 0.05 s may cause artifacts (too short for oscillator fade‑in).

Cellular Automata Theory

Elementary Cellular Automata (1D)

🔢 Wolfram's 256 Rules

Rule definition: Each cell's next state depends on its current neighborhood of three cells (left, center, right).

Neighborhood patterns (3 bits → 8 possibilities): 111 → pattern 7 110 → pattern 6 101 → pattern 5 100 → pattern 4 011 → pattern 3 010 → pattern 2 001 → pattern 1 000 → pattern 0 Rule number = 8‑bit binary encoding: Rule 30: 00011110₂ = 0*128 + 0*64 + 0*32 + 1*16 + 1*8 + 1*4 + 1*2 + 0*1 Rule 90: 01011010₂ Rule 110: 01101110₂ Implementation (see EvolveElementaryCA procedure): pattern = 4*left + 2*center + right (0–7) rule_bit = (rule_number mod (2^(pattern+1))) div (2^pattern)

2D Cellular Automata

# Game of Life (Conway, 1970) States: 0 = dead, 1 = alive Rule: B3/S23 (Birth if 3 neighbors, Survive if 2 or 3 neighbors) # Brian's Brain (3‑state cyclic) States: 0 = dead, 1 = alive, 2 = dying Rule: • Dead cell → alive if exactly 2 alive neighbors • Alive cell → dying (state 2) in next step • Dying cell → dead (state 0) in next step Neighborhood: Moore neighborhood (8 surrounding cells)

Wolfram's Classes

Class I (Homogeneous): • Evolution leads to uniform state • Example: Rule 0 (all cells die), Rule 255 (all cells live) • Sonic result: Static drone or silence Class II (Periodic): • Evolution yields periodic/repeating patterns • Example: Rule 4, Rule 108 • Sonic result: Looping rhythmic patterns Class III (Chaotic): • Evolution appears random, sensitive to initial conditions • Example: Rule 30, Rule 90 (though 90 is actually Class II) • Sonic result: Chaotic, unpredictable texture Class IV (Complex): • Localized structures that propagate and interact • Example: Rule 110 (Turing‑complete!), Game of Life • Sonic result: Structured yet evolving, "life‑like" patterns

Audio Mapping Strategy

# For each generation (time segment) and each active cell: if cell_active = 1 # Frequency mapping: if Elementary_CA (1D): freq = base_frequency + (cell_position / grid_size) * frequency_spread if 2D_CA: # Game of Life: average of row & column frequencies freq_x = base_frequency + (row / grid_size) * frequency_spread freq_y = base_frequency/2 + (col / grid_size) * frequency_spread/2 freq = (freq_x + freq_y) / 2 # Brian's Brain: diagonal mapping freq = base_frequency + ((row + col) / (2*grid_size)) * frequency_spread # Amplitude scaling: amp = constant / sqrt(grid_size) # 1D amp = constant / grid_size # 2D (more cells → quieter each) # Add oscillator term to formula: term = " + if x >= start and x < end then amp * sin(2π*freq*(x+offset)) * envelope fi" # Envelope for 1D CA: short raised‑cosine fade envelope = (1 - cos(2π*(x-start)/duration))/2 # 2D CA: no envelope (square window) # All terms concatenated into a massive additive‑synthesis formula

Complete Processing Pipeline

SETUP: Choose preset or custom parameters Set duration, grid_size, rule_type, rule_number, etc. INITIALIZATION: sample_rate = 44100 Hz total_segments = duration / segment_duration chunk_segments = 20 (optimization constant) Initialize CA based on rule_type: • Elementary: single live cell at center • Game of Life: random 30% density • Brian's Brain: random mix of 0,1,2 states EVOLUTION: FOR segment = 1 to total_segments: Store current generation (for 2D CAs: ca_history[segment]) Compute next generation via rule END FOR CHUNKED AUDIO GENERATION: num_chunks = ceil(total_segments / chunk_segments) FOR chunk = 1 to num_chunks: segment_start = (chunk-1)*chunk_segments + 1 segment_end = min(chunk*chunk_segments, total_segments) Build chunk_formula$ = "0" FOR segment = segment_start to segment_end: FOR each active cell in that generation: Calculate frequency based on cell position Calculate amplitude (normalized) Add oscillator term to chunk_formula$ END FOR END FOR Create Sound from formula: "chunk_X", using chunk_formula$ END FOR ASSEMBLY: Concatenate all chunk sounds Rename to "ca_presetName" Scale peak to 0.9 Clean up temporary chunk objects Play if play_after = 1 OUTPUT: Final sound in Objects list, Info window summary

Cellular Automata Types

Type 1: Elementary CA (1D)

📏 One‑Dimensional, Nearest‑Neighbor

Grid: 1 × grid_size (a single row of cells)

States: 0 (dead) or 1 (alive)

Neighborhood: Left, Center, Right (3 cells)

Rule specification: Wolfram rule number (0–255)

Initial condition: Single live cell at center

Sonic character: Each generation = time segment; each cell = frequency slot. Produces evolving melodic/rhythmic patterns that move across the frequency spectrum. Complexity varies dramatically with rule number.

Type 2: Game of Life (2D)

🎮 Conway's Classic (B3/S23)

Grid: grid_size × grid_size (square)

States: 0 (dead) or 1 (alive)

Neighborhood: Moore (8 surrounding cells)

Rule: Birth if 3 neighbors, Survive if 2 or 3 neighbors

Initial condition: Random ≈30% alive (density 0.3)

Sonic character: Clusters of activity create "clouds" of sound that evolve slowly. Stable patterns (still lifes), oscillators (blinkers), and spaceships produce repeating motifs. Sparse patterns yield isolated notes; dense patterns create dense textures.

Type 3: Brian's Brain (2D)

🧠 Three‑State Cyclic CA

Grid: grid_size × grid_size (square)

States: 0 (dead), 1 (alive), 2 (dying)

Neighborhood: Moore (8 surrounding cells)

Rule: Dead→alive if exactly 2 alive neighbors; Alive→dying; Dying→dead

Initial condition: Random mix: 30% alive, 20% dying, 50% dead

Sonic character: Moving gliders and sparks create rhythmic, pulsing patterns. The three‑state cycle produces natural "attack‑decay" envelopes. More chaotic and active than Game of Life, with faster evolution.

Comparison Table

FeatureElementary CAGame of LifeBrian's Brain
Dimensions1D (row)2D (grid)2D (grid)
States2 (0,1)2 (0,1)3 (0,1,2)
Neighbors3 (left, center, right)8 (Moore)8 (Moore)
Rule complexitySimple (3‑bit lookup)Moderate (birth/survival counts)Moderate (cyclic conditions)
Emergent behaviorChaos, fractals, computationStill lifes, oscillators, spaceshipsGliders, sparks, waves
Sonic densityMedium (grid_size cells/gen)Variable (clusters)High (many gliders)
Temporal evolutionFast (each gen = segment)Slow (patterns evolve gradually)Fast (cyclic movement)
Best forMelodic/rhythmic patternsTextural clouds, ambientRhythmic pulses, glitch

Preset Patterns

Preset 1: Rule 30 Classic

🌀 Wolfram's "Random" Rule

Parameters:

  • Duration: 8.0 s
  • Grid size: 32 cells
  • Rule type: Elementary_CA
  • Rule number: 30
  • Segment duration: 0.1 s
  • Base frequency: 150 Hz
  • Frequency spread: 200 Hz

CA behavior: Class III (chaotic). Produces asymmetric, seemingly random patterns that are actually deterministic. Used by Wolfram as a pseudorandom generator. The left side remains orderly, right side chaotic.

Sonic character: Chaotic texture with occasional ordered runs. Sounds like digital rain or granular synthesis. Good for unpredictable backgrounds.

Preset 2: Rule 110 Complex

⚙️ Turing‑Complete Complexity

Parameters:

  • Duration: 10.0 s
  • Grid size: 40 cells
  • Rule type: Elementary_CA
  • Rule number: 110
  • Segment duration: 0.08 s
  • Base frequency: 120 Hz
  • Frequency spread: 250 Hz

CA behavior: Class IV (complex). The simplest known Turing‑complete system. Produces localized structures (gliders) that interact in complex ways. More structured than Rule 30.

Sonic character: Evolving melodic patterns with repeating motifs. Sounds almost like algorithmic composition—structured yet unpredictable. Longer duration reveals more complexity.

Preset 3: Rule 90 Symmetric

🔄 Fractal Symmetry

Parameters:

  • Duration: 8.0 s
  • Grid size: 32 cells
  • Rule type: Elementary_CA
  • Rule number: 90
  • Segment duration: 0.1 s
  • Base frequency: 180 Hz
  • Frequency spread: 180 Hz

CA behavior: Class II (periodic) but produces Sierpinski triangle fractal patterns. Linear rule (XOR of neighbors). Perfectly symmetric around center.

Sonic character: Mirror‑image patterns across frequency spectrum. Creates harmonious, almost tonal clusters. Less chaotic than Rule 30, more geometric.

Preset 4: Game of Life Dense

🌌 Clustered Emergence

Parameters:

  • Duration: 12.0 s
  • Grid size: 24×24
  • Rule type: Game_of_Life
  • Rule number: (not used)
  • Segment duration: 0.15 s
  • Base frequency: 100 Hz
  • Frequency spread: 300 Hz

CA behavior: Conway's Game of Life with moderately dense initial population (30%). Evolves into stable clusters, oscillators, and occasional gliders.

Sonic character: Cloud‑like textures that slowly transform. Clusters create dense chordal masses; isolated gliders produce moving melodies. Long, evolving ambient soundscape.

Preset 5: Brian's Brain Chaotic

⚡ Cyclic Glider Storms

Parameters:

  • Duration: 10.0 s
  • Grid size: 28×28
  • Rule type: Brian_Brain
  • Rule number: (not used)
  • Segment duration: 0.12 s
  • Base frequency: 130 Hz
  • Frequency spread: 200 Hz

CA behavior: Three‑state cyclic CA with many gliders and sparks. Constantly moving patterns that never settle.

Sonic character: Rhythmic, pulsing textures with clear attacks (alive state) and decays (dying state). Sounds like digital insect swarms or complex rhythmic sequences.

Parameters & Mapping

Core Parameters

🎛️ User‑Adjustable Settings

ParameterTypeDefaultRangeDescription
Durationreal8.01.0‑60.0Total audio length (seconds)
Grid_sizeinteger328‑100Number of cells (1D: length, 2D: width & height)
Rule_typechoiceElementary_CA1‑3Type of CA (Elementary, Game_of_Life, Brian_Brain)
Rule_numberinteger300‑255Elementary CA rule (0‑255), ignored for 2D CAs
Segment_durationreal0.10.02‑1.0Duration of each CA generation (seconds)
Base_frequencyreal15020‑1000Lowest frequency (Hz) for cell mapping
Frequency_spreadreal2000‑1000Frequency range added to base (Hz)
Play_afterboolean10/1Auto‑play generated sound

Derived Values

ValueCalculationTypical RangeDescription
total_segmentsduration / segment_duration10‑500Number of CA generations
chunk_segments20 (fixed)20Segments per audio chunk
num_chunksceil(total_segments / chunk_segments)1‑25Audio chunks to generate
sample_rate44100 (fixed)44100Audio sampling rate

Frequency Mapping Details

Elementary CA (1D): Cell position: cell = 1 to grid_size Frequency: freq = base_frequency + (cell/grid_size) * frequency_spread Example: grid_size=32, base=150, spread=200 cell=1 → 150 + (1/32)*200 ≈ 156 Hz cell=16 → 150 + 0.5*200 = 250 Hz cell=32 → 150 + 1.0*200 = 350 Hz Game of Life (2D): Row i, Column j (both 1 to grid_size) freq_x = base_frequency + (i/grid_size) * frequency_spread freq_y = base_frequency/2 + (j/grid_size) * frequency_spread/2 freq = (freq_x + freq_y) / 2 This creates a 2D frequency plane where: Top‑left: lower frequencies Bottom‑right: higher frequencies Brian's Brain (2D): Diagonal mapping: freq = base_frequency + ((i+j)/(2*grid_size)) * frequency_spread Creates diagonal bands of frequency: Top‑left (i+j=2): lowest Center diagonal (i+j=grid_size): middle Bottom‑right (i+j=2*grid_size): highest

Amplitude Normalization

# To prevent clipping with many active cells: if Elementary_CA: amp = 0.6 / sqrt(grid_size) # Rationale: active cells scale with grid_size, but not linearly # Square root gives pleasant density without extreme peaks if Game_of_Life: amp = 0.4 / grid_size # Many more possible cells (grid_size²), so stronger normalization if Brian_Brain: amp = 0.5 / grid_size # Similar to Game of Life but slightly hotter # Additional per‑cell variation could be added: # amp *= (0.8 + 0.4*random) # for more natural variation

Envelope Shapes

Elementary CA: Uses raised‑cosine (Hanning) window to avoid clicks:

envelope = (1 - cos(2π*(x - segment_start)/segment_duration)) / 2

2D CAs (Game of Life, Brian's Brain): No envelope (square window) — each oscillator simply turns on/off at generation boundaries. This creates more percussive, rhythmic results.

Sonic Applications

Algorithmic Composition

🎼 Generative Music Engine

Technique: Use Rule 110 (Turing‑complete) as a "composition machine". Each generation becomes a measure; cell positions map to notes in a scale.

Mapping refinement: Quantize frequencies to equal‑tempered scale:

# Post‑processing idea: freq_quantized = 440 * 2^((round(12*log2(freq/440)))/12)

Result: Evolving melodies and harmonies that follow complex CA logic but stay within musical scales.

Rhythmic Pattern Generation

Use case: Create complex, polyrhythmic percussion

Technique: Use Elementary CA with short segment_duration (0.05 s) and map cell positions to different drum sounds (e.g., low cells = kick, middle = snare, high = hi‑hat).

Example: Rule 30 with grid_size=16, segment_duration=0.05 creates a 20 Hz "clock" with chaotic but deterministic rhythms.

Ambient Textures & Soundscapes

Use case: Evolving background pads for film/games

Technique: Game of Life with large grid_size (40×40), long segment_duration (0.2 s), low base_frequency (80 Hz), moderate frequency_spread (150 Hz).

Post‑processing: Add reverb, slow filter sweeps, stereo widening.

Result: Living, breathing textures that subtly change over minutes.

Experimental Sound Design

Glitch/IDM: Brian's Brain with small grid (16×16), very short segments (0.03 s), wide frequency spread (500 Hz). Creates stuttering, granular‑like textures.

Sci‑fi interfaces: Rule 90 (symmetric) with medium grid, mapped to synthetic bell‑like tones (additive harmonics).

Bio‑mimetic sounds: Game of Life patterns that resemble insect swarms, bird flocks, or cellular processes.

Educational Demonstrations

Hearing Wolfram's classes:

Visual‑audio correlation: Students can watch CA evolution online while listening to the sonic result, building intuition for emergent behavior.

Practical Workflow Examples

🎬 Sci‑fi Computer Interface

Goal: Complex, "thinking" machine sounds

Settings:

  • Rule_type: Elementary_CA
  • Rule_number: 110
  • Grid_size: 24
  • Segment_duration: 0.07 s
  • Base_frequency: 300 Hz (bright)
  • Frequency_spread: 400 Hz

Post‑process: Band‑pass filter (800‑2000 Hz), bit‑crush slightly, pan randomly.

🎵 Generative Ambient Album

Goal: 60‑minute evolving soundscape

Procedure:

  1. Generate 12× 5‑minute segments with varying parameters
  2. Rule types: Alternate Elementary (rules 30,90,110,184) and Game of Life
  3. Slowly drift base_frequency from 60 Hz to 120 Hz across album
  4. Cross‑fade segments with 30‑second overlaps
  5. Master with gentle compression and reverb

🔬 Cellular Biology Sonification

Goal: Sonify actual cell‑growth data

Adaptation: Replace random initialization with real binary data (e.g., microscope images thresholded). Use Game of Life rule to simulate growth, map cell density to amplitude, cell type to frequency.

Result: Audible representation of biological processes.

Optimization & Advanced Techniques

Chunked Formula Generation

Problem: Praat's formula interpreter has practical limits on formula length. A grid_size=40, total_segments=100, average 20 active cells/segment → 80,000 oscillator terms = formula too long.

Solution: Split into chunks of 20 segments:

chunk_segments = 20 # Constant num_chunks = ceil(total_segments / chunk_segments) for chunk from 1 to num_chunks: segment_start = (chunk-1)*chunk_segments + 1 segment_end = min(chunk*chunk_segments, total_segments) # Build formula for just these segments chunk_formula$ = "0" for segment from segment_start to segment_end: # Add terms for this segment... # Create chunk sound Create Sound from formula: "chunk_X", chunk_duration, chunk_formula$ # Concatenate all chunks

Memory Management for 2D CAs

Issue: Game of Life and Brian's Brain store entire history in ca_history[segment, i, j]. For grid_size=40, total_segments=100 → 40×40×100 = 160,000 integers.

Optimization options:

Performance Tips

For faster processing:
  • Reduce grid_size: Halving grid_size reduces cells 4× (2D) or 2× (1D)
  • Increase segment_duration: Fewer segments = fewer generations to compute
  • Use Elementary CA: Much faster than 2D CAs (no neighborhood loops)
  • Lower frequency_spread: Simpler sine calculations (marginal gain)
  • Disable Play_after: If just generating for later use

Extending the System

Additional CA rules:

Advanced audio mappings:

Troubleshooting

Problem: Script runs very slowly or crashes
Cause: Too many cells/generations (e.g., grid_size=50, duration=30, segment_duration=0.05 → 600 generations)
Solution: Reduce grid_size, increase segment_duration, use Elementary CA instead of 2D
Problem: Output is mostly silence
Cause: CA rule leads to quick extinction (e.g., Rule 0) or initialization too sparse
Solution: Try different rule (30,90,110), increase initial density for 2D CAs
Problem: Audio has clicks/pops
Cause: Square‑window oscillators (2D CAs) creating discontinuities
Solution: Add envelope to 2D terms, or use longer segment_duration
Problem: Formula too long error
Cause: chunk_segments=20 still produces too many terms
Solution: Reduce chunk_segments to 10 in script code