Fun with fractal chord progressions
2017-09-17 music math composition
I make a lot of music that is intended to be "ambient": something you can put on in the background and have it create a mood without demanding conscious attention in the foreground all the time. I'm also interested in automatic generation: I'd like to define some kind of pattern or structure and then have machines expand that into a complete composition, and have it be interesting all the way through, without too much human supervision. In this week's entry I'm going to go through a piece called Dharmapala which I wrote a couple years ago using a fractal chord progression. I've used this same technique in several other works, with varying success; I even built a mode for it into one of my homemade modules for realtime performance. But so far I've gotten the best results applying it in offline composition with a lot of careful planning and experiment.
Roman numeral analysis
You can skip this part if you already know it, but I'm not sure how many of my readers do. Let's think about the G major scale, which goes G, A, B, C, D, E, F#, and then wraps around to G again. If you start from any note in that scale, then skip one, take the next, skip one, and then take one more note, you end up with a three-note chord.
- from G, you get G, B, D: this is the G major chord (G).
- from A, you get A, C, E: A minor (Am).
- from B, you get B, D, F#: B minor (Bm).
- from C, you get C, E, G: C major (C)
- from D, you get D, F#, A: D major (D).
- from E, you get E, G, B: E minor (Em).
- from F#, you get F#, A, C: F# diminished (F#dim).
If you use some other major scale and follow this procedure, you get different chords, but you still get the same pattern: three different major chords, three minor ones, and one diminished. So if you want to study chord progressions in the abstract, maybe you don't want to think about exactly what key your song is in. A song in the key of G that uses the chords Em-C-G-D is kind of using the same chord progression as a song in Bb that uses the chords Gm-Eb-Bb-F, even though they are totally different chords, because in both cases the song is starting with the minor triad on the sixth degree of the scale, then major on the fourth, major on the first, and finally the major triad on the fifth. So people who study chord progressions often write them down using just the scale degrees, traditionally with roman numbers in lowercase for minor and uppercase for major. (There are further modifications possible for other kinds of chords, but this is far enough for this Web log entry.) Both Em-C-G-D and Gm-Eb-Bb-F can be called vi-IV-I-V progressions; they're just in different keys. A song with this progression will have a certain kind of feel to it regardless of the particular key it's transposed into.
In fact vi-IV-I-V in particular is a popular progression used in many kinds of music, and we probably all know many songs that use it. (Wikipedia has a list.) Some critics call it the "sensitive female" chord progressions because it's ubiquitous in the Lilith Fair style of singer-songwriter music, but they certainly don't have a monopoly on it. One nice aspect of this progression for ambient music is that it never really resolves. There is no V-I transition (much less a V7-I) nor anything like it that we're accustomed to hearing as musical punctuation. After going I-V the progression can just loop back around to vi without feeling like it has stopped. In fact, many people classify this progression instead as I-V-vi-IV, which is just the same as vi-IV-I-V with a different arbitrary choice of where to start.
The general outline here is that we're going to put together an ambient piece that just consists of playing a sequence of chords, a few hundred of them. In order to be ambient and fade into the background it should deliberately be somewhat repetitive, but if we want it to run six or ten minutes, it might be too boring to really just keep playing vi-IV-I-V over and over in the same key, especially with no lyrics. David Byrne wrote that singing is a trick to get people to listen to music for longer than they would ordinarily; if we're making instrumental music on a modular synthesizer, we need some other trick. So let's try playing vi-IV-I-V in several different keys:
- Key of E: C#m-A-E-B
- Key of C: Am-F-C-G
- Key of G: Em-C-G-D
- Key of D: Bm-G-D-A
The simple four-chord progression has turned into sixteen chords. The four keys I chose should look familiar: E-C-G-D is itself a vi-IV-I-V progression, or something very close. If you look closely you'll see I've ignored the distinction between E and Em, an issue I'll discuss in a moment, but just for now, let's try to express this transformation by something that looks mathematical or computerish.
x → minor(vi(x)) major(iv(x)) major(i(x)) major(v(x))
Note I am assuming the vi(), iv(), and similar functions extract degrees of the corresponding major scale; applying this to a minor chord is supposed to give the same result as applying it to a major chord. If you like, these are meant to look only at the roots of the input chords and not their qualities. Start with G, apply the rule, and you get Em-C-G-D. Then apply it recursively to each chord in that sequence and you get C#m-A-E-B-Am-F-C-G-Em-C-G-D-Bm-G-D-A. Each level of substitution multiplies the length of the sequence by four; with, say, four levels of substitution you get 256 chords, and they go all over the place, but with a single unifying structure that repeats endlessly at both the local and global scales. It's because of that self-similarity at different scales that I call this a "fractal" chord progression.
So, I built software to generate chord sequences that way, and I played them on the synth, and I thought it had possibilities but needed more variety. One way to build in some variety would be to swap between major and minor chords in a more interesting way. The rule above always generates a sequence of one minor and three major chords, over and over, even if the roots cover a wide range. So, more or less on intuition, I decided to use two different substitution rules, swapping between major and minor in the output whenever the input is minor:
major(x) → minor(vi(x)) major(iv(x)) major(i(x)) major(v(x))
minor(x) → major(vi(x)) minor(iv(x)) minor(i(x)) minor(v(x))
This pair of rules applied to a minor chord will generate chords that do not fit nicely into the corresponding minor scale, nor necessarily into any major scale, so it's to some extent breaking the assumptions of diatonic harmony, but that may be a good thing: it generates more variety and a bit of chromatic interest. Starting from G, applying the new rules once gives Em-C-G-D, same as before, because on a single major chord it's just the same as the earlier single rule. But then applying it a second time, the first four chords flip their qualities: C#-Am-Em-Bm-Am-F-C-G-Em-C-G-D-Bm-G-D-A. Not only the progression of chord roots, but also the quality of being major or minor, will exhibit a self-similar pattern.
Constraint programming for voicing
Each chord defines three notes out of the 12 in the octave, but it does not say in which octave to play each note - a decision called voicing. And the voicing really matters a lot to the way the music sounds; the ear tends to pick up the up-and-down motion of different voices as melody, more or less independently of the harmony defined by which chord is playing at a particular moment. So I wanted to have a way of automatically making voicing decisions that would lead to interesting music. I decided to apply constraint programming: define some rules constraining which voicings would be allowed, and then use a computer search to choose the specific notes.
If you read the MSK 008 manual there's an example in there of using ECLiPSe-CLP to choose the resistor values for the LED driver to satisfy conditions on the required voltages and currents. Here, we're going to do the same thing with notes.
One thing very noticeable about the vi-IV-I-V progression is that you can easily voice it to either go up or down, melodically. If your chords are Em-C-G-D and you choose the bass notes to be E-G-B-D, then it's going nicely up the scale a third at a time. On the other hand, you could instead choose the bass notes - with the same chords - to be G, E, B, A, and go down the scale a little less evenly, and then keep going another octave down as you wrap around the scale again. The same considerations apply to whichever note you choose to be the highest in the voicing. It's possible to run chords up and down several octaves, and change the voicing from all the notes close together to far apart in separate octaves, all without breaking the pattern. Different voicing decisions are used to good effect in Melissa Etheridge's "Angels Would Fall," where the same four chords repeat throughout, but the voicing goes either up or down depending on the mood of the lyrics at any given point. It would be nice to do something similar in a fractal-progression composition.
It's not easy to express the constraints I have in mind precisely without defining a lot of notation. In the actual composition I ended up writing them out in Prolog, but I don't really want to go through an introduction to Prolog, nor publish my (rather messy) complete source code. But here's the thing: given two voiced chords, we can say that they're going "up" if both the top and bottom notes go up: the second chord's lowest note is higher than the first chord's lowest note, and the second chord's highest note is highest than the first chord's highest note. Given that we have several octaves to play with, we can easily find such a voicing for any two chords. Similarly, we can say two voiced chords are going "down" if the top and bottom notes are both going down. We can similarly restrict two longer pieces of music to be going up or down by enforcing that the lowest and highest notes in the entire sequences, are higher or lower between the two.
Going further, a four-chord, or four-longer-chunk, sequence is going "up" if it goes up from each chunk to the next, and "down" if it goes down from each to the next. I ended up defining a third restriction for four-chunk sequences, too: the sequence is "flat" if it goes down, then up, then down again. ("Flat" in this case is not the opposite of "sharp" but rather the opposite of sloped - sorry if that's confusing, but that was the term that made sense to me when I was writing the code.) And I defined recursive rules for how to assign these voicing patterns, which combined with the previous rules end up looking something like this:
major(x,up) → minor(vi(x),up) [go up] major(iv(x),flat) [go up] major(i(x),up) [go up] major(v(x),flat)
major(x,flat) → minor(vi(x),up) [go down] major(iv(x),down) [go up] major(i(x),up) [go down] major(v(x),down)
major(x,down) → minor(vi(x),down) [go down] major(iv(x),flat) [go down] major(i(x),down) [go down] major(v(x),flat)
minor(x,up) → major(vi(x),up) [go up] minor(iv(x),flat) [go up] minor(i(x),up) [go up] minor(v(x),flat)
minor(x,flat) → major(vi(x),up) [go down] minor(iv(x),down) [go up] minor(i(x),up) [go down] minor(v(x),down)
minor(x,down) → major(vi(x),down) [go down] minor(iv(x),flat) [go down] minor(i(x),down) [go down] minor(v(x),flat)
Applying those rules recursively from a carefully-chosen "seed" sequence gives a list of chords and a complicated multi-level set of restrictions on how the lowest and highest pitches in different ranges of the piece have to be higher or lower than each other. I also set some rules (which I won't go into in detail here) how far each voice could jump between successive chords, and on the overall minimum and maximum MIDI notes to allow, covering a relatively narrow range near the start that widens out over time, the idea being that the piece should start out musically simple and then get more complicated with more open voicings. There is not much hope that a human being could choose notes to fit all the constraints that ended up generated by this recursive procedure, but the idea was never to do it by human effort anyway: I fed the whole mess into ECLiPSe-CLP and let it crunch for a while. There was a lot of back-and-forth as I tried different ideas, but I think the final constraint-satisfaction run ended up being about ten hours of CPU time overnight.
Here's the version I recorded in January 2015. That was before I started the company, so there are no North Coast modules in it as such, but it's using a one-off distortion module I made myself, as well as an Erica Polivoks VCF (which is responsible for a lot of the sound). This was one of the first tracks I ever recorded with the Polivoks VCF and I was blown away listening to the individual-voice tracks (of which there are three) as I was recording them. I was really pleased that the expressiveness of the unstable VCF survived even after I mixed the tracks down.
For this entry I dusted off the old MIDI files and recorded a new version with my new modules. This one showcases the Leapfrog VCF prototype, but I'm also using the Fixed Sine Bank for modulation, and the Octave Switch under both manual and LFO control (from the Sine Bank...) to put in some shifts on alternate notes. I'm also running it through a Clouds (not a North Coast module, sadly) to add some ambience, and using an Octave Switch output to control the pitch-shift on that. All in all it's a less polished track than the 2015 version, but still an interesting new take on the chord sequence.
◀ PREV Circuit board shopping || Year end NEXT ▶