Musical Random Walks Over Weighted Graphs

7-vertex-cliquestl;dr: https://github.com/ology/Music/blob/master/random-walk

In this post, I illustrate a simple technique in Perl 5 to perform random walks over (node-edge) graphs, adding the named, “semantic” vertices to a MIDI score.

The image on the left is not generated by the random-walk program, but is just a related illustration. :-)

OK – on with the code!

First, there is the standard perl preamble:

Next, come the handy module imports:

Here we can see that the program is going to handle weighted graphs, choose from the node values and track the progress as MIDI data.

Next up is the declaration of the crucial program parameters – the number of notes to play and the starting graph node.  These can be taken from the command-line (with shift) or if not, set to defaults:

The first task is to define the treble note, bass note, note duration and note velocity transition graphs.  The transitions are the probabilities to other nodes in the graph.  Here is the graph for the treble notes:

Combined with the bass, duration and velocity graphs, this can be used to generate a melody of sorts.  Check out the code (linked above) to see the other graphs that are used.

So how do we go about creating a melody, you ask?  Well, the meat of the program is the note creation and collection:

More on that in a bit… Because the end of the program is just to add the notes to the MIDI score and write it to a .mid file (named for the program):

OK.  The meat of the program is to do the random walk over multiple graphs and collect the note information.  This is the code:

First we accept the arguments to this subroutine.  Then set the initial vertices to the given initial node.  Next we walk the graph for the number of notes desired.  For each iteration, we get the vertex label (the MIDI note information) and append that to our growing note collection.  If we are not done iterating, we request the next vertex based on the vertex edge values.

This is done with the following subroutine:

This code gathers the immediate successors of the given vertex and notes the edge cost of each – the weight.  Then this is used to choose a new vertex by selecting one of its edges, given its weighted probability.

So the final result of this is a potential melody that can be played with something like Timidity or imported into your favorite DAW and tweaked at will.  Also, you could generate a small phrase and then enhance it with counterpoint type transformations.  This is done in the related program, random-walk-transform.

Anyway, here is a 64 note example: random-walk.mid

Comments

*