// we haven't had one of these in a while...
s.boot;
(
var osctypes, oscFunc, synthDefNames, synthDefFunc, counter, verbBus;
osctypes = UGen.allSubclasses.select({
|c|
var m;
m = c.class.findRespondingMethodFor(\ar);
m.isNil.if({ false }, { (m.argNames[1] === \freq) &&
m.argNames.includes(\mul) })
}).reject({
|c|
// remove un-modulatable or poorly interpolated UGens
c === FSinOsc || "[L|N]$".matchRegexp(c.asString) ||
"LFNoise".matchRegexp(c.asString)
});
oscFunc = {
|freq = 220, level = 0|
var subnode;
subnode = (level/3).coin.if({
0
}, {
{ LPF.ar(oscFunc.value(exprand(0.5, 5000), level + 1), 5000,
exprand(1, 1000)) } ! 2
});
osctypes.choose.ar(freq: freq + subnode)
};
synthDefNames = { |i| "Metamucil" ++ i.asString } ! 100;
synthDefFunc = {
|i|
SynthDef(synthDefNames.wrapAt(i), {
|out = 0, verbBus, freq = 220, gate = 1, attack = 0.5, release =
0.5|
var env, osctree, panner, final;
env = EnvGen.kr(Env.asr(attack, 1, release), gate: gate,
doneAction: 2);
osctree = Limiter.ar(LeakDC.ar(oscFunc.value(freq)) * -30.dbamp)
* -3.dbamp;
panner = Mix.fill(2, { |i| Pan2.ar(osctree[i],
LFNoise1.kr(exprand(0.1, 5.0))) });
final = panner * env;
Out.ar(verbBus, rrand(-36, 0).dbamp * final);
Out.ar(out, final)
})
};
synthDefFunc.value(0).memStore;
verbBus = Bus.audio(s, 2);
~verbSynth = { GVerb.ar(In.ar(verbBus.index, 2), drylevel: 0) }.play;
counter = 0;
p = Pbind(
\instrument, Pfunc({
var x = counter;
counter = counter + 1;
synthDefFunc.value(counter).memStore;
synthDefNames.wrapAt(x)
}, inf),
\freq, Pfunc({ exprand(20, 2000) }, inf),
\dur, Pfunc({ exprand(0.5, 10.0) }, inf),
\legato, Pfunc({ exprand(1.0, 4.0) }, inf),
\attack, Pfunc({ exprand(0.5, 5.0) }, inf),
\release, Pfunc({ exprand(0.5, 5.0) }, inf),
\verbBus, verbBus.index
);
)
e = p.play;
e.stop; // might take a little while
~verbSynth.free;
--
Tim Walters | The Doubtful Palace | http://doubtfulpalace.com