Computing Emotions with Bach
When I listen to Bach, I am rarely swept away by mere melody. Instead, I observe how hidden rules expand and evolve without ever being violated.
Most people think of music as the language of emotion. However, Bach’s counterpoint is not a tool for the immediate venting of feeling. It is a sonorous system constructed with rigorous logic and architectural precision. Saying his music is mathematical is not a cliché. It means Bach’s method of manipulating sound can be modeled through explicit transformations and constraint satisfaction.
To a developer, a Bach score is not a sentimental letter, but an algorithmic specification. Today, I will rewrite that specification using Topaz, the language I am currently architecting.
Melody is a Sequence of Data
If we reduce music to data, it becomes a set of pitches and durations mapped onto a timeline. The beautiful lines we hear are essentially arrays of integers.
Bach does not merely list this data. He defines it as a clear data structure that becomes an object for computation. A Bachian "Subject" is a coupling of two sequences: represents pitch and represents duration.
// Sequence P = { p₁, p₂, ... pₙ } represents Pitches
// Sequence D = { d₁, d₂, ... dₙ } represents Durations
type Note = { pitch: int, duration: int }
// A Subject is a sequence of Notes ordered in time
let subject: List<Note> = [
{ pitch: 62, duration: 4 }, // D4
{ pitch: 69, duration: 4 }, // A4
{ pitch: 71, duration: 2 }, // B4
{ pitch: 69, duration: 2 }, // A4
// ...
]
While this structure is simple, the music expands infinitely once this data meets a Function.
Transformations through Operators
A Fugue is a system that takes a subject as input and applies operators to return a new melody. Bach primarily employs three transformations.
The first is Inversion, which reflects the melody across a horizontal axis. The second is Retrograde, reversing the temporal order. The third is Augmentation, stretching the time scale to play the melody in slow motion. Because these are mathematical operations, we can implement the exact logic occurring in Bach’s mind using Topaz’s list comprehensions.
// 1. Inversion reflects around axis 'a'
// Formula: f(p) = 2a - p
function invert(melody: List, axis: int) {
return [
{ ...note, pitch: (2 * axis) - note.pitch }
for note in melody
]
}
// 2. Retrograde reverses the time axis 't'
function retrograde(melody: List) {
return melody.reverse()
}
// 3. Augmentation stretches time by factor 'k'
function augment(melody: List, factor: int) {
return [
{ ...note, duration: note.duration * factor }
for note in melody
]
}
The core of this system is the "Entry." Once a subject is declared, other voices enter at different intervals to layer transformed versions of that subject. What the listener hears is no accident. It is the result of these transformation functions interacting at runtime to build a cathedral of sound.
Counterpoint as a Constraint Satisfaction Problem
How do we play these transformed melodies simultaneously? This brings us exactly to where the strict rules of counterpoint come into play.
Parallel fifths are forbidden, dissonance must be resolved, and large leaps must be compensated. To a developer, this is a Constraint Satisfaction Problem with a limited solution space. While Bach designed his voices to move independently, he ensured they satisfied these rigid constraints at every vertical intersection. This acts as a Type System for stability.
Just as a compiler throws an error for a type mismatch, counterpoint prevents music from collapsing into chaotic noise. Constraints make the music resilient.
Synchronous Parallel Design
Bach’s polyphony mirrors the concurrency patterns of modern computer science. Different voices play independent melodies like separate threads, yet this is not asynchronous processing.
Operating on a Shared Time-base and checking the harmonic constraints of other voices in real-time makes it a "synchronous parallel design." Each voice maintains autonomy while sharing the rules of the entire system. It is a sophisticated architecture maintaining multiple flows without a deadlock. When this synchronization fails, the code becomes a bug and the music becomes noise.
Structure Generates Emotion
If Bach’s music feels cold, it is because he did not inject emotion directly. While Romantic composers shouted that they were sad, Bach designed a structure that evokes sadness.
The emotion we feel is not the composer's, but the intellectual awe discovered while exploring a fortress of logic. It provides the catharsis of seeing complex phenomena explained through a few elegant principles. While the world is full of unhandled exceptions, everything is orderly within a Bachian fugue.
The input is transformed and the tension is resolved within the constraints of the type system. If the universe is written in code, Bach's scores are the most perfect libraries ever written to keep the system from falling apart.