super pedantic clarification:
when you use Function.fork with no clock argument, (or Routine.play) it still uses a (default) TempoClock. you can change the default TempoClock. you can use static methods to access the default TempoClock.
one reason this is significant is that TempoClock has meter and other stuff that SystemClock doesnāt:
s = Server.default;
s.waitForBoot({
t = TempoClock(5);
TempoClock.default = t;
{
SynthDef.new(\event, { arg freq;
Out.ar(0, SinOsc.ar(freq) * EnvGen.ar(Env.perc, doneAction:2) * 0.1);
}).send(s);
s.sync;
TempoClock.beatsPerBar = 5;
/// these do the same thing:
// TempoClock.default.beatsPerBar = 5;
// t.beatsPerBar = 5;
inf.do {
Synth(\event, [\freq, (60 + (3 * TempoClock.beatInBar)).midicps]);
1.0.wait;
};
}.fork;
});
and you can, say, modulate everything on the default clock at once:
s = Server.default;
s.waitForBoot({
t = TempoClock(5);
TempoClock.default = t;
{
SynthDef.new(\event, { arg freq, pan=0;
var snd = SinOsc.ar(freq) * EnvGen.ar(Env.perc, doneAction:2) * 0.1;
Out.ar(0, Pan2.ar(snd, pan));
}).send(s);
s.sync;
TempoClock.beatsPerBar = 5;
{
inf.do {
Synth(\event, [\pan, -0.5, \freq, (60 + (3 * TempoClock.beatInBar)).midicps]);
1.0.wait;
};
}.fork;
{
inf.do {
Synth(\event, [\pan, 0.5, \freq, (69 + (5 * TempoClock.beatInBar)).midicps]);
0.75.wait;
};
}.fork;
}.fork;
});
w = Window.new("tempo", Rect(0, 0, 100, 300));
Slider.new(w, w.bounds).action_( { |sl|
TempoClock.default.tempo_(sl.value * 20.0)
});
w.front;
iām trying to think of a scenario where itās better to explicitly schedule something on the SystemClock. in theory:
- if youāre calling stuff that isnāt thread safe.
- if you want to make sure its timing can never be messed with by something like the 2nd example above.