An experimental evolutionary music generator that uses symbolic recombination instead of traditional randomness.
Each generation produces 48 unique MIDI sequences based on perfect shuffle crossover, and you β the listener β guide the evolution.
Originally written in PHP (2017). Now fully rebuilt in Node.js with a lightweight web interface.
- β Simple browser-based interface for interactive selection
- π΅ Generates 48 MIDI sequences per generation
- 𧬠Select your 16 favorite tracks and click Evolve to produce the next generation
- π Uses perfect shuffle crossover to blend melodies
- π² Adds random "newbie" sequences to keep diversity alive
- πΌ Based on a symbolic scale (default: natural minor)
- ποΈ Tunable
shiftparameter subtly alters recombination rhythm - π§ Zero machine learning β pure symbolic evolution
This project explores how structured crossover operations β like perfect shuffles β can produce meaningful musical patterns. Instead of noise or chaos, it uses symbolic determinism:
parent1 + parent2 β interleaved β offset β new generation.
It's like gene-splicing musical DNA β but with math and groove.
git clone https://github.com/xcontcom/perfect-shuffle-music-composer.git
cd perfect-shuffle-music-composer
npm install
node miditest.jsThis project depends on:
midi-writer-js
express
Install via:
npm install midi-writer-js expressThen open your browser and go to:
http://localhost:3000
- Visit the web interface.
- Click to preview any of the 48 generated MIDI sequences.
- Select exactly 16 that you like by checking the boxes.
- Hit Evolve β a new generation will be created using perfect shuffle crossover.
- Or click Recreate to generate a fresh random population.
Each new generation is built from:
- 16 survivors (top 16 selected by the user)
- 16 fresh individuals (randomly generated using a fixed scale)
- These parameters can be customized
Pairs of survivors are combined via perfect shuffle crossover:
for (let j = 0; j < notescount; j++) {
tarray[j * 2] = parent1[j];
tarray[j * 2 + 1] = parent2[j];
}Then two children are formed by slicing this interleaved array with an optional offset (shift), like so:
child1[j] = tarray[j];
child2[j] = tarray[(j + shift) % tarray.length];Changing shift tweaks the musical phrasing across generations.
perfect.shuffle.music.mp4
legacy/ # PHP
miditest.js # Main Node.js app
public/
βββ midi/ # Output MIDI files
population.json # Saved population data (auto-generated)
test.js # Different mixing method
Made by Serhii Herasymov, based on chaotic late-night discoveries in 2017 and reborn with clarity in 2025.
MIT License. See LICENSE for details.
