Shuffle Is Not Composition
A lot of "AI music" demos press shuffle and call the output creative, which is the same as calling a cat walking across a keyboard a sonata. I wanted a tiny generator that produces a real MIDI file and then grades itself on the things your ear notices first: key, repetition, downbeats, and leaps.
motifdiff uses a masked symbolic denoising loop. It starts from fixed anchors, fills pitch tokens from a small motif corpus, and nudges the result toward a chord progression instead of hoping randomness accidentally becomes a song.
A Listen Test With Receipts
The output is `artifacts/motifdiff.mid`, so you can actually listen to the evidence. The benchmark also compares it to a random pitch baseline on scale adherence, motif reuse, tonal anchor, and mean melodic leap, so you don't have to take my ears' word for it.
No model weights, no sample packs, no service running in the background pretending to be creative. Just a readable generator and a metric suite that makes it harder to fool yourself.
The Number
The guided sequence stays in key 100% of the time against the random baseline's coin-flip 46%. Tonal anchor lands at 0.50 versus 0.08. Mean leap drops from 9.87 semitones to 3.90, the difference between a melody and someone falling down a flight of stairs onto a piano.
The MIDI artifact regenerates in CI every single run.
Half the "Generated" Melody Was Never Generated
I went and checked exactly how the guided sequence gets built, step by step. It writes a hand-composed eight-note motif directly into four fixed spots in the sequence, transposed up a fourth every other repetition. Of the 64 total steps in the published benchmark, 32 of them, exactly half, are copied verbatim from that motif. Never touched by the masked denoising step. Never sampled, never scored, never generated by anything at all.
There is a second problem sitting right next to it. The scale adherence metric checks whether a note belongs to the key. The candidate pool the generator ever gets to pick from is already restricted to exactly the notes that belong to the key. So scale adherence hitting 1.00 is not a result, it is a guarantee, true for literally any sequence the generator could ever produce, good or bad. The random baseline it gets compared against pulls from a wide, unrestricted 30-pitch chromatic range instead, which means most of that 1.00 versus 0.46 headline gap is a difference in candidate pools, not a difference in intelligence.
So I built the honest version. Strip the hardcoded motif out entirely and credit the algorithm only for the steps it actually produced. Build a fair baseline that draws uniformly from the exact same restricted candidate pool the real generator uses, no motif, no chord weighting, nothing. Then compare those two head to head, averaged over 50 seeds instead of one lucky anecdote.
Scale adherence ties at 1.000 either way, which confirms it was never measuring anything. Tonal anchor and mean melodic leap do show a real, positive, reproducible edge for the actual transition-and-chord-aware weighting, roughly a tenth of a point better on landing chord tones and nearly a full semitone tighter on leaps. That is genuine signal. It is also a fraction of the size the published guided-versus-random gap implies, since half of that gap was hand-written content and the rest was measured against a baseline that could not have scored well no matter what generated it.
The original generator and benchmark are untouched, so the published table still reproduces exactly. The honest comparison ships as an explicit companion script. 13 tests pass locally and on GitHub Actions across Python 3.9, 3.11, and 3.13.