Tdef task reference definition


superclass: TaskProxy





keeps a reference to a task (time pattern) that can be replaced while playing.

It plays on when the old stream ended and a new stream is set and schedules the changes to the beat.


Tdef(key) returns the instance, Tdef(key, pat) defines the pattern and returns the instance, like Pdef and Ndef.

it is very similar to [TaskProxy]



*new(key, obj)

store the task in a global dictionary under key.

if there is already a Tdef there, replace its task

with the new one.

obj is a function or a pattern of time values.

*new(key)

acess the task at that key (if none is there, a default task is created)

*default

a default source, if none is given. the default is a loop that does nothing with a 1.0 beat wait time

*removeAll

remove all tasks

*all

dict that stores all Tdefs

*all_(envir)

set the global environment

quant_(beats)

set the quantisation time for beat accurate scheduling

can be a pair [offset, quant]

*defaultQuant_(beats)

set the default quantisation for new instances (default: 1.0)

can be a pair [offset, quant]


condition_(func)

provide a condition under which the pattern is switched when a new one is inserted.

the stream value and a count is passed into the function.

the methods count_(n) simply counts up to n and switches the pattern then

reset

switch the pattern immediately. (stuck conditions can be subverted by this)



envir_(event)

provide a default environment for the proxy. 

If given,  it is used as an environment for the routine 

function. When set for the first time, the routine pattern is rebuilt.

set(key, val, key2, val2, ...)

set arguments in the environment. 

If there is none, it is created and the routine pattern is rebuilt.


endless

returns a Proutine that plays the proxy endlessly, replacing nil with a default

value (1 s. wait time). This allows to create streams that idle on until a new pattern is inserted.



a) using it as stream reference

embedInStream(inval)

just like any stream, embeds itself in stream.

see example for usage.


b) using it as Task


play(clock, doReset, quant)

starts the Pdef and creates a player. 

if you want to play multiple instances, use .playOnce(clock, doReset, quant) quant can be an array of [quant, phase]

stop

stops the task

player

the current task (if the Tdef is simply used in other streams this is nil)


pause / resume / reset / mute / unmute

perform player method 

isPlaying 

returns true if Tdef is running.

if a Tdef is playing and its stream ends, it will schedule a task for playing 

as soon as a new function is assigned to it.





a) using Tdef as a task player



Tdef(\x).play; // create an empty Tdef and play it.


Tdef(\x, { loop({ "ggggggggggggggggg9999ggg999ggg999gg".scramble.postln; 0.5.wait; }) });



Tdef(\x, { loop({ "---------////----------------------".scramble.postln; 0.25.wait; }) });

Tdef(\x, { loop({ thisThread.seconds.postln; 1.wait; }) });

Tdef(\x, { loop({ thisThread.seconds.postln; 1.01.wait; }) });


TempoClock.default.tempo = 2;


Tdef(\x, { "the end".postln });

Tdef(\x, { "one more".postln });

Tdef(\x, { loop({ "some more".scramble.postln; 0.25.wait; }) });


TempoClock.default.tempo = 1;


Tdef(\x).stop;

Tdef(\x).play;


Tdef(\x).clear;





// sound example


(

// load a synthdef

s.boot;

SynthDef("pdef_grainlet", 

{ arg out=0, freq=440, dur=0.05;

var env;

env = EnvGen.kr(Env.perc(0.01, dur, 0.3), doneAction:2);

Out.ar(out, SinOsc.ar(freq, 0, env))

}).store;

)

Tdef(\x).play;


(

Tdef(\x, { 

loop({

s.sendMsg("/s_new", "pdef_grainlet", -1,0,0, \freq, rrand(600, 640));

0.1.wait;

})

})

)


(

Tdef(\x, { 

var x;

x = Pseries(300, 20, 100).loop.asStream;

loop({

s.sendMsg("/s_new", "pdef_grainlet", -1,0,0, \freq, x.next);

0.05.wait;

})

})

)


(

Tdef(\x, { 

var x;

x = Plazy({ Pseries(300 + 300.rand, 10 + 30.rand, 10 + 30.rand) }).loop.asStream;

loop({

s.sendMsg("/s_new", "pdef_grainlet", -1,0,0, \freq, x.next);

0.05.wait;

})

})

)


// metronome

Tdef(\y, { loop({ s.sendMsg("/s_new", "pdef_grainlet", -1,0,0, \freq, 1500); 1.wait; }) }).play;


// play ending stream once

(

Tdef(\x, { 

var x, dt;

dt = [0.1, 0.125, 0.05].choose;

x = Plazy({ Pseries(1300 + 300.rand, 110 + 130.rand, 16) }).asStream;

x.do({ arg item;

s.sendMsg("/s_new", "pdef_grainlet", -1,0,0, \freq, item);

dt.wait;

})

})

)


... and so on ...


Tdef(\x).stop;

Tdef.removeAll;




b) embedding Tdef into other Tasks / Routines



(

Tdef(\a, { "one".postln; 1.wait; "two".postln });

Tdef(\c, { var z; z = Synth(\default); 0.5.wait; z.release });

r = Task({

"counting...".postln;

2.wait;

Tdef(\a).embedInStream;

1.wait;

Tdef(\c).embedInStream;

"done.".postln;

});

)


r.play; // play a stream


Tdef(\c, { var z; z = Synth(\default, [\freq, 300]); 1.5.wait; z.release }); // change the def


r.reset;

r.play;


// of course Tdefs can be used in other Tdefs:

(

Tdef(\b, {

"counting...".postln;

2.wait;

Tdef(\a).embedInStream;

1.wait;

Tdef(\c).embedInStream;

"done.".postln;

});

)

Tdef(\b).asStream.play;


// if one wants to branch off a stream in a separate thread, asStream is used.

// also the method playOnce can be used

(

Routine({

Tdef(\c).asStream.play;

0.1.wait;

Tdef(\c).asStream.play;

0.1.wait;

Tdef(\a).asStream.play;


}).play;

)







Tdef as a time pattern


Instead of using a Pdefn for time values, it can be useful to use a Tdef. 

When changing its source, it keeps the stream of values synchronized to its clock.



(

// load a synthdef

s.boot;

SynthDef("pdef_grainlet", 

{ arg out=0, freq=440, dur=0.05;

var env;

env = EnvGen.kr(Env.perc(0.01, dur, 0.3), doneAction:2);

Out.ar(out, SinOsc.ar(freq, 0, env))

}).store;

)





Tdef(\z, Pseq([1, 1, 1, 0.5, 0.5], inf));


(

Pset(\instrument, \pdef_grainlet, 

Ppar([

Pbind(

\dur, Tdef(\z),

\note, Pseq([1, 3, 2, 1, 0], inf),

\x, PfuncTempoClock.default.elapsedBeats.postln } // posts the onset times

),

Pbind(

\dur, 4, // reference beat

\sustain, 0.1,

\note, 8

)

])

).play(quant:1);

)



Tdef(\z, Prand([1, 1, 0.23, 0.5, 0.5], inf)); // exchange time pattern

Tdef(\z, Pseq([1, 1, 1, 1], inf)); // pattern stays in sync.

Tdef(\z, Pseq([1, 1, 1, 0.5, 0.5], inf)); // but might be in different order (

// to avoid this, set the quant to a appropriate value.