Write Like Taylor Swift--A Markov-chain based Pop Music Chord Generator

Josh Oberman
Coursera Developing Data Products Class

What is a Markov Model

  • A Markov model is a mathematical model that defines transition probablities between a set of states {S1...SN}. These probabilities may be defined in a 2-d transition matrix, where rows represent the current state and columns represent the possible transition states.

  • Markov Models are widely used in natural language processing applications, biogenetics, and a handful of other fields. There has been some academic work applying markov modeling to musical melody and harmony, usually focusing on sophisticated classical composers who constructed highly formal compositions, such as Bach. Somewhat strangely, markov modeling of pop music songs remains underdeveloped, despite being far less formally complex.

Deriving Chord Progressions from Pop Music

  • As an inital application, I decided to work wiht a very simple small dataset: 4 chord progressions from 3 major pop artists. The songs were all in major keys and the intervals of the chord progressions (i.e. I,II,III,IV,V, etc.) were entered manually in to my RCode.

  • I then built a custom algorithm that created a transition matrix by summing up the transitions between the harmonically related chords. I treated each 4 chord progression independently, and "forced" resolution by making the V chord an "absorption state" in the Markov Model that always lead back to the I. I then used the "markovchain" R library to auto-generate chord progressions of arbitrary length that always start on the I. Song matrices were also divided in to verse chords and chorus chords, respectively

Building the Transition Matrix

The transition matrix was constructed by adding "1" to the proper row, column index each time a chord transitioned. The code below is taken verbatim from the app, and allows one to input a matrix of songs where each column represents the key-independent sequence of chords.

transMatrix<-function(songs){
    uniqueVals<-unique(c(songs)); nVals<-length(uniqueVals); len<-nrow(songs)
    p <- matrix(nrow = nVals, ncol = nVals, dimnames = list(uniqueVals,uniqueVals), 0)
    for (t in 1:(ncol(songs))){
        for(i in 1:len - 1){
            p[songs[i,t], songs[i+1,t]] <- p[songs[i,t], songs[i+1,t]] + 1
        }
    } 
    for (i in 1:nVals){
            p[i, ] <- p[i, ] / sum(p[i, ])}
        p
    }

Applications

  • Tool for creative block
  • Teach people how to "write like Taylor Swift"
  • Interesting AI auto-generation of pop music

Areas for further work

  • Handle chord progressions of arbitrary length
  • Use higher-order Markov Models that account for the chords 2-3 back in the sequence instead of just one chord back.
  • Find a good database or webscrape a site (i.e. link) for chord progressions and write code to process the key-independent harmonic intervals
  • Handle midi file input; run markov models on drum patterns, vocal leads, etc. accounting for semantic parsing of rhythm and melody + duration of notes, etc