25

I am a Software Developer/Musician who has free time before summer classes start up. I wanted to sharpen my chord reading and improvising skills.

What I would like to do is generate a phrase of variable length that has pseudo-randomly generated chords. I don't want to use completely random chords because I don't think that would sound good or be fun to play.

Are there rules to follow when creating a progression or "next chord" that will give you a higher probability of making something that sounds good, and is that method better than what you would get with just using completely randomly generated chords?

What I'm envisioning right now is something akin to getting 8 or 16 bars from a lead sheet, with interesting chords to sight read and practice for the day. I don't really care about a melody at the moment. From what I've read, currently even the best AI researchers have problems creating melodies for a given progression.

7
  • There is some research on this using AI but I feel it is a little overkill for what I am trying to do mateuszdorobek.pl/publication/Jazz-chords-generation
    – sntrenter
    May 25 '21 at 21:05
  • I like to play around with inversions and negative harmony. And jumping between octaves. And wolf whistles. And playing notes like a seesaw or other variants. And mixing chords/melody, and playing with volume intensity and repitition.
    – Emil
    May 26 '21 at 6:25
  • I think a wolf whistle that is in an entire chord shape is pretty cool, but it sounds a bit robotic, so maybe not sprinkle them all the time.
    – Emil
    May 26 '21 at 6:49
  • Check out Band-in-a-Box software by PG Music. It has a feature called reharmonize, which sounds like what you would like to do. It does require a melody to work from though. I don't know how the software comes up with its progressions, but I'm sure there is some interesting programming behind it. May 26 '21 at 10:20
  • If we made all the chords sus4s, would the chance that any random chord progression (made of those) would sound decent or better go up?
    – Dekkadeci
    May 26 '21 at 12:24

10 Answers 10

23

There are several "chord maps" on the net which indicate chord successions; these may be a good starting point. The chord maps do not give any relative weights or probabilities to chords.

A simple Markov Chain also makes a good model (but very limited.) The idea is to randomly (with indicated probabilities) generate the probability of a chord succession. Trivial version:

I -> V .40
I -> IV .60
IV -> I .30
IV -> V .70 
V -> I 1.00

This transition matrix may be expanded; it's too short-sighted (only on3 chord back) to generate anything that sounds good. One could make a two- (or more) step system but that quickly gets big (not hard to program, just tedious). Again, it doesn't capture long-range functions.

I've tried (but not very seriously) a Markov Chain with side information (V -> I gets more probable as the length of the chain increases). Other side information may be used for long-range patterns.

As pointed out in other answers, some stock movements (I -> ii6 -V7) may be chunked and treated as a single object (as could ii0-I64-V7-I or the like).

There are many papers on the subject. One can search Google Scholar to find interesting stuff.

18

Formal Grammars

I have done some research on formal grammars for composition. A formal grammar G = (V, S, P) consists of a vocabulary V, a starting symbol S in V, and replacement rules P. A rule consists of a left-hand side (LHS) that describes what it can replace, and a right-hand side (RHS) that describes the replacement. If you want to model harmonic progressions, your vocabulary would consist of chords. Consider this simple chord grammar I just made up:

V = {I, IV, V}
S = I
P = {
  p1: I  -> V I
  p2: V  -> I IV
  p3: IV -> I
}

We start with S in step 0. For every step we pick a random symbol in the sentence and pick a random rule that has the symbol as the LHS. We then replace the symbol in the sentence with the RHS of the rule. This can be repeated until no more symbols can be replaced (in this case indefinitely). Here is one example:

step rule sentence
0 - I
1 p1 V I
2 p2 I IV I
3 p1 I IV V I
4 p1 I IV V V I
5 p2 I IV I IV V I
6 p3 I IV I I V I

Complex Chord Grammars

Steedman1 defines a grammar for 12-bars Jazz:

chord substitution rules for 12-bars jazz by Steedman

Another example by Rohrmeier2 (not all rules shown):

chord substitution rules by Rohrmeier

Quick and Hudak3 use selection probabilities and a superscript that indicates the duration of the chord:

probabilistic temporal graph grammar for harmonic progression by Quick and Hudak

These images were taken directly from the references below. I will not explain the syntax and operations here; please read the full papers.

Comparison with Machine Learning

While machine learning, in particular artificial neural nets (ANNs), are very capable of solving language tasks, grammars (and traditional rule-based systems in general) have a few advantages:

  • Simple: It is essentially just string replacement. Setting up an ANN is more complex.
  • Transparent: It is clear why the grammar does what it does. ANNs are "black-boxes".
  • Flexible: If you are not satisfied, change the rules. ANNs need to be retrained.

The disadvantage is that you have to come up with the model. Grammars do not "learn" from data. But they can and have been combined with ML approaches as well.

Markov chains and transition matrices run kind of orthogonal to the grammars I show here. With the former you develop the progression in the direction of the timeline. With the latter you develop the progression from the abstract to the concrete and the whole timeline at once. I think both approaches have merits. At least with context-free grammars, you kind of lose the directional aspect.

Conclusions

Grammars are easy to setup and appropriate for the task. You can come up with your own rules, or use existing grammars from literature. Give them a try!


References

  1. Mark Steedman. The blues and the abstract truth: Music and mental models. Mental models in cognitive science, pages 305–318, 1996.

  2. Martin Rohrmeier. A generative grammar approach to diatonic harmonic structure. In Proceedings of the 4th sound and music computing conference, pages 97–100, 2007.

  3. Donya Quick and Paul Hudak. A temporal generative graph grammar for harmonic and metrical structure. In Proceedings of the International Computer Music Conference, 2013.


I recommend reading up on Probabilistic Temporal Graph Grammars3. Donya Quick further developed Kulitta, which is a Haskell library for automatic composition that uses such grammars for generating harmonic progressions.

4
  • This is a fascinating answer - I would add a section to it under ML. One application of ML could be to generate a set of chord combinations - representing each chord with relationship to the other as a vector (not a straightforward task) - then have one or more humans provide a rating for how good the chord progression sounds. In this approach you could "teach" the model how to find aesthetically pleasing combinations by observing patterns in the chords that would be otherwise difficult to recognize. Since chord progressions are short it would be fast to give each a rating by hand.
    – Paul Hazen
    May 28 '21 at 5:50
  • @PaulHazen Thanks, I agree, grammars are fascinating. What you describe sounds like something close to a Markov chain (1st order, if only chord pairs are used). While you could use human evaluators, the transition matrices are usually trained on existing progressions. You can essentially piggy bag on the aesthetic taste of master composers. Still, Markov chains also have drawbacks. For example, they are lacking in large-scale structure, which you can easily achieve with grammars.
    – Lucius
    May 28 '21 at 14:24
  • "...until no more symbols can be replaced (in this case indefinitely)" this is the real problem/challenge rather than picking the "next chord." It's the difference between pointless rambling and a sensible phrase. The Steedman example seems to deal with the problem, because it's a series of substitutions/insertions in a 12 bar blues, a predetermined phrase structure, not really a next chord generator. May 28 '21 at 20:37
  • @MichaelCurtis My simple example recurses indefinitely, but you can also be very precise about which abstractions appear at which level of the derivation. With a context-free grammar you get the sentence as the leaves of a tree structure. That tree structure can contain phrases, bars, tension/release - any hierarchical organization really. This is why I prefer grammars as a foundation over Markov chains, etc. They allow automation and randomization in a very deliberate way, at the cost of me actually having to think about how the generates piece should look.
    – Lucius
    May 29 '21 at 6:05
8

One reasonable starting approach is to pick a key, generate a first chord, treating each note as an independent voice, then for subsequent chords, change one or two notes (voices) by one or two semitones each, staying within the key signature.

That will give you series of chords with smooth voice-leading, which is a significant element in creating pleasing chord progressions. Once you see the types of sequences you get, you can refine the algorithm. For example, there might be restrictions in terms of how many moves can be made in one direction, or whether two notes are required to move in the same or different directions.

If you really want to get into the thick of things, find a copy (or online summary, perhaps) of Johann Fux's The Study of Counterpoint, and encode the rules for "first species" in three or four voices.


To generate a complete phrase, it's probably easiest to use the "phrase model", which would mean including a tonic, pre-dominant, dominant, and again tonic chord, in that order. Since you will be generating diatonic chords (with the above algorithm), you can encode the functions of each type of chord to do a rough analysis of the chords being generated.

1
  • 1
    I like the approach, though it doesn't seem exactly fitting for the Jazz tag the OP has in the question. May 25 '21 at 22:01
4

AI and computer-assisted aren't the same thing. True AI is very hard, because the computer has to infer all the patterns from trial and error.

But in your case, you could fairly easily program the following:

  • common cadence patterns
  • rules about movement by cycle of fifths or by thirds
  • variants of chords
  • several modulatory patterns, including enharmonic diminished 7ths.

Personally, I'd recommend using a series of SQL tables to define increasing levels of complexity. For example, you could define chord types and their inversions in one table. Another table would list sequences of chords and inversions that go well together, from simple two-chord progressions to more complex cadences.

The nice thing about doing it this way would be that additional tables could be used to organize more complex processes (like modulating to a key a minor second down).

You can also do it progressively: start with just a couple simple cadences and some simple harmonic motions, and then add new variants and complexities as you develop the system.

By the way, I'm not just speculating as a fellow pianist, I'm fairly active in stackoverflow as well. I could probably be talked into collaborating on something like this, because I've sometimes thought of doing it as well. :D

4

Breaking this down into parts:

  1. To sharpen your chord reading skills, I recommend getting a real book (or two) and a metronome. Open the real book to a random page and set the metronome to a challenging tempo. For variety, give yourself a list of genres and choose from those too (e.g. swing, bossa, samba, double time ballad etc). When the metronome starts try to read the whole piece without stopping and record yourself. Afterwards you can go over the recording and see which sections you had trouble with. The advantage of this approach is that you'll be using real chord sequences that you're likely to encounter when playing. Howard Roberts had a guitar method that recommended doing something similar to this (Jazz Guitar Technique in 20 Weeks).

  2. To answer the question of how to generate these in software, the easiest approach would be to take a corpus/dataset of chords and train a markov based model to predict new sequences. One example dataset is here https://github.com/infojunkie/ireal-musicxml although you may need to do additional processing to get the chords into a useful format.

Are there rules to follow when creating a progression or "next chord" that will give you a higher probability of making something that sounds good, and is that method better than what you would get with just using completely randomly generated chords?

Yes - two that spring to mind are voice leading and periodicity. To implement voice leading in software you can use the algorithms suggested by Dmitri Tymoczko. There's an implementation in R here: https://github.com/pmcharrison/minVL Periodicity determines how consonant a chord will sound for a given key center - there's ongoing research to determine how this results in chord sequences but it will give you a starting point on whether a given chord "sounds good" when compared with a randomly generated starting point. See https://github.com/pmcharrison/incon for various implementations of periodicity/harmonicity. From that selection, I prefer Stolzenberg (2015).

2

You could try something that works around harmonic sequences.

There is a common saying that goes something like "it's not a mistake if you play it twice" or in Adam Neely's words "repetition legitimizes." Harmonic sequence exploits that idea, because you repeat a harmonic pattern. Even if the progression is "odd", sequencing it can often turn it into something of interest.

Make some templates for two or three chord progressions (bi-grams or tri-grams.) You could do that several different ways, but starting with one of the four diatonic seventh chords and then moving to the next chord by voice leading or root progression procedures, will give you a whole lot of bi-grams.

Take the palette of bi-grams, randomly select one, then sequence it for three iterations. Randomly select ascending/descending direction and half-step of whole step distance for the sequence.

You should be able to top off the sequential passage with a full or half cadence, moving from the last sequential chord by root progression of P4 or P5 to either a ii or V to start the cadence should work. You could program that or do it on the fly as a type of improve exercise.

That will provide at least 8 bar, and in most cases it should make musical sense. If you ensure a good amount of variety on the bi-gram palette, you will get a lot of "randomness." But not random in the musical sense of musical nonsense. The sequencing will make it work. But three stages of random selection (bi-gram, sequence direction, sequence distance) will provide lots of novel progressions.

1

As you are not doing this for "earnest" reasons but just to play around and sharpen your skills, how about this: learn to work with simple AI networks (e.g., Tensorflow). Download as many chord progressions as you can (maybe in the form of free tabulatures which there are plenty available). Write a little parser which extracts just the chord progression. Train your network with that. See what it spits out.

Alternatively, you can try to personally train the network. Let it just do its thing, play its progression on your own guitar, and decide for yourself if you like it or not; then feed this decision back into the training.

Both should be quite interesting and also pretty achievable exercises. Will you create the next Rock Opera with this? Probably not. But it should be a nice little exercise indeed!

1

If you're feeling up to the task of labelling a dataset and want to go the AI route, you could try LSTMs.

You can choose a musical Key, and then each chord in the key would be a categorical variable (maybe stick with just Major and Minor chords, and then include extensions in later experiments).

If C->Db->...->B is 1->2->...->12 for major and is 13->...->24 for minor, then the progression in the key of C:

C G A F would be the data point [1 8 10 6],

When you have a large dataset of these points, you can train LSTMs.

The python package Keras contains lots of out of the box models which are helpful. The syntax for building a neural network in Keras is (in pseudocode):

from keras import Sequential, LSTM, Dropout

model = Sequential()
model.add(LSTM(units = 50, return_sequences = True, input_shape =(4, 1))
model.add(Dropout(0.2))
model.add(LSTM(units = 50, return_sequences = True))

model.fit(training_data)

Another advantage on this approach over accuracy is that you can add additional categorical variables into the dataset. For example, if you wanted to get common chord progressions for a genre, when you create your data point, label the genre too.

So a chord progression in the rock genre might look like: C G A F would be the data point [1 8 10 6, 0]

where the last 0 is genre.

The general use of this is that if you input a starting chord, the model returns the next chords.

# Pseudocode
input data = [6]
model.predict(input_data)
-> [6, 8, 3, 1]

The best [imo] guide on LSTMs is [here][1]. It assumes familiarity with Neural Networks in general.


  [1]: https://colah.github.io/posts/2015-08-Understanding-LSTMs/
0

It's more complicated than "given x chord what could come next"? As that implies that in a progression of chords, n is only related to n-1, and not n-2. You are correct to expect that totally random sounding chords will not sound good. And while there are ways to be confident that chord n+1 won't sound out of place after chord n, a function of purely f(n-1) will sound (overall, to the ear which is listening to the entire progression with a context larger than 2 chords in sequence) just as random. To put it another way, while it's fair to say that "chord x can follow chord y", there as an assumed context of a broader progression happening in which chord x and chord y fit together.

Your progression generator, to sound minimally random and bad, would need to begin with somehow choosing or generating that context (key/mode/some stylistic bias for chord selection), and then work within that to create a base progression, and then optionally modulate that base progression in successive repetitions with variations and substitutions of the base progression chords.

It might be useful to create a data model of the circle of 5ths and to internally model the chords as offsets around the circle, as this would make the selection and code-syntax of the description of chords related to each other by their key-center, and the relationships between different key-centers more intuitive in your code.

I have a (stalled out) project where I was working toward doing something similar to this. It was also an exercise in studying music theory, as I had to really learn well each fundamental theory-concept in order to architect those concepts in relation to each other as classes and objects, just to have a base framework in which I could express musical concepts in code. Over 2-3 weeks I worked out a pretty solid baseline architecture of pitchclass, intervals, and scales, with unit tests for using them them to do various transpositions and calculations. This is where I stalled but the next step would have been to implement smart classes for building a lot of chord concepts on top of the interval and scale concepts, and then perhaps integrate the circle of fifths and key centers. Only after that would I have been prepared to use that framework in some procedural code to try to do something cool like generating corny robot music. :)

-1

Frame challenge:

It is not meaningful to codify what a "good" pseudorandom progression because such models are either already explained through music theory or music analysis. Instead of using computers to be creative, why not understand the creativity of existing art made by humans for humans.

The premise of your question assumes some idealized version of "good" chord progression. Another assumption you make is that you can have a computer generate some "good" chords through rules. That is, you can generate pleasant sequence of chords without necessarily understanding the function or the underlying principles of music, which many other answers have alluded and referenced.

What a procedure can do is mimic existing progressions, even if it is using AI (which is just applied heuristics).

Instead of trying reducing music to a couple of chord progs or markov chains, try to examine and explain why common progressions sound "good" to you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.