It wasn’t until recently that I explored the demand rate objects in Supercollider. They always kind of confused me. Learning sound synthesis in Csound there was AudioRate and ControlRate. Now in Supercollider this demand rate stuff seemed odd. Now after exploring the objects for the past year I have learned to love them. While I still don’t know how to explain them in terms of AudioRate and ControlRate I use them regularly to trigger patterns and change arguments.
There are several objects similar to the P objects i.e. Pseq, Pbind etc. but D objects can run in SynthDefs which is pretty cool.
This first example shows triggering frequency changes using Duty
trigger = {Duty.ar(Dxrand([0.1, 0.2, 0.3, 0.4, 0.5], inf), 0, Dwhite(100, 1000, inf))};
In this code the first argument “Dxrand([0.1, 0.2, 0.3, 0.4, 0.5], inf)” creates triggered rhythm with Dxrand selecting a value randomly and never repeating the same one in a row. The “0” after the Dxrand is reset and for this example we don’t need to reset anything. The TDuty will continue to select time values from the Dxrand. The last part, Dwhite, is a random white noise generator with values between 100 and 1000. The value produced by Dwhite is what gets sent as an argument to the object that Duty is controlling. For Example:
(
SynthDef(“example”, {
var in, trig;
trig = Duty.ar(Dxrand([0.1, 0.2, 0.3, 0.4, 0.5], inf), 0, Dwhite(100, 1000, inf)).poll;
in = SinOsc.ar(trig, 0, 0.4) ;
Out.ar(0, in);
}).add
)
a = Synth(“example”)
While you can also do this with “P” objects there are some fun uses using the “D” objects in ways that work well for interaction.
(
SynthDef(“delay”, { arg att = 0.01, rel = 1, test = 0.01;
var in, delay, thresh, al, de, b, list;
in = AudioIn.ar(1);
thresh = Amplitude.kr(in, att, rel, 1);
al = (thresh > test);
list = [some kind of list of values for delay time];
b = Dxrand(list, inf) ;
de = Demand.kr(al, 0, b);
delay = DelayN.ar(in, 1, de, 0.5);
Out.ar(0, [in, delay]);
}).add
)
In this example an audio input’s amplitude is being tracked and when over a certain threshold triggering the Demand.kr object to release a number to set the Delay amount. In this case the number is randomly selected using the Dxrand but an object like Dseq could also be used to sequence a series of delays in order.
Demand is a neat object because unlike Duty or the TDuty object Demand waits for a trigger to release a value. This makes it very powerful for interactivity.
(
SynthDef(“example2”, { arg fq = 10;
var trig, seq, freq;
trig = Impulse.kr(fq);
seq = Drand([Dseq((1..5), 1), Drand((4..10), 8)], 2000);
freq = Demand.kr(trig, 0, seq * 50).poll;
SinOsc.ar(freq, 0, 0.3);
}).add;
)
In this final example we are controlling the frequency of a SinOsc using a semi-random pattern. Drand selects one of the sequences and the value in the sequence is output to the Demand object. The demand object is triggered using an Impulse and the value selected by the Drand is multiplied by 50 which serves as the frequency we hear. Something I like doing with D objects is making their values arguments so I can control them dynamically when I am live coding.
I hope this small demand explanation is helpful. I am always looking to write about supercollider and Max/MSP stuff. A lot of times I write about questions or comments that my students bring up in class. Feel free to contact me if you have a question or want something demonstrated. I will do my best to make it useful.