ProxyChain playing multiple synth and filter functions in one proxy
ProxyChain keeps a global repertoire of sound functions by name.
A ProxyChain has an ordered collection of sound functions and uses a nodeproxy
to add or remove the sound functions to/from the signal chain individually, by name.
*add(name, func, name, func, ... ) add functions to ProxyChain.allSources.
(
q = q ? ();
q.numChans = 5;
ProxyChain.add(
// add a sound source
\dust, \mix -> { |dens=20, dustdec=0.02, dustfreq= 600|
Ringz.ar(Dust.ar(dens).lag(0.0001), dustfreq, dustdec)
},
// an association with \filter becomes a filter,
// and creates a wet/dry balance on the output.
\ringmod, \filter -> { |in, randrate=5|
in.asArray[0] // force mono inputs
* SinOsc.ar(LFNoise0.kr([randrate, randrate]).exprange(300, 3000)).sum
},
\dist, \filter -> { |in, drive=10, amp=0.2| (in.asArray[0] * drive).clip2(0.5) * amp },
// an association with \filterIn also becomes a filter,
// but creates the wet/dry balance control on the fx input.
\riseComb5, \filterIn -> { arg in, delay = 0.023, dlDrift = 0.02, spread=0.5,
decayRise=0.5, decayFall=100;
var delayscales = 2 ** ((0 .. q.numChans - 1) * 2 / (q.numChans - 1) - 1 * spread);
var dels = delayscales.scramble.collect { |dscale|
var timedrift = LFDNoise3.kr(0.3, dlDrift, 1) * dscale;
var ampcomp = (20 * decayRise).dbamp * (decayFall ** -0.25);
var combs;
in = in.asArray[0] * ampcomp.lag(0.2);
combs = (decayFall * [ 1, decayRise]).collect { |decay|
CombL.ar(in, 1, delay * dscale, decay * delay)
};
combs[0] - combs[1]; // combs come in slowly, like formlet.
};
Splay.ar(dels)
}
);
// add specs for the controls used (for NodeProxyEditor).
Spec.add(\dens, [0.1, 1000, \exp]);
Spec.add(\dustamp, [0, 1, \amp]);
Spec.add(\dustdec, [0.0001, 0.1, \exp]);
Spec.add(\dustfreq, \freq);
Spec.add(\dt, [0.001, 0.2, \exp]);
Spec.add(\dc, [0.01, 100, \exp]);
Spec.add(\drive, [1, 100, \exp]);
Spec.add(\spread, [0, 1, \amp]);
Spec.add(\decayRise, [0, 0.9, \amp]);
Spec.add(\decayFall, [1, 1000, \exp]);
Spec.add(\dlDrift, [0, 0.1, \amp]);
s.boot;
)
*new(numChannels, slotNames, server)
numChannels - of the proxy
srcFunc - a source to put in slot 0
slotNames - define which functions from ProxyChain.allSources will be available in what order.
// can be sources (func, \mix -> func)
// or filters (\filter -> func, \filterIn -> func)
c = ProxyChain(q.numChans, [\dust, \ringmod, \dist, \riseComb5, \test]);
c.px.play; // play the proxy
c.gui(\chaintest, 12); // make a NodeProxyEditor for it
*from(proxy, slotNames)
make a proxychain for an existing proxy.
p = ProxySpace.push;
~pxchain.ar(2);
c = ProxyChain.from(~pxchain, [\dust, \ringmod, \dist, \riseComb5, \test]);
~pxchain.play;
add(key, wet) add a sound or filter function, wet is dry/wet balance
c.add(\dust, 0.123);
c.add(\dust, 0.2);
c.add(\ringmod, 0.5);
c.add(\dist, 1);
c.px.fadeTime = 2;
c.add(\riseComb5, 0.1); // \filterIn not show correctly in NodeProxyEditor yet.
// add a local version of a source:
(
c.add(\dust, nil, \mix -> { |dens=20, dustdec=0.02, dustfreq= 600|
Ringz.ar(Dust.ar(dens).lag(0.0001), dustfreq * [0.62, 1, 1.62], dustdec).mean
});
)
c.sources.postcs;
c.sources.put(\dust, nil);
c.add(\dust);
c.sources.postcs;
remove(key) remove a sound or filter function.
c.remove(\dist); // nodemap removes settings as well, so ...
c.remove(\ringmod);
c.remove(\riseComb5); // sometimes misses current value - why?
c.slotNames; // all slotnames that are available.
c.slotsInUse; // which ones are playing now?
c.remove(\dust);
butWin(name, buttonList, nSliders)
make a button window for simple control, and extra functions.
(
c.butWin(\PxChain,
[
[ \generators, \label ],
[ \dust, \switch ],
[ '1 > 1', \label ],
[ \ringmod, \switch ],
[ \dist, \switch ],
[ '1 > 5', \label ],
[ \riseComb5, \switch ],
[],
[\edit, \extra, { c.gui('Mestre', 16) }],
[\play, \extra, { c.px.playN }],
[\end, \extra, { c.px.end }],
],
16
)
)
To do:
insert new slotNames by name, or remove existing slotnames, keeping structure consistent;
for reconfiguration of the list of proxychain slots that can be used.
// maybe later like this.
c = ProxyChain(q.numChans, [\gen, [\dust], '1>1', [\ringmod, \dist], '1>5', [\riseComb5]]);