Friday 30 April 2010

Random Walks in Max and PureData

It's been a while since we've looked at PureData and Max as algorithmic composition tools, today's algorithmic composition tutorial looks at Random Walks.

We've looked before in this Random Walks OpenMusic tutorial but this is the first time we've used in random walks in Max and PureData.

Random Walks
We'll start with a simple example:

1. Given a starting pitch of middle C
2. We will make a random choice of two possibilities, up or down 1 semitone from our current pitch
3. We now have a new pitch, from this new pitch go back to step 2 and repeat.


The easiest way to use random walks in Max and PureData is to use the drunk object. This object allows you to set a start value, maximum step size and a bound. Drunk then performs a random walk between 0 and the bound value. Here's an example of a drunk random walk in PureData:


And in Max:

Sunday 25 April 2010

OpenMusic and Chaos - OMChaos library

Our last few Algorithmic Composition posts have featured OpenMusic tutorials. We're continuing our look at OpenMusic today by looking at chaos, using the OMChaos library.

Chaos theory is a field of mathematics where dynamic systems are very sensitive to initial conditions. The famous 'butterfly effect' states that small differences can lead to large variations later: the small flap of a butterfly's wings may cause effects that later alter the path of a tornado.

Many of our previous algorithmic composition tutorials have used random elements (e.g. probabilities and Markov chains). Although Chaos might appear random, it's important to note that it is deterministic: if you run the algorithm again with exactly the same input it will produce the same output.

Today we'll start to look at using some Chaos algorithms to generate algorithmic music.

OpenMusic and Chaos - The OMChaos library
1. Make sure that OMChaos has been enabled in the preferences of OpenMusic.


2. Create a new patch in your workspace. OMChaos has 4 categories of functions: orbitals, IFS, fractus and UTILS.


3. The OMChaos orbitals menu features the core of the library. Each of these orbitals functions is a different chaos algorithm. Each of them shares the important chaos algorithm characteristic: small changes in initial conditions can lead to large changes later.

4. We'll start by using the KAOSN function.

5. This OpenMusic function is a form of a very common chaos algorithm fn+1=cfn(1-fn). That's to say: to get the next value of f, multiply the current values of c, f and (1 - f). This formula involves only 1 subtraction and two multiplies but it leads to chaotic behaviour. In this graph you can see with values of c below 3 the behaviour is very predicatable. However if c > 3.75 then very small changes in f lead to very large changes later on:


6. Here we've used 24 values for .95 for f 3.75 for c and set the length to be 24. Evaluating the KAOSN function will produce a series of 24 values based on these input parameters. Each time its evaluated it will produce the same numbers. If we change the input values to f 3.75 and c .94999, the numbers generated will start the same but slowly deviate as the sequence grows in length: the butterfly effect, small changes in initial conditions lead to large changes later on.


7. We'll use this chaos function to generate pitches between MIDI note 48 and 72. The output of the kaosn function is a series of floating point numbers between 0 and 1. To get the number in the range we want add:
  • an om* function and 24, giving our series a range of 0 to 24
  • an om+ function and 48 giving our series a range of 48 to 72
  • an om* function and 100, to change MIDI notes into the MIDIcents pitch representation OpenMusic uses
  • The om-round function rounds these numbers into integers

8. In this patch we'll have two voices with slightly different initial conditions for our chaos function. They will start playing identical notes and then slowly start to deviate. We'll append a reversed copy of the list, so we'll have a musical palindrome. To do this we can add cons and reverse functions. Reverse will reverse our original pitch list and cons will add this reverse pitch list to the end of our original pitch list. If you evaluate the cons function you'll see it's created list of lists (two sets of parentheses), we use the flat function here to flatten the list into a single set of parentheses:


9. Connect the output of voice, to the chords input of a voice.

10. We now need to duplicate what we have so far so we can create another set of pitches with slightly a different initial for our KAOSN function. Select all [CMD A on Mac, CTRL A on PC] and duplicate [CMD D on Mac, CTRL D on PC]. Change the second input to one your KAOSN functions to .94999, so that the two sections have slightly different initial conditions.

11. We also need to tell OpenMusic what rhythm to use for our melody. The voice function uses Rhythm Trees as its rhythmic representation. Rhythm trees are beyond the scope of this algorithmic composition post, but we will create some algorithmic music with rhythm trees in a future algorithmic composition tutorial. For now add in a repeat-n function and a mktree function. In this example we'll create 48 32nd notes:


10. Your patch should now look something like this (click on the image for a larger version):
11. To evaluate each voice press v, to play the voice press p to send it to a MIDI port. If you haven't done this already you can set up your MIDI outputs in OpenMusic preferences.

12. To hear both voices at the same time we need to create a list of both voices add in a poly function.


13. We can now hear both voices starting with the same pitches, slowly diverging and the converging back to the same pitches.

14. We'll be looking at rhythm trees in more detail in a future post, but for now to make the rhythms more interesting we'll use the nth-random function to choose randomly from a list of possible rhythms: (1/32 1/8 -1/16 -1/4 1/16) negative numbers represent rests. Repeat-n will generate a hundred of the randomly chosen rhythms:
15. Your final patch should look like something like this (I've changed the length of the sequence for both KAOSN functions to 50, giving us a melody 100 notes long when the reversed melody is added to the end). Click on the image for a larger version.



OpenMusic OMChaos Library Tutorial Summary
We've created an OpenMusic patch using the OMChaos library to generate chaotic pitches. Two voices have been used, with slightly different initial conditions the melodies diverge. Appending a reverse version of the melody on the end gives us a musical palindrome.

We then introduced the concept of rhythm trees in OpenMusic and randomly selected some rhythms from a given list.

Subscribe to the RSS feed and tune back regularly for more algorithmic composition tutorials, posts and reviews using Common Music, OpenMusic, PureData, MaxMSP and other algorithmic composition software.

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.

Wednesday 21 April 2010

OpenMusic and CSound - om2csound library

We've looked at algorithmic composition with OpenMusic in a few posts before. This post looks as using OpenMusic and CSound.

CSound is a very powerful synthesis program that is cross platform, free to download under the GNU Lesser General Public License and available here. It has hundreds of built in synthesis algorithms ranging from simple to advanced, cutting edge synthesis and sound processing methods.

CSound works with two files:
  • A .orc Orchestra file that specifies the instruments
  • A .sco Score file that specifies how the instruments will be played e.g. the notes
Although the synthesis algorithms are very powerful, writing scores by hand can be tedious, here's an example score:

f1  0      4096  10 1   
;p1 p2     p3    p4 p5   
 i1 0      .50   71 61    
 i1 .5000  .50   67 78    
 i1 1.0000 .50   63 70    
 i1 1.5000 .50   61 71    
 i1 2.0000 .50   76 78

This example has only 5 p-fields but an instrument can have many more p-fields than this. The standard 5 p-fields are:
  • p1 = instrument number
  • p2 = onset
  • p3 = duration
  • p4 = amplitude
  • p5 = frequency
The above CSound score specifies only 5 notes, an entire musical piece with lots of instruments could involve thousands of notes and would be time consuming to type in. Fortunately, we can use algorithmic composition techniques to generate our CSound scores for us.

1. OpenMusic has a CSound library, you need to enable this in preferences:


2. Create a new patch and add an instrument0 object:



3. This object takes inputs for the various p-fields and creates a list of all of the them to create our CSound score. As our instrument will have 5 p-fields we need to create some more inputs. Select the instrument0 object and press the > key twice, this will create two more inputs:


4. Now we create processes to fill these 5 p-fields, we can use any method we like but we'll keep things simple to start with. The first p-field in our example is easy, it's our instrument number and in this example is instrument 1.


5. The second p-field is onset time: the time the note starts. We'll keep our example simple and have 40 notes starting every half a second. For this we use an arithm-ser function (arithmetic series). For this we give a start value (0) an end value (19.5) and the step size:

This outputs a list of onsets that looks like this:
(0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 9.5 10.0 10.5 11.0 11.5 12.0 12.5 13.0 13.5 14.0 14.5 15.0 15.5 16.0 16.5 17.0 17.5 18.0 18.5 19.0 19.5)

6. Our next p-field is duration. We'll keep this simple and use .5 as a duration for all our notes. We can use a repeat-n function to do this:


Our patch now looks like this:
7. Our next p-field (p4) is amplitude. Again we could use any process to generate these numbers, but for now we'll make a simple random choice. CSound can work with amplitude values in dB and raw amplitude values and can convert from one to the other. Here we'll work with decibels and get OpenMusic to choose 40 random values between 60 and 90 using om-random and repeat-n functions:

8. Our 5th and final p-field is frequency, CSound supports a number of different pitch representations and can convert between them including frequency (Hertz), MIDI pitches, octave pitchclasses etc. We'll work with MIDI pitches and use the same method to generate our pitches as we used for amplitude: the om-random and repeat-n function:


Our patch now looks like this:


9. When we evaluate our patch it outputs a list of lists with all our algorithmic musical data in it. We next need to add in an editsco function that converts this and saves it as a .sco file.


10. We also need to add a function table into this. Function tables in CSound are used to store data that we need to access, this might be:
  • The points of a sine wave
  • A sample
  • An envelope shape etc.,
Our final patch looks like this (click on the image to see a larger version):



When we evaluate the editsco function, this will bring up a dialog box and save the file to disk. The final score file produced looks like this:

f  1       0          4096       10      1   
;p1        p2         p3         p4      p5   
i  1      0          .5000      64      81   
i  1      .5000      .5000      65      64   
i  1      1.0000     .5000      67      64   
i  1      1.5000     .5000      74      66   
i  1      2.0000     .5000      80      72   
i  1      2.5000     .5000      89      66   
i  1      3.0000     .5000      69      82   
i  1      3.5000     .5000      86      61   
i  1      4.0000     .5000      79      69   
i  1      4.5000     .5000      81      61   
i  1      5.0000     .5000      61      66   
i  1      5.5000     .5000      81      62   
i  1      6.0000     .5000      61      78   
i  1      6.5000     .5000      85      79   
i  1      7.0000     .5000      67      76   
i  1      7.5000     .5000      72      81   
i  1      8.0000     .5000      67      77   
i  1      8.5000     .5000      78      81   
i  1      9.0000     .5000      79      80   
i  1      9.5000     .5000      64      69   
i  1      10.0000    .5000      81      74   
i  1      10.500     .5000      86      62   
i  1      11.0000    .5000      82      72   
i  1      11.5000    .5000      71      75   
i  1      12.0000    .5000      61      65   
i  1      12.5000    .5000      66      77   
i  1      13.0000    .5000      67      73   
i  1      13.500     .5000      70      82   
i  1      14.0000    .5000      65      67   
i  1      14.5000    .5000      90      67   
i  1      15.0000    .5000      88      60   
i  1      15.5000    .5000      69      62   
i  1      16.0000    .5000      75      60   
i  1      16.5000    .5000      89      68   
i  1      17.0000    .5000      83      75   
i  1      17.5000    .5000      76      71   
i  1      18.0000    .5000      61      78   
i  1      18.5000    .5000      85      70   
i  1      19.0000    .5000      61      81   
i  1      19.5000    .5000      68      63   
e

Not only would this have been very time consuming to type in by hand, we now have the big advantage of using algorithmic composition techniques with OpenMusic and CSound: if we want to change anything or how we generate any of the musical parameters we're using (instrument, onsets, duration, amplitude, pitch) we can do this very easily.

For example in a previous post we looked at using different probabilities to algorithmically compose musical data. Let's say we want to use a triangle distribution instead of our current om-random function, we can keep our patch and plug a trian-seq function into our pitch instead (we've also used an om-round function to ensure each note is an integer.


To do this by hand would involve typing out and replacing lots of our score elements by hand, using algorithmic composition we can evaluate the patch again to output a new score and keep revising it until we like it.

Playing Your Algorithmic Score In CSound
You now have a .sco file. Save this example orchestra as a .orc file, you can paste this into a standard text editor and save it as basic.orc for example.

instr     1
a1    oscil     ampdb(p4), cpsmidi (p5), 1
      out       a1
endin


Open up your .orc and .sco files in CSound to render them to an audio file and listen to them. Our instrument is a simple sine wave oscillator oscil with just 3 parameters: amplitude, pitch and the function table we're using. Instruments can get much more complicated (and interesting) than this, and often end up with lots more p-fields in the score. This makes the range of sounds much more interesting but also means the score is more complex to complete by hand. Fortunately we can use algorithmic composition techniques to generate the score for us.

In future posts we'll have another look at creating CSound scores in OpenMusic and look at more interesting and developed methods of algorithmic composition and more developed CSound instruments. If you're interested in CSound there are some very good tutorials available at www.csounds.com.


Try modifying your patch to use some of the other different OpenMusic algorithmic composition methods we've looked at so far to generate CSound scores and check back to http://www.algorithmiccomposer.com/ soon for more algorithmic composition techniques.

Saturday 17 April 2010

The OpenMusic OMalea library - Random Walk

In our last post we had a look at some of the functions in the omalea OpenMusic library.

In the last post we looked at mapping some different probability distributions to pitch. Using other omalea functions, we can explore a number of random walk functions to generate pitch sequences:

Random walks
Imagine a drunk walking home. When he reaches a junction he can turn left, right or carry straight on, being quite drunk he randomly chooses a direction, then he reaches another junction and repeats the process.

Using a random walk process for deciding pitches with algorithmic composition, we choose a start note and then randomly choose between the same note, a note above or a note below, we can usually choose how big a steps our 'drunk' can take.

These two random walks brownian1 and randwalk1 set a start point, upper and lower boundaries, a sequence length and a bandwidth or maximum step.

brownian1:

rand-walk1:

The layout of both examples if fairly straightforward with the random walk function and a rhythm-tree, feeding into a voice object.

In a future post we'll look at some of the remaining omalea functions, including using markov chains in OpenMusic.

Friday 16 April 2010

Probabilities in OpenMusic using OMalea

We've introduced OpenMusic the computer-aided composition environment in a couple of previous algorithmic composition posts.

Today we'll have a look at using the OpenMusic library omalea to discuss the concept of probabilities and music. OpenMusic has a number of libraries that give additional functionality. Omalea (OM stands for OpenMusic and alea is Latin for dice. Aleatoric music uses chance as part of the compositional process. Both Pierre Boulez and John Cage have made use of aleatoric processes).

To enable the omalea library, go to preferences:

Check the omalea checkbox to load and enable the library:

In your workspace, create a new patch.
The omalea library offers four categories of functions: distributions, alea-seq, random-walk and tools.

Distributions
The distributions functions offer a range of ways of making aleatoric choices with different probability distributions.
The range of distributions includes linear (each possibility has the same chance of being selected e.g. RAN and RAN01), through choosing between 2 or a set a number of possibilities where you define their probability of being selected (CHOIX and CHOIXMULTIPLE), through to various triangle and various bell curve like distributions.

Choices (choix) - a coin flip' between two choices where you can adjust the probability. Here it's set to 50/50 chance of being note 5900 (B) and 6200 (D) - OpenMusic using MIDIcents to represent pitch so middle C (MIDI note 60) is 6000.

Poisson - a bell curve of normal distribution based around MIDI note 60.

A linear distribution.
When using the distribution functions to create pitches we had to perform a number of other operations to scale the numbers up and get appropriate values. OpenMusic uses MIDIcents to represent pitch so 6000 = MIDI note 60 or middle C.

If we're creating pitches, it's probably easy to use the alea-seq functions:


Not-centr chooses a random pitch, in this example around note 6000 +/- 12 semitones. It chooses only one value, here the repeat-n function has been used to generate a list of 8 randomly chosen notes:
Alea-seq works in a similar way, however as you can see in this example, it can generate lists of notes. Here we generate 8 notes, there's no need for the repeat-n function if using this object:
Linea-seq also produces a sequence of notes with a linear distribution. Using linea-seq you specify the number of notes and the upper and lower boundaries:


Triang-seq works in the same way to linea-seq, however it uses a triangle distribution. Notice how the notes are more centred around middle C:


Randomness, probabilities and chance are very useful tools for algorithmic composers. We'll look at these more in future posts in both OpenMusic and other software. We'll also have a look at some of the remaining omalea functions in future http://www.algorithmiccomposer.com/ posts and start to pull the tools together to create full compositions.