Hello again,
This is a pretty “low urgency question”.
I am designing a Pbind that should modulate certain parameters over time according to user input (through midi for example), whilst others stay the same. I have arrived at three different solutions, and I am curious if one is more efficient or preferred in general. These Patterns should be able to evaluate at around 6.000 times per second ideally, possibly even more during performance, which is why the efficiency question is important.
The patterns are wrapped in a class.
//Method 1: Pfunc
MyClass {
var <>amp
getPbind {
^Pbind(
\amp, Pfunc({amp}),
\freq, Pseq([220, 330], inf)
)
}
}
This is the simplest in syntax, but I think calling the Pfunc so many times per second (also, its many Pfuncs per Pbind in the actual code) is less efficient.
//Method 2: Pdef + Plambda
MyClass {
var <amp;
getPattern {
var freqP = Plet(\melody, Pseq([220, 330], inf), 1);
var bindP = this.evalPdef;
^Plambda(
Ppar([freqP, bindP], inf)
);
}
evalPdef {
^Pdef(\myPattern,
Pbind(
\amp, amp,
\freq, Pget(\freq, 220, inf)
)
);
}
amp_ {|val|
amp = val;
this.evalPdef;
}
}
Syntax here is a little more complicated but it seems to me that its more efficient, as we make the most of Pdef’s live EventStream editing functionality. But this may just be from my limited understanding of what sclang and the Patterns interface is doing behind the scenes.
//Method 3: Directly communicating with Synths through Control Busses
MyClass {
var <amp, ampBus = Bus.control(s);
getPattern {
^Pbind(
\freq, Pseq([220, 330], inf),
\ampBus, ampBus
)
}
amp_ {|val|
amp = val;
ampBus.value_(val)
//Synths read from this bus at init time
}
}
This would offload some of the pressure from the client to the server, although the server is also running CPU intensive tasks, so maybe this also isn’t preferred.
Thank you for any insights, and also for all the patience answering these questions!