Play-function approach A (also see note below):
diff --git a/SCClassLibrary/Common/Collections/Event.sc b/SCClassLibrary/Common/Collections/Event.sc
index 9ceda30b6..77f68d9b6 100644
--- a/SCClassLibrary/Common/Collections/Event.sc
+++ b/SCClassLibrary/Common/Collections/Event.sc
@@ -243,7 +243,7 @@ Event : Environment {
),
durEvent: (
- tempo: nil,
+ tempo: { thisThread.clock.tempo },
dur: 1.0,
stretch: 1.0,
legato: 0.8,
@@ -449,7 +449,11 @@ Event : Environment {
~finish.value(currentEnvironment);
tempo = ~tempo;
- tempo !? { thisThread.clock.tempo = tempo };
+ tempo !? {
+ if(tempo.isFunction.not) {
+ thisThread.clock.tempo = tempo
+ }
+ };
if(currentEnvironment.isRest.not) {
Play-function approach B:
diff --git a/SCClassLibrary/Common/Collections/Event.sc b/SCClassLibrary/Common/Collections/Event.sc
index 9ceda30b6..8dcdc8c99 100644
--- a/SCClassLibrary/Common/Collections/Event.sc
+++ b/SCClassLibrary/Common/Collections/Event.sc
@@ -449,7 +449,11 @@ Event : Environment {
~finish.value(currentEnvironment);
tempo = ~tempo;
- tempo !? { thisThread.clock.tempo = tempo };
+ if(tempo.isNil) {
+ ~tempo = thisThread.clock.tempo;
+ } {
+ thisThread.clock.tempo = tempo
+ };
if(currentEnvironment.isRest.not) {
msgFunc approach:
diff --git a/SCClassLibrary/Common/Audio/SynthDesc.sc b/SCClassLibrary/Common/Audio/SynthDesc.sc
index 504c547a2..5ffde9747 100644
--- a/SCClassLibrary/Common/Audio/SynthDesc.sc
+++ b/SCClassLibrary/Common/Audio/SynthDesc.sc
@@ -442,6 +442,9 @@ Use of this synth in Patterns will not detect argument names automatically becau
if (name != "?") {
if (msgFuncKeepGate or: { name != "gate" }) {
if (name[1] == $_) { name2 = name.drop(2) } { name2 = name };
+ if(name == "tempo") {
+ stream << "\ttempo ?? { tempo = thisThread.clock.tempo };\n";
+ };
stream << "\t" << name2 << " !? { x" << suffix
<< ".add('" << name << "').add(" << name2 << ") };\n";
names = names + 1;
All tested with this code:
(
SynthDef("sinestempo",
{ arg out=0, freq=440, sustain=0.05, amp=0.1, pan, tempo;
var env;
env = EnvGen.kr(Env.sine(sustain / tempo), doneAction:2) * amp;
tempo.poll(Impulse.kr(0));
Out.ar(out, Splay.ar(SinOsc.ar({freq * Rand(0.98, 1.02) } ! 20, 0, env), spread: 1 - pan, center: pan))
}
).add;
)
p = Pbind(\instrument, \sinestempo).play;
TempoClock.tempo = rrand(1.0, 2.0);
p.stop;
For the play-function “\tempo as a function” approach A, one question is: should tempo: { something }
in an event set the clock’s tempo? This diff says no. First, nobody is doing that currently because the default event prototype barfs on any non-nil tempo value that is not a simple number – it’s not breaking a currently-valid usage.
Second, currently, if an event is play
-ed, and one of its keys is needed for an arg list, and that key is populated as a function, then the function is resolved at the last second, just before sending. Up until that moment, it’s passed around only as a function. So I’ve retained that – a \tempo
function remains an abstract value except for final resolution in the arg list. (If a user wants to calculate a tempo for every event, using a function, and make it a concrete value, they can write \tempo, Pfunc { ... something ... }
– which is exactly what they have to do now, so, no breakage. I think users should not be encouraged to exploit event-keys-as-functions except for rare cases where there’s no other way.)
If it would be desirable to evaluate a tempo function upfront, then at least do a check so that it calls tempo_ only when the tempo is actually different. I don’t think it will make a difference for TempoClock, but I’m not sure we want LinkClock, Scott W’s BeaconClock, or my DDWLeadClock and DDWFollowClock to broadcast repeated non-changing tempo changes. (Not calling tempo_ at all for a tempo function naturally avoids this.)
hjh