Second Order Markov Chains in PureData

It’s been too long since the last algorithmic composition post, but a series of new posts are on the way!

To kick things off we’ll revisit one of our previous Markov chain algorithmic compositions. Previously we looked at first order Markov chains in PureData. We also extended this into a second order Markov chain in Max.

Let’s have a quick recap first.

First Order Markov Chains
In a previous Algorithmic Composition post we built a first order Markov Chain analysis and generation patch. In 1st order Markov chains the next note is based on the current note and a list of probabilities for following notes. This is stored in a State Transition Matrix (STM), here’s an STM that lists the notes of Happy Birthday and the probabilities of each subsequent note.

Second Order Markov Chains
Second order Markov Chains choose the next note based on the two previous notes and the probability of subsequent notes following those two notes:

Creating 2nd Order Markov Chain Analysis and Generation in PureData.
1. First complete the steps to create a first order Markov chain in Pd. Your main patch window should look something like this:

2. In order to modify our patch to perform a second order analysis we need to make a couple of small changes to our ‘pd markovMIDIAnalysis’ and pd markovPitchGenerate’ subpatches.

Second order markov chains base the next note on the previous two notes and the probabilities of other notes following those two notes in sequence. We therefore need to store the two notes as our index.
We’ll modify our analysis and composition patches to store and access these two notes together e.g. 60 60 becomes 6060, 72 69 becomes 7269 etc. Inside ‘pd markovPitchAnalysis‘ modify the ‘pd pair’ subpatch to look like this:

When we implemented a 2nd order Markov chain in Max we used the ZL stream object, unfortunately this isn’t implemented yet in PureData however the following subpatch does the same job. The contents of your ‘pd zl-stream’ subpatch should look like this:

3. We’ve now completed the analysis part of our 2nd order patch. Finally modify the pd markovPitchGenerate’subpatch to look like this:

Load up a MIDI file and you’re all set to be generating 2nd order Markov Chain compositions in PureData. A further interesting thing to try is to use multiple named coll objects each with a different piece of source music in each and transition between them.

You can hear some example output from this second order Markov chain here

It’s also good to try implementing first order Markov chains for rhythm generation too.

A new series of algorithmic composition tutorials will be coming up over the Summer, so bookmark and check back soon for more algorithmic composition tutorials for Max, Pd, OpenMusic and more

10 thoughts on “Second Order Markov Chains in PureData

  1. Rafael Valle

    Hi, this is Rafael Valle.
    I came up with an abstraction that allows the usage of any order abstraction.
    Please let me know if you’d be interested in posting the code here!

    Best Regards and thank you for this great website,
    Rafael Valle

  2. Olivvier

    Hi, thanks a lot for your tutorials. I have some issues with this one, I have checked everything twice and it doesn’t work. In your video demo when you click on the “pd Markov analysis” it seems to be different from the capture you put on this page, since there is no “pd chunk” mentionned..
    Could you post the puredata file or explain me how to make it work?
    Thanks Olivier

  3. tom karches

    Questions :
    – is the Random 30 just used to give some velocity variation?
    – when I did the 1st order Markov, the music never stopped. This one eventually stops. Why is that?

  4. Algorithmic Composer Post author

    Thanks for the questions.
    1. yes the random 30 is to give some variation to the MIDI velocity
    2. it depends on the source material you’re using for the Markov chain, though it’s more likely to stop with higher order Markov chains. The Markov chain stops when it reaches a deadend, so if MIDI notes 64, 62 can only be followed by MIDI note 60 and after this there were no notes MIDI note 60 in the original piece. Then the Markov chain can’t continue, it’s possible to put a little addition to the patch in that catches this and retriggers.

    Hope this helps!


Leave a Reply