Friday, 23 April 2010

OpenMusic Markov Chains and omlea

We've looked at using OpenMusic for algorithmic composition in a number of posts before, we've also looked at using the OpenMusic OMalea library and random walks in OpenMusic. Today we're going to use OpenMusic and OMalea to work with Markov Chains.

Markov Chains are a very useful tool for the algorithmic composer, we've looked at Markov Chains in keykit here. If you're not familiar with how Markov Chains work it's definitely worth reading this algorithmic composition post.

In brief, Markov Chains chose the next note using a probability. For example if the current note is E, there might be a 70% chance of the next note being a A and a 30% chance of it being an C#. These probabilities are stored in something called a transition table or transition matrix.

We can either create the transition matrix by hand or we can create it by analysing an existing piece of music (or any other piece of data).


This is the approach we'll take in today's post. We'll load up a MIDI file, create a transition matrix from this using the ana-mark function, and then generate new melodies based upon this.

1. First of all we need to load up a MIDI file. Create a new class MIDIfile, either by choosing from the menu or CMD clicking (CTRL click on PC) and typing midifile.



2. Evaluate the midifile class by hitting the 'v' key or CMD clicking on it's output (CTRL click on PC). This will allow you to load up a MIDI file, once it's loaded make sure the midifile class is selected and press b to lock it. This will ensure that you don't have to load the MIDIfile every time you evaluate the patch.

3. We next have to extract the pitch data from the MIDI file. We can also use markov chains to generate rhythm, dynamics and other musical information, but for now we'll stick with pitch. Add a mf-info function, this allows to extract each note from the MIDI file.

4. If you evaluate the mf-info function, you can see a list of lists that describe each note, something like this, where the values are pitch, onset, duration, velocity and MIDI channel
((64 1000 500 52 1) (73 1500 385 58 1) (74 1875 125 43 1) (62 2000 500 32 1))

5. We need to access just the first element of each set of parentheses: the pitch. There are a number of ways we can do this, but the simplest is to use the mat-trans function followed by the first function. Add these in one a time and evaluate them to see what they do. You patch should now look like this:


6. Now when we evaluate our patch we get a list of pitches. This can be fed into the ana-mark function (remember you need the omalea library enabled to be able to use this function - this can be turned on in preferences if it's not already).

The ana-mark function in OpenMusic automatically generates a Markov transition matrix for us of the form:
((list-of-pitches ((first-pitch-probabilities) (second-pitch-probabilities... ... (last-pitch-probabilities)))

Something like this:
((1 2 3) ((0.0 1.0 0.0) (0.333 0.0 0.667) (0.0 1.0 0.0)))

7. We need to be able to separate our list of pitches, the first element in the list [ (1 2 3) in the above example ] from the list of probabilities [the second element in the list]. For this we can use the Lisp functions first and second. You can type first and second directly into a new box to create them, or create them from the drop down menu. So far our patch looks like this:

8. We can now connect a Markov function. There are two Markov functions in the OpenMusic omalea library, markov1 generates a single next pitch and can be used with repeat-n to generate a series of pitches. Markov2 generates a series of pitches. Here we've added a markov2 function and asked it to create a series of 50 notes starting with the first note.

9. When you evaluate markov2 you'll notice that outputs the index rather than the actual pitch we entered. So if we were using notes 60, 64, 65 and 67 the markov2 function thinks of them as 1, 2, 3 and 4. We can easily map this index to our original list of pitches by using the posn-match function (position match). Your finished patch should look like this:
Now when you evaluate the patch, we generate a list of pitches based upon the original set of pitches in out MIDI file. To get a better understanding of what's happening at each stage, evaluate each function in turn by selecting and pressing v and looking at the output in the listener window. To get a better understanding of Markov Chains in general do have a read through a previous on Markov chains and algorithmic composition.

You can also try using the Markov chains to generate elements of your CSound scores as looked at in the post on algorithmic composition, OpenMusic and CSound - using the om2csound library.

Check back soon for more algorithmic composition techniques and tutorials.

8 comments:

Mark Chambers said...

Hi,

I keep getting an error from the Markov2 object. It says "Error while evaluating the Mrkov2 box: In + of(0.0 nil) arguments of type number."

I have a screenshot of it.

BTW, I love this blog. I appreciate what you are doing. The IRCAM documentation is not the best. Not nearly as user friendly as cycling74's docs.

Thanks for the work.

Acuma said...

Hi Mark
Glad you like the blog, more posts coming up soon.

You can send the screenshot to algorithmiccomposer@hotmail.com and I'll have a look.

best,

Algorithmic said...

This error does sometimes occur when you evaluate Markov2 directly - connect it to a voice object and the problem seems to stop.

Try adding in the Markov rhythms from this tutorial and all should be well..

http://www.algorithmiccomposer.com/2010/05/algorithmic-composition-openmusic.html

Jesse said...

Hey man- Your blog is really awesome! I'm super into it! I have a question for you, though- I'm using OM 6.5. Your "mf-info" object has two inputs, but when I put down that object, it only has one input. The same with the "lisp+" and "lisp*" functions, except they have no inputs! Thanks man! :)

Algorithmic said...

Hi
Thanks for the comment. You can add more inputs to OpenMusic inputs by selecting and then keying > to add inputs or < to remove.

Hope this works for you!

All the best

Jesse said...

Thanks man! I appreciate your help! :)

Jesse said...

Hey, man! Sorry I keep bugging you, but I was wondering if you could tell me how to create the transition table in OpenMusic. I can't figure out what kind of object to use, and I can't find the information anywhere!
Thanks-

Jesse

Anonymous said...

I wonder how you did Mar4kov table, where it is written
Nilson

Post a comment