// Markov Chains // (C) 2007 Fernando Lopez-Lezcano // "And the song is!..." // define the notes of our melody ~notes = [60, 60, 62, 60, 65, 64, 60, 60, 62, 60, 67, 65, 60, 60, 72, 69, 65, 64, 62, 70, 70, 69, 65, 67, 65]; // train a new markov set by using a stream derived from our array of notes // the third argument is the order of the chain, let's start with "1" ~chain = MarkovSetN.fill(~notes.size, Pseq.new(~notes).asStream, 1); // and we create potential seeds to "autostart" the pattern ~chain.makeSeeds; // print the entire markov chain // each line in the printout starts with a set of numbers (only one for first // order chains) and then a list of all the possible outcomes of that input // sequence of numbers, each outcome associated with a probability of occurrence // (and including the real number of occurrences at the end as well). In a given // row all probabilities will add up to "1" ( var dict = ~chain.dict; dict.keys.do( {arg key; var size, targets; size = (dict.at(key)).size; key.post; " --> ".post; size.do( { arg i; postf("<%,%:%> ", // the item dict.at(key).at(i), // its probability of occurrence truncated to 3 decimal places round(dict.at(key).weights.at(i) * 1000) / 1000, // number of times it was present dict.at(key).counts.at(i)); } ); "".postln; } ); ""; ) // a test instrument... ( SynthDef("beep", {arg midinote = 60, amp = 0.9, dur = 1, pan = 0, legato = 0.8; Out.ar(0, Pan2.ar( SinOsc.ar(midinote.midicps, mul: amp) * EnvGen.kr(Env.perc(0, dur*legato), doneAction: 2), pan ) ) }).store; ) SynthDescLib.global.read; // we now define the note played on our instrument based on our // Markov chain ( var note = 60, stream = ~chain.asStream; r = Task({ {Synth("beep", [ \midinote, { note = stream.next; note.post; " ".post; note }.value, \dur, 0.2 ]); 0.2.wait; }.loop; }).play(SystemClock) ) // we can now do higher order analysis ~chain = MarkovSetN.fill(~notes.size, Pseq.new(~notes).asStream, 2); ~chain.makeSeeds; // this won't be very successful as we easily get into dead ends... ~chain = MarkovSetN.fill(100, Pseq.new(~notes).asStream, 3, true); ~chain.makeSeeds; ( var note = 60, stream = ~chain.asStream; r = Task({ {Synth("beep", [ \midinote, { note = stream.next; note.post; " ".post; note }.value, \dur, 0.2 ]); 0.2.wait; }.loop; }).play(SystemClock) )