Skip to content

The Bach Generator That Stopped Repairing

I write a program that generates Bach's instrumental music. Organ fugues, the unaccompanied cello suites, the Chaconne. It emits MIDI, not notation. The first architecture was, in hindsight, too naive. Generate the notes first, then fix the rule violations afterward. I thought that would work.

It did work. Parallel fifths disappeared. Voice crossings were resolved. Leaps got reined in. The tests went green.

But when I played it back, it wasn't music.

There was a strange sensation: the more I fixed, the less it sounded like music. However many repairs I stacked on, what poured out was a storm of dissonance — unlistenable, like a child mashing an organ at random. Watching it come out batch after batch, I understood there was no finish line down this road. Eventually I threw the whole engine out. I threw out the very idea of repair. This is a record of that pivot.

Counterpoint in three minutes

Let me set up the minimum vocabulary first. Most engineers reading this have probably never had much to do with counterpoint. You can skip this section, but reading it makes the second half go down in one gulp.

Counterpoint is the craft of sounding several independent melodies at once and still making them agree. It isn't a tune with backing chords. Rather than a main melody plus harmony, every line stands on its own as a melody, and they don't fall apart when layered together. Each line is called a voice. A fugue stacks three, four of them.

There are two axes. Horizontal — each line, on its own, has to be a singable melody. Vertical — the notes sounding together at any instant have to ring without mud. Composing is the work of satisfying the vertical and the horizontal at the same time, continuously.

Think of several people talking at once. Each is saying something coherent (horizontal), and they aren't all chanting the same words in unison (vertical independence). The moment everyone collapses onto one voice, it stops being a conversation and becomes a chant.

Consonance and dissonance

The distance between two notes is an interval. Depending on the distance, the sonority is stable or tense. Every score from here on is playable; press play and check it with your ears.

First, the perfect consonances — the perfect fifth and octave.

Perfect consonancePerfect consonances: fifth, octave, twelfth
Hollow and stable. These intervals make solid anchors for a beginning or an ending — but two voices that keep landing on them in parallel stop sounding like two voices.
Every upper note sits a perfect fifth, octave, or twelfth above the held C.

Why "perfect"?

"Perfect" isn't a quality judgment. C up to G is a perfect fifth; C up to the C above it is a perfect octave — both blend so strongly that the two notes nearly fuse into one. A third or sixth comes in two sizes, major and minor, so its color shifts; the fifth and octave have no such wobble — there's essentially one of each. Hence "perfect." And that strong blend is exactly why their parallels get forbidden later.

Next, the imperfect consonances — thirds, sixths, and tenths.

Imperfect consonanceThirds, sixths, and tenths
The workhorses of two-voice writing: rich enough to sound full, restless enough to keep moving. And unlike the perfect intervals, voices may run in parallel thirds or sixths all day.
Thirds and sixths against the held C — full, but still leaning forward.

Seconds, sevenths, and the tritone are dissonances; they create tension.

DissonanceSeconds, sevenths, and the tritone
Dissonance isn't the enemy. Counterpoint runs on the tension it creates. What breaks is unmanaged dissonance — a clash that shows up without preparation, or walks off without resolving. Hold that thought; it is the hinge of this whole article.
vertical_dissonanceEach red interval — a second, a seventh, the tritone — is a dissonance that wants out.

Motion

When two voices move, the relationship is one of three. Parallel (same direction), contrary (opposite directions), or oblique (one holds while the other moves). A voice's independence comes from not always moving in parallel.

Safe motionContrary and oblique motion
Contrary motion (opposite directions) and oblique motion (one voice stationary) are the safe ways to reach any interval, perfect ones included. You hear two voices because they are doing two different things. Most parallel troubles vanish the moment one voice turns the other way.
First the voices open in opposite directions; then one holds while the other moves.

Beats

One more thing. Beats have a hierarchy: the head of each bar is strong, everything else is weak. The dissonance from a moment ago may pass through on a weak beat, but land it on a strong beat and it reads as a structural error. Where you can put tension depends on where you are in the bar.

FoundationStrong and weak beats
Count along as it plays: 1-2-3-4, 1-2-3. The first beat of each bar, the downbeat, is a checkpoint; the ear expects the harmony to be stable there. The engine uses the same binary: the tick at the head of a bar is strong, everything else is weak. Tension may pass through on a weak beat; land it on the downbeat and it reads as a structural error.
Beat 1 of each bar is the strong beat — the place the harmony has to be stable.

That gives us voices, consonance and dissonance, motion, and the strong and weak beats. That's enough tooling. Now the real question: why can't repair make music?

Learn, generate, fix

The engine I discarded — the one I called the "legacy generation system" in the commit log — was, for who I was back then, decent work. It had three stages.

First, learning. I built a corpus of 448 real Bach works as JSON, then extracted Markov transition tables and 5-gram vocabulary tables from it. Statistics of the form "this figure tends to be followed by that one."

Then, generation. Lay down notes while consulting the vocabulary tables. Voice motion went through a constraint solver — a three-layer model called ConstraintState: obligations to satisfy, invariants never to break, and a per-note gravity, with a FeasibilityEstimator to judge "is this still solvable from here." A fairly elaborate machine.

Then, scoring. Hand the result to a scorer in a sibling project, bach-mcp, which graded it by closeness to the real corpus. Too low, regenerate. Not an automatic loop, though — I drove it by hand, eyeballing the score.

In short: learn Bach from data, imitate to generate, then fix what looks wrong. Not so different from the naive instinct behind today's generative AI. The trouble was packed entirely into "fix."

The repairs pile up

Generated notes always carry rule violations. Each time, I added another repair pass. Skim the terms — what I want you to see is the pile itself, left behind in the commit log.

  • Erase parallel fifths and octaves (parallel repair)
  • Fix leaps — big jumps in a line (leap resolution module)
  • Fix repeated notes (repeated-note repair)
  • Fix clashes between neighboring voices (tritone repair, cross-relation fix)
  • Stop the outer voices from landing on a bare perfect interval (hidden-perfect outer-voice rule)
  • Untangle voice collisions across the whole timeline (harmonic-timeline-aware collision resolution)
  • Rebuild the voice-leading in the coda — the closing bars (coda voice-leading search)

Each one is correct on its own. Parallel fifths are forbidden in counterpoint; they should be fixed. But the more repairs I added, the more new problems surfaced. Nudge a note to kill a parallel fifth, and the nudge creates a leap. Fix the leap and you get a repeated note. Fix the repeated note and now it's a parallel octave against another voice. Whack-a-mole.

And the fatal part: repair can erase a rule violation, but it cannot make music.

Repair breaks the music

Why can't local repair produce music? It's faster to look at concrete cases, checking each one by ear.

Parallel fifths are forbidden not for moral reasons. To borrow the conversation again: the instant two people move in lockstep a perfect fifth apart, the two voices melt into one.

ForbiddenParallel fifths
Two voices moving the same way at the same perfect interval fuse into one. The red verticals are both perfect fifths; the arrows show neither voice is holding, so there is no oblique escape. This is the textbook forbidden parallel — and the single most-chased target of the old repair passes.
parallel_fifthBoth voices climb together and stay a perfect fifth apart — the red verticals are identical.

Through the lens of repair, this looks like a "shift one note and it's gone" problem. And indeed it goes away. But the note you shifted lives inside the logic of a melody. A line that connected smoothly to its neighbors now snaps to suit the repair. The violation is gone, but the line is dead.

Hidden fifths are nastier. Even if there's no fifth at this exact instant, when the outer voices arrive at a perfect fifth from the same direction, the ear hears the ghost of a parallel fifth.

Forbidden arrivalHidden fifth
There is no parallel fifth here — only one fifth. But the outer voices arrive at it moving the same way, and the ear still hears the ghost of the parallel. 'Now' is not enough; the approach has to be right too.
hidden_parallel_fifthSimilar motion walks out of an imperfect interval straight into a bare perfect fifth.

Here's where a key fact bites: only parallels of perfect intervals are forbidden. Parallel thirds and sixths — tenths included — are in fact a staple of Bach's writing, two voices riding nicely alongside each other.

From BachBach: WTC I Prelude in E♭ — a full bar of parallel tenths
Bar 32 of the E♭ major prelude (WTC I, BWV 852): two lines race a full bar in lockstep tenths, a compound third on every sixteenth. The quality slides between major and minor as the scale demands, but it never leaves the family of imperfect consonance — so the parallel rule has nothing to say. Try the same trick with fifths or octaves and it falls apart. Parallel motion is not the crime; parallel perfection is. (The notes sustained above each run — B♭ and G, then E♭ and C — are omitted.)
Two sixteenth-note lines run the whole bar in strict parallel tenths — and not one rule complains.

So a "remove the parallels" repair is too blunt. Perfect and imperfect intervals are treated in opposite ways, which means you have to decide what to keep and what to kill before you place the note.

A suspension can't be made after the fact

The limits of repair show clearest in the suspension.

A suspension holds a note that was consonant on the previous beat into the next beat, where it becomes a dissonance, and then resolves down by step. Preparation — suspension — resolution, in three beats. It must be prepared as a consonance before it turns dissonant.

Allowed patternThe 7-6 chain
Chain the 7–6 figure and it becomes an engine: the upper voice ties over each bass step, clashes as a seventh, resolves to a sixth — and that sixth is the preparation for the next seventh. The syncopated upper line against a steadily falling bass is one of the most recognizable sounds in Baroque sequences.
suspension_seventh_sixthsuspension_resolution_step_downAs the bass walks down, each resolution is already the preparation for the next suspension.

This is the catch. Repair only acts after it finds a dissonance that is currently sounding. But the preparation of a suspension has to be in place on the beat before the dissonance sounds. By the time repair spots the violation, it's already too late. Rewind time to rewrite the previous beat as a consonance, and now the previous beat's consistency falls apart.

Place a dissonance with no preparation and it's just mud, not a suspension.

Weak beatUnprepared dissonance
A weak-beat non-chord tone is fine only when the line steps into it and out of it, making the pattern legible. Reach it by leap or leave it by leap and it stops being a passing tone and starts being a mistake — and no amount of after-the-fact patching turns one into the other.
unprepared_dissonanceThe weak-beat dissonance is left by a leap, so the ear cannot read it as a passing tone.

Listen to a chain of Bach suspensions and you hear the dissonances generating a rhythm of tension and release. Post-generation fixes can never reach this. You have to build it with the time axis intact, at the design stage.

From BachBach: WTC I Prelude in B minor — suspensions passed between voices
The B minor Prelude (WTC I, BWV 869). The suspensions do not sit in one voice; they are handed back and forth, so the dissonance never stops arriving. Listen and you hear tension and release become a pulse of its own. There is no way to reach this by fixing notes after the fact — Bach built the whole time axis to do it, and every time I hear it I understand again why I deleted the repair passes.
suspension_preparationsuspension_resolution_step_downOver a walking bass, soprano and alto take turns holding a note into a dissonance and resolving it down by step.

The constraint of surviving inversion

There's one more case local repair can never reach. Invertible counterpoint.

Here, to invert means to take the lower voice, lift it a whole octave, and let the two voices trade places. Swap them and the intervals change. Say the lower note is C and the upper is G — a perfect fifth. Lift the C above the G and now it reads G up to C: a perfect fourth. The fifth turned into a fourth. A third turns into a sixth the same way. The two interval numbers always add up to nine.

You can watch it happen with the toggle below. Flip between "original" and "inverted": line A on top holds still while line B (blue) below rises an octave, and every third turns into a sixth.

Invertible counterpointLift one line an octave — and it still works
raise line B an octave —
Two short lines written to be invertible. Line A on top stays frozen across both views — the same notes, in the same place. Only line B (blue) below changes: switch to “inverted” and it lifts a whole octave, so the two voices invert and the intervals flip to their complements — 3rds become 6ths — yet both versions stay consonant. Play each: the swap costs nothing.
invertible_at_octaveToggle the two: line A on top never moves; only line B (blue) rises an octave, and every third becomes a sixth.

And here's the trap. Between two voices on their own, the perfect fourth counts as a dissonance — even though the perfect fifth is a consonance. So a fifth that was perfectly stable flips into a dissonant fourth the instant you swap the voices.

The perfect-fourth puzzle

G up to the C above it is a perfect fourth. It sounds settled to the ear, yet between two voices alone it's treated as a dissonance — an old rule of counterpoint. The reason: the lower G reads as the foundation, leaving the upper C feeling unsupported. Add a third voice underneath and the fourth becomes consonant again. So it only causes trouble in exactly this case — swapping two voices top for bottom.

Invertible counterpointInversion at the octave: 5 becomes 4
The lower voice leaps an octave and the two trade places. The two pitches sounding are the same, yet the fifth has become a fourth — consonance turned to dissonance, with no note rewritten.
invertible_at_octaveThe same two notes are a fifth; lift the lower one an octave and they are a fourth.

To satisfy this, you have to design the two lines from the start so each works whether it's on top or on the bottom. It isn't the kind of property you can approach by repairing after generation. In Bach's fugues, subject and countersubject satisfy this constraint as a matter of course, which is exactly why the development can swap them top-for-bottom without falling apart.

From BachBach: BWV 847 — the same pair, top and bottom
follow the blue countersubject —
Two real statements of the same subject and countersubject from the C minor fugue (WTC I, BWV 847). Toggle between them and follow the blue line: at bar 7 the countersubject sits on top; at bar 20 it has dropped below the subject, and the two voices have traded octaves note for note. It survives the move because the lines were built to — octave-complementary intervals throughout, no strong-beat fourths waiting to turn dissonant, no octave-parallels lying in wait to become fifths. Bach wrote it invertible from the start, the only way it is ever possible. (A third voice is dropped at each spot for clarity.)
invertible_at_octavefourth_only_on_weak_beatAt bar 7 the countersubject (blue) sits above the subject; at bar 20 Bach turns the pair over and the same countersubject runs below — every interval still holds.

Voice crossing has the same smell. The old engine treated crossings as something to "detect and fix." But Bach crosses voices deliberately, to sharpen the independence of the lines rather than blur it. Repair fixes uniformly the very thing that must not be fixed uniformly.

From BachBach: Goldberg Variation 3 — a canon at the unison must cross
Goldberg Variation 3 is a canon at the unison — the follower repeats the leader's line a bar later at the very same pitch. Same pitch, same register: when the follower enters on the B the leader sang a bar ago, the leader has already stepped down a third, and the voices are crossed from the first note. On paper, stems and slurs keep the two lines readable; a generated voice has no paper, so the engine simply refuses to cross at all. Bach takes the tangle as the fair price of strict imitation. (The ground bass is omitted.)
voice_crossingTwo canon voices share one register; the moment the follower enters, the leader has already slipped beneath it.

Place it right the first time

The conclusion was simple. Stop generating-then-fixing. Choose the right note at the moment you place it.

The new engine — I named it the "composer subsystem" in the commits — builds MIDI directly from a harmonic plan and per-voice intents. At its center is candidate_search. When placing a note at a position, it evaluates the candidate pitches one by one. Does it create a parallel perfect interval? Cause a voice crossing? Is the leap appropriate? Is the dissonance prepared and resolved? Is it valid as a passing tone? Does it carry the fugal answer? Each rule scores the candidate, and the highest-scoring one is chosen.

It isn't a matter of fixing violations after they appear. A candidate that would be a violation simply never gets chosen. The repair passes became unnecessary. The only thing that runs after generation is the validator — final checks of structure, the horizontal flow, and the vertical sonority. It's not a device that fixes; it's a device that confirms the placement was right.

With the new engine standing, I cut off the retreat.

  • First I moved the 448-work Bach reference corpus, scorer and all, into bach-mcp. The generation engine doesn't depend on this data — the real Bach is consulted only at the final verification.
  • I switched all ten forms across the C API, the CLI, and the WASM build over to the new composer.
  • And I deleted the legacy engine wholesale. The counterpoint, fugue, forms, ornament, instrument, transform, and solo-string subsystems, along with the Generator that tied them together.

Verification after the deletion: 920 ctest cases, the WASM build plus 217 JS tests, 146 Python tests — all green. For how much code I threw away, nothing broke. The pile of repairs was never the essence.

Confirm the rules by ear

I wanted the rules candidate_search looks at to be something you could hear, not just read. So I built a counterpoint course alongside the site. Every playable score in this article is lifted straight from that course.

The course teaches the grammar through Bach's own examples. Take the fugal answer. Transpose the subject directly to the dominant and you get a "real answer"; adjust part of it to preserve the tonal logic and you get a "tonal answer." Which one to choose is not a local matter but a question of the whole piece's tonal design.

What's the dominant?

The dominant is the key a fifth above the home key. If C major is home, the dominant is G major. In a fugue the subject first appears in the home key, and the answer replies in the dominant — that call-and-response between home and dominant is the backbone of the whole form.

Fugal deviceSubject and tonal answervoices play in turn
Transpose the whole subject up a fifth and you get a real answer. Bend just the opening so tonic maps to dominant and dominant back to tonic, and you get a tonal answer — which keeps the exposition anchored in the home key. Which one is right is not a local choice; it falls out of how the whole piece is keyed.
tonal_answer_dominant_mappingThe subject opens on the tonic, the answer on the dominant — the head is mapped I→V, not transposed note for note.
From BachBach: WTC I Fugue in C minor — the tonal answervoices play in turn
The most-quoted tonal answer there is — the C minor fugue (WTC I, BWV 847). The subject starts C–B♮–C and drops to G: tonic to dominant. Answered literally a fifth up, that note would be D and the exposition would lurch out of key. Bach answers G–F♯–G, bending the one note home to C — tonic for dominant, dominant for tonic, the tail transposed exactly. One note, decided by the key of the whole movement. That is the kind of judgment a repair pass cannot make.
tonal_answer_dominant_mappingThe subject's fourth note drops to the dominant; the answer bends that one note back to the tonic and transposes the rest exactly.

Once the subject enters, it needs a countersubject riding alongside it. And when the subject entries overlap, you get a stretto.

From BachBach: WTC I Fugue in C major — stretto at one beat
Bars 7–8 of the C major fugue (WTC I, BWV 846), the one famous for being built almost entirely of stretto. The soprano starts the subject; a single beat later the alto starts the same subject a fourth below, and both run to the end. A real overlap, an exact transposition — entries piled on entries, and nothing collides. (The bass of these bars is omitted.)
stretto_overlap_validThe alto starts the subject a beat after the soprano and a fourth below — while the leader is only four notes in.

Then the cadence. Not only the perfect cadence, but the deceptive cadence that betrays expectation, and the Picardy third that closes a minor-key piece on a major chord. A cadence is harmonic grammar — and this too can't be written unless it's decided before the notes are placed.

From BachBach: Goldberg Aria — the final cadence
The last two bars of the Goldberg Aria (BWV 988). The melody's sixteenths spiral down onto F♯, the leading tone, while the bass threads the cadential harmony onto D. Then the contract is paid: F♯ rises a semitone to G, the bass falls D to G, an inner voice slips in just for the final chord. A perfect authentic cadence is a promise the outer voices make and keep. (Held under a fermata in performance; trimmed here at the double bar.)
cadence_voice_leadingThe melody lands on the leading tone F♯ and rises to G as the bass falls from dominant to tonic.
From BachBach: BWV 847 — the final bar turns major
The final bar of the C minor fugue (WTC I, BWV 847). The bass has held the tonic C since bar 29; above it the dominant gathers one last time, the top voice climbs F–G–A♭ and falls back, and the seventh F resolves down to E natural — the raised, major third, sitting on top as the piece ends. A minor fugue closing in major: the old Picardy convention, the leading tone resolved and the final chord turned to the light. (One inner voice omitted; the original doubles the pedal an octave lower.)
cadence_voice_leadingOver the tonic pedal, the dominant seventh F falls to E♮ — a C minor fugue ending on a major third.

The course's table of contents is also, exactly, the list of rules candidate_search looks at — intervals and consonance, motion and forbidden parallels, dissonance treatment, melodic writing, tonal grammar, fugal devices, and form-specific constraints. The article's constraints map one-to-one onto the course's chapters. If the reasoning piques your curiosity, the fastest path is to follow the counterpoint course from the start. Every score plays right in the browser.

What I learned

I started out thinking "Bach is logic." I was wrong.

More precisely: it is logic, but you cannot apply the logic after the fact. Remove a parallel fifth, fix a leap, resolve a dissonance — each is doable one at a time. But music is not a heap of such local correctnesses. A suspension must be prepared before it sounds; invertible counterpoint must hold up when top and bottom are swapped; an answer must sit inside the tonal design of the whole piece. None of them can be reached by "place it, then fix it."

Don't generate then fix. Place it right from the start. It took throwing away an entire engine to understand something this obvious. And every time I play a generated piece, I sit a while with the greatness of Bach — a man who wrote all of this without fixing a single note after the fact.