RedMst a sort of timeline - master controller

RedMst controls track objects (RedTrk). it does so by sending play and stop messages to them synced to a clock. RedMst also has a global counter for sections. if a track is not already playing and is activated to play for a certain section, it gets sent a play message when RedMst reaches that section, else the track is stopped.

The section counter is driven manually by user input (*next, *goto, etc) or by RedSeq. all messages controlling playback (*next, *previous, *goto, *play, *stop) are scheduled to happen on the next quant beat.

note: when you replace/overwrite a RedTrk as it is running, it will stop playing and not start until you goto a new RedMst section.

see also [RedTrk], [RedTrk2], [RedSeq], [RedMstGUI], [RedGrandMst],

[RedMstGUI], [RedMstGUI2], [RedMstGUI3]

*play(startSection)

play activated tracks on the next quant beat.

*goto(gotoSection)

play activated and stop non-activated tracks on the next quant beat.

*next

go to the next section (section= section+1) on the next quant beat.

*prev

go to the previous section (section= section-1) on the next quant beat.

*isJumping

true if about to go somewhere on the next quant beat.

*stop

stop all tracks on the next quant beat.

*clear

stop and remove all tracks, reset section counter and stop the clock. clears action function.

<*tracks

dictionary of all tracks. tracks (RedTrk objects) add themselves here when created.

<>*clock

master clock. if not set TempoClock.default is used.

<>*quant

master quant beat. default= 4.

<*section

counter for current section.

<*maxSection

highest section found among all tracks.

<*jumpSection

nil if not going somewhere.

equals next section index if about to go to that section on the next quant beat.

<>*stopAheadTime

how much time ahead play the stop message will be scheduled. default= 0.05 seconds.

<>*skipEmpty

next and previous methods skip over sections that does not have active tracks. default= false.

<>*action

a function to be evaluated when section changes.

<*isPlaying

boolean

*at(key)

returns track for key.

*add(trk)

done automatically for all new instances of RedTrk.

*remove(trk)

usually done with *clear. removes a track from master controller.

*makeWindow(size, skin)

convenience method. see RedMstGUI

//note: if you press cmd+. then you'll need to start the clock again

//--simple example with 3 pbind tracks

(

s.waitForBoot{

RedMst.clear; //remove all tracks and clock from previous

RedMst.clock= TempoClock(150/60); //create and set a new clock

RedMst.quant= 4; //set quant beat

RedTrk(

\bass, //track name

Pbind(\degree, Pseq([0, 5], inf), \octave, 4), //track item

#[0, 1, 2, 3] //track active sections (when to play)

);

RedTrk(

\melody,

Pbind(\degree, Pseq([0, 5, 2, 3, 3, 1], inf), \dur, Pseq([0.25, 0.25, 0.5], inf)),

#[1, 2, 5]

);

RedTrk(

\melody2,

Pbind(\degree, Pseq([7, 6, 4, 3], inf), \dur, 2, \octave, 6),

#[2, 3]

);

}

)

RedMst.play;

RedMst.next;

RedMst.next;

RedMst.next;

RedMst.next; //nothing in section 4 so quiet. see skipEmpty

RedMst.next;

RedMst.stop;

RedMst.clear;

//--more advanced example with 7 pbind tracks and custom synthdefs

(

s.waitForBoot{

RedMst.clear; //start afresh - remove tracks

RedMst.clock= TempoClock(150/60); //set master clock

RedMst.quant= 4;

//--synths

SynthDef(\hat, {|out= 0, tuesday= 5000, amp= 0.5, pan= 0|

var e, z;

e= EnvGen.kr(Env.perc(0.01, 0.1), 1, amp, doneAction:2);

z= BPF.ar(PinkNoise.ar, tuesday*(e+0.5));

Out.ar(out, Pan2.ar(z*e, pan));

}).store;

SynthDef(\bas, {|out= 0, freq= 70, gate= 1, amp= 0.5, pan= 0|

var e, z;

e= EnvGen.kr(Env.adsr(0.01, 0.6, 0.4, 0.1), gate, amp, doneAction:2);

z= LPF.ar(LFSaw.ar(freq), freq*2*(e+1));

Out.ar(out, Pan2.ar(z*e, pan));

}).store;

SynthDef(\pad, {|out= 0, freq= 700, gate= 1, amp= 0.5, pan= 0|

var e, z;

e= EnvGen.kr(Env.asr(0.01, 0.5, 0.1), gate, amp, doneAction:2);

z= LPF.ar(LFSaw.ar(freq*[1, SinOsc.kr(3, 0, 0.008, 2)]).mean, freq*3, 0.4);

Out.ar(out, Pan2.ar(z*e, pan));

}).store;

//--patterns

RedTrk(\hatSimple, Pbind( //track name

\instrument, \hat,

\dur, Pseq([0.6, 0.4], inf),

\amp, Pseq([0.2, 0.5], inf)

), #[0, 1, 3, 4]); //which sections track active

RedTrk(\basIntro, Pbind(

\instrument, \bas,

\dur, Pseq([0.6, 1, 1, 1, 0.4], inf),

\amp, 0.5,

\sustain, 0.6,

\degree, Pseq([0, 5, 4, 5, 1], inf),

\octave, 3

), #[0, 3]);

RedTrk(\padA, Pbind(

\instrument, \pad,

\dur, Pseq([2, 3, 1, 1], inf),

\amp, 0.5,

\degree, Pseq([[0, 5], [0, 4], [3, 5], [3, 5]], inf),

\octave, 4

), #[1, 4]);

RedTrk(\basA, Pbind(

\instrument, \bas,

\dur, 1,

\amp, 0.5,

\degree, Pseq([Pseq([-3, -2, 2, 1], 3), -3, 1], inf),

\octave, 3

), #[1, 4]);

RedTrk(\basBreak, Pbind(

\instrument, \bas,

\dur, 4,

\amp, 0.4,

\degree, Pseq([-2, -3], inf),

\octave, [3, 4],

\strum, 0.1

), #[2]);

RedTrk(\hatBreak, Pbind(

\instrument, \hat,

\dur, Pseq([0.2, 0.2, 0.2, 0.4], inf),

\amp, Pseq([0.5, 0.3, 0.3, 0.5], inf)

), #[2]);

RedTrk(\padTrem, Pbind(

\instrument, \pad,

\dur, Pseq([0.2, 0.2, 0.2, 0.4], inf),

\amp, Pseq([0.5, 0.3, 0.3, 0.5], inf),

\degree, 0

), #[2, 3]);

}

)

RedMst.play //start from beginning

RedMst.next //goto section A (index 1) on next beat1. activated tracks will play

RedMst.next //goto next section (break = index 2)

RedMst.next //and so on... (index 3...)

RedMst.goto(2) //jump back to break

RedMst.next

RedMst.stop

RedMst.tracks

RedMst.tracks.keys

RedMst.maxSection

RedMst.play

RedMst.section

RedMst.action= {("action! tempo:"+RedMst.clock.tempo+"section:"+RedMst.section).postln}

RedMst.next

RedMst.goto(0)

RedMst.goto(1)

RedMst.goto(2)

RedMst.goto(3)

RedMst.goto(4)

RedMst.stop

RedMst.clear //free all tracks and remove them from RedMst. clears action function

//note: does not stop the clock

//--example with some different items

(

var a, b, c, d, e, f, g, h, i, j, k, l, m, n;

s.waitForBoot{

RedMst.clear;

RedMst.clock= TempoClock(150/60);

RedMst.quant= 4;

//--items (just comment out any 3rd party classes you don't have installed)

a= Pbind(\freq, Pseq([500, 600], inf));

b= Pdef(\pdef, Pbind(\degree, Pseq([0, 1, 2, 3, 5], inf)));

c= Tdef(\tdef, {inf.do{|i| i.postln; 1.wait}});

d= Ndef(\ndef, {SinOsc.ar([900, 909], 0, 0.3)});

e= Routine({inf.do{|i| (i*10).postln; 1.wait}});

f= Patch(Instr(\test, {SinOsc.ar([400, 404], 0, 0.1)}));

g= NodeProxy.audio(s, 2).source= {SinOsc.ar([500, 505], 0, 0.1)};

h= {SinOsc.ar([600, 606], 0, 0.1)};

i= SynthDef(\def, {|gate= 1| Out.ar(0, SinOsc.ar([700, 707], 0, 0.1*EnvGen.kr(Env.asr, gate, doneAction:2)))}).store;

j= {"testing, testing".postln}.asRoutine; //wrap functions in routines to play them

k= BBCut2(CutStream1.new, BBCutProc11.new);

l= BBCut2(CutBuf2(BBCutBuffer("sounds/break")), BBCPPermute.new); //(bad style as buffer not freed)

m= RedMOD.read("~/mods/lukas/eva.mod").prepareForPlay;

n= RedXM.read("~/mods/4-mat_-_rose.xm").prepareForPlay;

//--tracks

RedTrk(\steady, Pbind(\legato, 0.1, \freq, 800), #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);

RedTrk(\test01, a, #[1]);

RedTrk(\test02, b, #[2]);

RedTrk(\test03, c, #[3]);

RedTrk(\test04, d, #[4]);

RedTrk(\test05, e, #[5]);

RedTrk(\test06, f, #[6]);

RedTrk(\test07, g, #[7]);

RedTrk(\test08, h, #[8]);

RedTrk(\test09, i, #[9]);

RedTrk(\test10, j, #[10]);

RedTrk(\test11, k, #[11]);

RedTrk(\test12, l, #[12]);

RedTrk(\test13, m, #[13]);

RedTrk(\test14, n, #[14]);

}

)

RedMst.play(0) //section 0 - only steady reference pulse

RedMst.goto(1) //pbind

RedMst.goto(2) //pdef

RedMst.goto(3) //tdef

RedMst.goto(4) //ndef

RedMst.goto(5) //routine

RedMst.goto(6) //patch

RedMst.goto(7) //nodeproxy

RedMst.goto(8) //{}.play

RedMst.goto(9) //synthdef

RedMst.goto(10) //function as routine - just posting once

RedMst.goto(11) //bbcut2 stream - uses audio input

RedMst.goto(12) //bbcut2 buffer

RedMst.goto(13) //redmod

RedMst.goto(14) //redxm

RedMst.stop

RedMst.clear