You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A collection of Perl, Python, and R scripts for generating MIDI music, exploring music theory, and experimenting with algorithmic and mathematical composition techniques.
Overview
This repository is a sandbox of musical experiments spanning:
Algorithmic composition — using genetic algorithms, cellular automata, fractals, and chaos theory to generate music
Music theory exploration — scales, modes, chord progressions, intervals, cadences, and harmonic analysis
Hardware control — scripts that clock and drive drum machines, synths and Eurorack, plus a web UI for a Volca Drum
Almost every program is a standalone, single-file script. Many have a write-up on https://ology.github.io; look for the link in the script's header comments.
The author's own packages: music_voicegen, music_melodicdevice, music_bassline_generator, music_creatingrhythms, chord_progression_network, random_rhythms, music_drummer
Scripts by Category
Algorithmic Composition
Script
Description
ai-genetic
Uses a genetic algorithm (AI::Genetic) to evolve a pitch set scored by consonance, then optionally evolves rhythm and velocity. Applies atonal transformations (inversion, retrograde, rotation, transposition).
ai-genetic-pro
AI::Genetic::Pro version: evolves pitches whose adjacent intervals must be 2–5 half-steps, then feeds them to contrapuntal transformations.
algo-progression
Generates a whole band by genre: chord progressions (from Music::Dataset::ChordProgressions), drums, bass line, and optional arpeggios.
algo-progression-rt.pl
Real-time version of algo-progression, played on an external device.
cope
Scores chord combinations with David Cope's tension model (Music::Tension::Cope).
cope-genetic
Genetic search over chords using Cope tension, with a dissonance threshold at the tritone.
pso-cope.pl, pso-chord.pl, pso-music.pl
Particle-swarm experiments using Cope tension and a Tenney-height dissonance model (pso-chord.pl is unfinished).
bitstring-fitness
Evolves bit-string individuals (Algorithm::Evolutionary) with a musical fitness function.
evolver.pl
Breeds MIDI phrases from a "mother" and "father" using partitions and permutations.
fragments
Builds pieces from short fragments using Music::VoiceGen and partitioned durations.
micro-themed
Micro-motifs with inversion and transposition (the header warns it "produces unsavory things").
reichify
Steve Reich-style phasing built on cyclic permutations.
tape-loop
Imitates the tape-loop effect of Eno's Music for Airports.
Chaos, Fractals & Mathematics
Script
Description
lorenz-attractor.pl
Solves the Lorenz system using RK4 integration; maps x/y/z trajectory values to MIDI pitch ranges and writes quarter-note triads. Outputs a .csv of trajectory data alongside the MIDI file.
lorenz-attractor.py
Python equivalent of the above.
mandelbrot_music.py
Sonifies the Mandelbrot set — escape count drives pitch, and duration is its inverse.
barycenter, barycenter3, barycenter4
Genetic algorithms scored with Music::Interval::Barycentric chord geometry; 3 adds cadences and rhythm partitions.
hilbert-notes
Uses a Hilbert space-filling curve to traverse a note grid.
astrophysics
Space-themed piece built on Voss noise (Music::Voss).
five-parsecs, kiloparsec
Space-themed pieces: drums with fills and crashes, and Voss-noise melodies.
event-horizon, gravity-well, sidereal-time
More space-themed pieces using scale-note walking, cadences and chords.
collision
Wind-chime simulation with Collision::2D.
base-fibo2, base-primes
Fibonacci numbers and primes rewritten in other number bases and played.
primes, primes-layered, prime-durations
Primes as note indexes and durations.
oeis-midi
Plays any OEIS sequence modulo the number of notes in a scale.
voss-method, voss-method-midi, voss-alteration
Voss's 1/f method from Musimathics (numbers, MIDI, and phrase alteration).
quantum
Note choice via Quantum::Superpositions::Lazy.
play-pixels, play-color-pixels
Hear an image pixel by pixel (grayscale, or one chord per RGB colour).
prolog-music
Scale and note logic expressed in AI::Prolog.
Cellular Automata & Systems
Script
Description
game-of-life-cluster
Runs Conway's Game of Life on a grid of notes with incrementing octaves; each generation's live-cell cluster becomes a chord. Seeded with a glider (a blinker is commented out).
lindenmayer-midi
Applies L-system (Lindenmayer system) rewriting rules, supplied in YAML, to produce MIDI sequences.
midi-turtle.pl
Turtle-graphics-style movement (Data::Turtle) mapped to notes.
cryptomorphic
Voss-driven structure with rhythmic motifs and Music::VoiceGen melodies over drums.
random-walk, random-walk-transform
Random walks over weighted graphs (Graph::Weighted); the second adds atonal transformations.
note-transition, stat-walk
Count note transitions in a MIDI file (saved with Storable), then walk the frequencies to generate new music. -sync variants handle synchronized parts.
Weighted-graph chord and drum generators with synchronized parts.
perm-perm, variations, combi-duras.pl
Permutations, variations and duration combinations.
random-selection, random-selection-mutate
Random population samples compared by Levenshtein distance, then mutated.
Rhythm & Drums
Script
Description
euclidean-beats
Distributes kick and snare onsets using Euclidean rhythm algorithm with prime-number onset counts. Hi-hat plays straight eighths.
euclidean-drums.pl
Real-time Euclidean drum machine for an external MIDI device (args: verbose, port, BPM).
clocked-euclidean-drums.pl
Euclidean drum patterns synchronised to an external MIDI clock.
clocked-euclidean-drum-fills.pl
Adds fills to clocked Euclidean drum patterns.
OMB.pl
One-Man Band: generates randomised hi-hat, kick, and snare patterns plus drum fills using Music::Duration::Partition. Six fill styles descend the tom kit with optional cymbal substitutions.
Offline scripts write a .mid file to the current directory named after the script ($0.mid). Real-time scripts take a MIDI port-name fragment instead (list ports with python3 midi-ports.py). Run them directly: