PLbindef wrapper for Pbindef which allows replacement in object prototyping style
Part of: miSCellaneous
Inherits from: Pbindef
PLbindef works like a normal Pbindef and, like the latter, uses Pdef's global bookkeeping, but replacement of key streams can be done in object prototyping style with a dedicated PLbindefEnvironment, which also holds player methods. This Environment is itself assigned to the PLbindef's name in an Environment of choice, by default the current Environment. Setting can thus be done in very condensed syntax, also in combination with EventShortcuts.
NOTE: PLbindefs are registered globally in the same Dictionary as Pdefs, Pbindefs and PLbindefPars. It's recommended to do cleanup with 'clear' after using PLbindef / PLbindefPar as in examples below. Otherwise unwanted or strange behaviour might be caused by leftover sources when playing a new PLbindef / PLbindefPar example with same key. With SC >= 3.7 occasional posts of the default parent event occur with Pbindef, so also with PLbindef. I didn't notice any different other behaviour though.
See also: PLx suite, PLbindefPar, PLbindefEnvironment, PLbindefParEnvironment, EventShortcuts, PLx and live coding with Strings
Creation / Class Methods
*new (...args)
Creates a new PLbindef object. First arg should be the key, followed by key/value pairs for the Pbindef. The last arg can be an optional environment which determines where the corresponding PLbindefEnvironment should be stored, by default this is the current Environment at instantiation time.
Instance Methods
clear
As with Pbindef: stop, but in addition remove name entry from refEnvir and clear sourceEnvir.
sourceEnvir
Getter for PLbindef's PLbindefEnvironment.
refEnvir
Getter for the Environment where PLbindef's PLbindefEnvironment is associated with PLbindef's key.
Examples
// synthdefs to play with
(
SynthDef(\noise_grain, { |out = 0, freq = 400, att = 0.005, rel = 0.1, rq = 0.1, amp = 0.1|
var sig = { WhiteNoise.ar } ! 2;
sig = BPF.ar(sig, freq, rq) *
EnvGen.ar(Env.perc(att, rel, amp), doneAction: 2) *
(rq ** -1) * (250 / (freq ** 0.8));
OffsetOut.ar(out, sig);
}).add;
SynthDef(\sin_grain, { |out = 0, freq = 400, att = 0.005, rel = 0.1, amp = 0.1|
var sig = { SinOsc.ar(freq, Rand(0, 2pi)) } ! 2;
sig = sig * EnvGen.ar(Env.perc(att, rel, amp), doneAction: 2);
OffsetOut.ar(out, sig);
}).add;
SynthDef(\saw_grain, { |out = 0, freq = 400, att = 0.005, rel = 0.1, amp = 0.1|
var sig = { VarSaw.ar(freq, Rand(0, 1)) } ! 2;
sig = sig * EnvGen.ar(Env.perc(att, rel, amp), doneAction: 2);
OffsetOut.ar(out, sig);
}).add;
)
Ex.1) Setting key streams
// store PLbindef under key \x
(
PLbindef(\x,
\instrument, \sin_grain,
\dur, 0.2,
\midinote, Pwhite(60, 90)
)
)
// Environment has been made and assigned to the variable ~x in currentEnvironment, check
~x
// now the Environment can also be treated as a player
~x.play
// set params while playing
~x.att = Pwhite(0.01, 0.2)
~x.midinote = 75
~x.att = 0.01
~x.dur = 0.02
~x.midinote = Pbrown(60, 90, 1.5)
// pause
~x.stop
// resume
~x.play
// use method 'value' for parallel setting
~x.(\dur, 0.05, \midinote, Pwhite(70.0, 72))
~x.stop
// cleanup
~x.clear
Ex.2) PLbindef with EventShortcuts
// syntax can be more condensed with EventShortcuts, turn it on, post defaults
EventShortcuts.on
EventShortcuts.postCurrent
(
PLbindef(\u,
\i, \saw_grain,
\d, 0.2,
\m, Pwhite(60, 90)
)
)
~u.play
~u.d = 0.1
~u.m = Pn(Plazy { Pseries(rrand(50, 70), 1.5, 20) })
~u.m = ~u.m + [0, 4, 7]
~u.i = PLseq([\sin_grain, \saw_grain])
~u.a = Pn(Pseries(0.05, 0.01, 20))
~u.m = 70
// stop + cleanup in one
~u.clear
Ex.3) PLbindef with VarGui
// start with gui and define pitch sequence with sliders
(
p = PLbindef(\z,
\i, \saw_grain,
\d, 0.2,
\m, PLseq(\midi)
);
VarGui([\midi, [50, 90, \lin, 1, 60] ! 7], stream: p).gui;
)
~z.m = PLseq(\midi) + [0, 5, 8]
~z.m = ~z.m + PLseq([-1, 0, 1] * 12)
~z.clear
Ex.4) PLbindef with PbindFx
See also Ex.7c in PbindFx help
// boot server with extended resources
(
s.options.numPrivateAudioBusChannels = 1024;
s.options.memSize = 8192 * 16;
s.reboot;
)
(
SynthDef(\echo, { |out, in, maxEchoDelta = 0.2, echoDelta = 0.1,
decayTime = 1, amp = 1, mix = 1|
var sig, inSig = In.ar(in, 2);
sig = DelayL.ar(
CombL.ar(inSig, maxEchoDelta, echoDelta, decayTime, amp),
maxEchoDelta,
maxEchoDelta - echoDelta
);
Out.ar(out, (1 - mix) * inSig + (sig * mix));
}).add;
SynthDef(\wah, { |out, in, resLo = 200, resHi = 5000,
cutOffMoveFreq = 0.5, rq = 0.1, amp = 1, mix = 1|
var sig, inSig = In.ar(in, 2);
sig = RLPF.ar(
inSig,
LinExp.kr(LFDNoise3.kr(cutOffMoveFreq), -1, 1, resLo, resHi),
rq,
amp
).softclip;
Out.ar(out, (1 - mix) * inSig + (sig * mix));
}).add;
SynthDef(\noise_grain, { |out = 0, freq = 400, att = 0.005, rel = 0.1, rq = 0.1, amp = 0.1|
var sig = { WhiteNoise.ar } ! 2;
sig = BPF.ar(sig, freq, rq) *
EnvGen.ar(Env.perc(att, rel, amp), doneAction: 2) *
(rq ** -1) * (250 / (freq ** 0.8));
OffsetOut.ar(out, sig);
}).add;
SynthDef(\saw_grain, { |out = 0, freq = 400, att = 0.005, rel = 0.1, amp = 0.1|
var sig = { VarSaw.ar(freq, Rand(0, 1)) } ! 2;
sig = sig * EnvGen.ar(Env.perc(att, rel, amp), doneAction: 2);
OffsetOut.ar(out, sig);
}).add;
)
// prepare EventShortcuts for additional keys
(
EventShortcuts.addOnBase(\default, \fxs, (
dec: \decayTime,
cd: \cleanupDelay,
cf: \cutOffMoveFreq,
fxo: \fxOrder,
dta: \echoDelta
), true);
EventShortcuts.makeCurrent(\fxs);
EventShortcuts.on;
)
(
// source and fxs passed as PLbindefs
k = [\q, \echo, \wah];
PLbindef(\q,
\i, PLrand([\noise_grain, \saw_grain]),
\d, 0.25,
\m, PLseq([60, 60, 60, 62]),
\fxo, PLseq([0, 0, 1, 2]),
// echo introduces delay, so do delay if no echo
\lag, Pfunc { |e| e.fxo.asArray.includes(1).if { 0 }{ 0.2 } },
\a, 0.1,
\att, 0.01,
\rel, 0.1,
\cd, Pkey(\att)+ Pkey(\rel) + 0.001
);
PLbindef(\echo,
\fx, \echo,
\dta, 0.06,
\a, 0.5,
\dec, Pwhite(0.3, 1.8),
\cd, Pkey(\dec)
);
PLbindef(\wah,
\fx, \wah,
\cf, Pwhite(1, 3),
\a, 0.5,
\cd, 0.01
);
p = PbindFx(*k.collect(PLbindef(_))); // PbindFx(*(k.collect { |x| PLbindef(x) }));
q = p.play;
)
// manipulate midinotes
~q.m = ~q.m + PLseq([0, 12, -12])
~q.m = ~q.m + PLrand([0, [0, -4]])
~q.m = ~q.m + PLrand([0, [0, -7]])
// rhythm
~q.d = PLshufn([1, 1, 2, 1] / 8)
// echo param and fx order sequence
~echo.dta = Pwhite(0.03, 0.08)
~q.fxo = PLseq([0, 0, 1, 2, 1, [1, 2]])
~q.m = 48
// produce overtone series with echodelta
~echo.dta = 1 / 24.midicps / PLseq((1..16))
// this also works in chords ("fx expansion")
// source is processed twice per event
~echo.dta = 1 / [24, 26.7].midicps / PLseq((1..16))
// cleanup
q.stop
k.do { |i| PLbindef(i).clear }