Six pieces of music generated entirely from algorithms — no samples, no recordings, just math turned into sound.
Every sound on this page was produced by a Python script with zero external audio libraries. The program generates raw waveforms — sine, triangle, and sawtooth waves — applies ADSR envelopes, synthesizes drum sounds from noise and pitch sweeps, and assembles everything into WAV files. The compositional decisions — which notes to play, when, how loud, how long — come from six different mathematical systems, each producing music with a distinctive character.
The algorithms range from deterministic (L-systems, cellular automata) to probabilistic (Markov chains) to chaotic (Lorenz attractor). The question isn't whether algorithms can compose "good" music — it's what kind of musical structures emerge naturally from different mathematical processes.
Before we can turn mathematics into music, we need to turn numbers into sound. The engine generates audio from first principles: every waveform is computed sample by sample at 44,100 Hz.
Sine waves produce pure tones — a single frequency with no harmonics. Triangle waves have a warmer, slightly hollow character, with only odd harmonics rolling off as 1/n². Sawtooth waves are rich and buzzy, containing all harmonics. For pads, we layer detuned sawtooths with a low-pass filter to create warm, evolving textures.
The drums are fully synthesized, not sampled. A kick drum is a sine wave with a rapid exponential pitch sweep from ~150 Hz down to 40 Hz. A snare blends filtered noise with a 180 Hz sine body. A hihat is a burst of noise with a very fast decay (~30ms).
Every note passes through an ADSR envelope (Attack, Decay, Sustain, Release) that shapes its amplitude over time. Fast attacks for percussion, slow attacks for pads. Without envelopes, everything would click and pop at note boundaries.
An L-system is a string rewriting system invented by botanist Aristid Lindenmayer to model plant growth. Start with an axiom (F), apply production rules (F → F+G-F-G+F, G → GG) repeatedly, and the string grows exponentially. After 4 iterations, a short axiom becomes hundreds of symbols.
The melody interprets this string like turtle graphics: F plays a note and steps up the scale, G plays a note and steps down, + and - shift the current position by larger intervals. The result has self-similar structure — the same motifs appear at different scales, just as the branching pattern of a fern repeats at every level of zoom.
Elementary cellular automata are the simplest possible computational systems: a row of binary cells, each updating based on its three-cell neighborhood. Rule 30 — which Wolfram famously put on the cover of A New Kind of Science — produces pseudo-random patterns from a single seed cell. Rule 90 generates the Sierpinski triangle.
Rule 30 drives the rhythm: specific cells trigger kick, snare, and hihat. Rule 90 drives the melody: active cells in each generation select notes from a C minor scale. The result is rhythmically unpredictable (Rule 30's chaos) but melodically structured (Rule 90's fractal regularity).
A Markov chain models sequences where the next state depends only on the current state. Here, the states are chords — I, ii, iii, IV, V, vi plus secondary dominant V/V and borrowed ♭VII. The transition matrix encodes how likely each chord is to follow each other chord, based on patterns common in pop and jazz harmony.
The chain starts on I (C major) and walks probabilistically through the harmonic space. Over it, a melody line mixes chord tones (60% probability) with stepwise passing tones (40%), quantized to C major. The warm pad sound underneath is three detuned sawtooth waves with a low-pass filter.
Because the transitions are probabilistic, every run produces different music (though the seed is fixed here for reproducibility). The transition weights create certain tendencies — V resolves to I 45% of the time, V/V resolves to V 70% of the time — that give the progressions a sense of harmonic gravity without being formulaic.
The Lorenz system is the original chaotic attractor — three coupled differential equations that Edward Lorenz discovered in 1963 while modeling atmospheric convection. The trajectory never repeats but stays confined to a butterfly-shaped region of phase space.
We run the system numerically (Euler method, dt=0.005) and map the three coordinates to musical parameters:
The music inherits the attractor's character: it orbits around two tonal centers (the two "wings" of the butterfly), swooping between them unpredictably. It almost repeats — you hear similar phrases return — but never quite the same way. This is the musical signature of chaos: sensitive dependence on initial conditions made audible.
Conway's Game of Life runs on a 12×16 grid of cells. Each generation, cells live or die based on their neighbor count: exactly 3 neighbors to be born, 2 or 3 to survive. From random initial conditions, complex patterns emerge — gliders, oscillators, still lifes.
The grid becomes a polyphonic instrument. Each of the 12 rows maps to a note in the C minor pentatonic scale. Each of the 16 columns maps to a micro-timing offset within the time step. When a cell is alive, its note sounds. The amplitude scales inversely with the number of active cells, so dense generations produce a wash of sound while sparse generations let individual notes ring out.
The piece begins with chaotic polyphony as the random soup evolves, then thins as cells die off or settle into oscillating patterns. The musical density tracks the system's information content.
The golden ratio (φ = 1.618...) and the Fibonacci sequence have deep connections to rhythm and proportion. Here, they control both time and pitch.
Rhythm: The drum patterns use Euclidean rhythms generated by Bjorklund's algorithm — which distributes k onsets as evenly as possible across n steps. When k and n are consecutive Fibonacci numbers, the result has maximal rhythmic interest: 5 kicks in 13 steps, 8 hihats in 13 steps, 3 snares in 8 steps. These are the rhythms found in West African drumming, Cuban son, and Bulgarian folk music.
Melody: Each note's interval is determined by the fractional part of successive multiples of φ. Because φ is the "most irrational" number (its continued fraction is all 1s), these fractional parts spread out maximally uniformly over [0,1] — a property called low discrepancy. The melody explores the D dorian scale evenly, never clustering in one register for too long.
Each mathematical system imposes a different kind of structure on the music, and you can hear the difference:
The most interesting observation: the algorithms that produce the best-sounding music are not the most complex ones. The Markov chain works because it encodes human preferences. The Fibonacci rhythms work because they match patterns humans independently discovered. The Lorenz attractor works because its dynamics happen to map well to musical tension and release. Mathematics doesn't automatically make good music — but when the math resonates with human perception, the results are striking.
The entire system is a single Python file (~600 lines) with no dependencies beyond numpy (for nothing — I didn't even use it; it's pure stdlib). Audio is generated sample-by-sample using the wave and struct modules. The synthesis includes:
Total code generates all six pieces in about 30 seconds on a modest server. Output is 16-bit 44.1kHz mono WAV, converted to MP3 for the web.