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], [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));
}).add;
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));
}).add;
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));
}).add;
//--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
//if crucial, bbc, redmod etc libraries not installed just comment out those lines (f, k, l, m, n)
(
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)))}).add;
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