Here’s something I’ve been interested in for a while – finally made a prototype after a question on the mailing list.
The question was about handling continuous control changes in a pattern context. Patterns are oriented toward discrete events, making it harder to handle arbitrary control signals.
I’ve been saying for a long time that I think the best way to handle it is to allocate, map and deallocate buses automatically. That is, instead of trying to handle everything within one SynthDef, we could have a player that would put several synths together.
This example depends on a couple of extensions, which you can find in this gist. (I had hoped to upload the files as attachments, but, inexplicably, a SuperCollider users’ forum does not allow SuperCollider source files to be uploaded!)
With those extensions, then you can do like this:
(
SynthDef(\testMod, { |out, gate = 1, amp = 0.1|
var eg = EnvGen.kr(Env.asr(0.01, 1, 0.1), gate, doneAction: 2);
var freq = ModControl.kr(\freq, 440, \exp);
Out.ar(out, (SinOsc.ar(freq) * (eg * amp)).dup);
}).add;
SynthDef(\lfo, { |out, gate = 1, rate = 2|
FreeSelf.kr(gate <= 0);
Out.kr(out, LFTri.kr(rate))
}).add;
SynthDef(\ctlEnv, { |out, levelScale = 1, levelBias = 0, time = 1, connect = 1|
var env = \env.kr(Env.newClear(12).asArray);
var init = In.kr(out, 1);
var start = Select.kr(connect, [env[0], init]);
Out.kr(out, EnvGen.kr(env, 1, levelScale, levelBias, time));
}).add;
)
// sliding pitches played in the default SynthDef
// *without adding sliding logic into the SynthDef*
(
p = Pbind(
\type, \notemap,
\dur, Pexprand(0.1, 0.8, inf),
\legato, Pexprand(0.5, 3.0, inf),
\freqEndpoints, Pexprand(200, 1200, inf).clump(2),
\pan, Pwhite(-1.0, 1.0, inf),
\detunedFreq, Pfunc { |ev|
var sustain = ev.use { ~sustain.value } / thisThread.clock.tempo;
(
instrument: \ctlEnv,
env: Env(ev[\freqEndpoints], [1], \exp),
time: sustain,
addAction: \addBefore
)
}
).play;
)
// LFO with depth envelope
(
(
type: \notemap,
instrument: \testMod,
degree: 2,
amp: 0.5,
freqMod: (instrument: \lfo, addAction: \addBefore),
freqModDepth: (
instrument: \ctlEnv,
env: Env([1, 1.5], [2], 4),
time: 1,
addAction: \addBefore
),
sustain: 3
).play;
)
There are certainly some problems left to deal with. Automatic pitch conversions are not compatible (because of some funky handling of ‘detunedFreq’, it doesn’t work to apply a control-signal event to \freq
directly – this would have to be cleaned up). Also I haven’t fully dealt with releasing the auxiliary synths. And currently it’s necessary to specify addAction
in the sub-events (this will get boring very quickly).
But, for a rough prototype, it works surprisingly well. It’s not leaking synths or buses AFAICS.
Posting here to gauge how much interest there is in this sort of idiom.
hjh