Thursday, 20 May 2010

Algorithmic Composition with OpenMusic | Markov Chains and Rhythm

Previous Algorithmic Composition tutorials have looked at using Markov Chains in OpenMusic, using some of the functions available in the OMalea library to analyse the pitches of a MIDI file and create new algorithmic compositions based on these.

Today we're looking using Markov Chains in OpenMusic to generate rhythmic patterns for algorithmic compositions.

 Algorithmic Composition Markov Chain OpenMusic
Our previous OpenMusic tutorial used these functions from OpenMusic's OMalea library:
  • ana-mark to analyse a MIDI file to create a transition table of pitches and
  • markov1 to generate a new algorithmic composition based on the transition table.
Although we were previously using our Markov chain to analyse and generate pitches, you can also use ana-mark and markov1 from the OpenMusic OMalea library to generate rhythms.

Algorithmic Composition: Rhythm
Each note has two rhythmic properties: the note onset and the note duration. If we're representing our rhythms as absolute time in milliseconds (ms) it's important when analysing an existing MIDI file to do some pre-analysis work on it. For the purposes of building our Markov transition table, all note onsets and durations should be carefully quantized and all tempo changes removed. It's also useful to use a single tempo of 60 BPM.

Using a tempo of 60 BPM means that the durations are consistent, easily divisible and easy to read

Whole note = 4000
1/2 note = 2000
1/4 note = 1000
1/8 note = 500
1/16 note =250
etc

This does not mean that you can only produce music at 60BPM as it is very easy to change the tempo later for example, halving the onset time and duration of each note would double the tempo. Using a consistent tempo means that you can create your transition table from multiple pieces of music.

If you don't quantize the music before analysis, we may have many different similar values for note durations. All of these durations might sound like 1/8th notes 506 498 502 490 513, however as they are different values they won't be treated as equivalent in our Markov analysis.

Before analysis:

  • Load your MIDI file(s) into a sequencer and carefully rhythms, ensure that you quantize note onset, note on and note off.
  • Remove tempo changes and set the tempo to 60BPM.
Using OpenMusic OMalea library to Generate Markov Rhythms
The note list from a MIDI file in OpenMusic is output in the following order:

1. Pitch
2. Onset
3. Duration
4. Velocity
5. Channel

Previously we used the Lisp first function to analyse only the pitches of our MIDI file and to generate an algorithmic composition like this:


Algorithmic composition OpenMusic

Rather than taking the first value (pitch) we can take the third (duration) to analyse and algorithmically compose a rhythm from the Markov chain of the input durations:

Algorithmic composition Markov
We can perform a Markov analysis on both the pitches and durations and the algorithmically generate some new musical examples based on these analyses:

Algorithmic composition Markov tutorial
OpenMusic OMTP Library
The examples above use the OMalea library to analyse and generate algorithmic compositions based on Markov Chains. Paul Nauert's OMTP library also includes some Markov functions, these are specifically designed as rhythm tools. In preferences ensure the OMTP library is enabled:

Algorithmic composition OpenMusic Markov

In this first example, we work use the m-rhythm function from the OpenMusic timepack library (OMTP):

Algorithmic composition
To start with we'll generate a simple algorithmic composition using a zero order Markov chain. Zero order Markov chains base their next choice only on a set of probabilities and do not consider what the previous event was.

OpenMusic Markov
The inputs to the m-rhythm function are as follows:
  • A list of possible rhythms
  • The probability of each rhythm occuring
  • A target length in bars
  • An initial condition for the Markov Chain.
In the above example 1/8th notes are the most probable and 16th note rests the least probable.

To make the output a little more interesting we'll add an n-cercle class to our patch:

OpenMusic algorithmic composer
The n-cercle class is usually used as a representation of pitch classes, here we've a diminished scale into the n-cercle - double click the n-cercle to enter the editor.

OpenMusic algorithmic composition

We'll then choose some random pitch classes from our scale and combine this with our zero order Markov chain:

OpenMusic zero markov
The p->mc function is from Nauert's other OpenMusic library OMPF.

To create a first order Markov chain using m-rhythm we create a nest list: a list of lists. Each sublist represents one rhythm and the probability of the other rhythms in the list following it:

algorithmic composition Markov
In a similar way we can create a second order Markov chain by having a deeper nested list:

algorithmic composition
It's possible to create any order Markov chain using m-rhythm by using nested lists.

In forthcoming algorithmic composer tutorials we'll explore in more depth OpenMusic and the OMTP and OMPF libraries, as well as exploring similar algorithmic composition ideas in MaxMSP, PureData, Common Music and other algorithmic composition software.

Subscribe to the RSS feed and check back soon for more algorithmic composition tutorials.

1 comment:

Kelly Forte said...

How do you make the first patch in this post a 2nd order markov chain?

Post a comment