PbindFx with no main envelope and type \set

I’ve looked briefly at the extensive documentation for for PbindFx but I can’t tell at a glance if it can work without a main envelope and with type \set for the main Pbind and with fx Pbinds doing the actual envelopes (e.g. separate ones per channel).

Basically I’m trying to suss if I could rewrite my Pproto code from this question (for the motivation see How to get constant slope instead of constant time envelope re-attacks? ) with PbindFx instead of Pproto. I’m concerned that with no main envelope to end the PbindFx effects (which for me would be envelopes) would not get released/freed… which would be a problem as I’m generating a lot of those. There are some diagrams in the PbindFx help with the main envelope gating out seemingly being the trigger for the fxs to end…

This is a combined special demand, but afaics everything seems doable. I’m starting with envelopes as this is more straight.

To be honest I couldn’t tell at a glance too :slight_smile: but the cleanup mechanism isn’t bound to envelopes, so fxs can take over this job.

(
SynthDef(\source_no_env, { |out = 0, freq = 400,
    attackTime = 0.005, amp = 0.1, gate = 1|
    var env, sig = Saw.ar(freq, amp);
    Out.ar(out, sig ! 2)
}).add;

SynthDef(\wah_env, { |out, in, att = 0.01, rel = 0.5, resLo = 200, resHi = 5000,
    cutOffMoveFreq = 0.5, rq = 0.1, amp = 1, mix = 1|
    var sig, inSig = In.ar(in, 2), env;
    sig = RLPF.ar(
        inSig,
        LinExp.kr(LFDNoise3.kr(cutOffMoveFreq), -1, 1, resLo, resHi),
        rq,
        amp
    ).softclip;
	env = EnvGen.ar(Env.perc(att, rel, amp), doneAction: 2);
	Out.ar(out, ((1 - mix) * inSig + (sig * mix)) * env);
}).add;
)

// overlapped events with different release times

(
p = PbindFx([
        \instrument, \source_no_env,
        \dur, 0.25,
        \amp, 1,
        \midinote, Pwhite(50, 90),
        \fxOrder, 1,
        \cleanupDelay, 0
    ],[
        \fx, \wah_env,
        \mix, Pseq([0.2, 0.5, 0.7], inf),
        \cutOffMoveFreq, Pseq([1, 2, 5, 10], inf),
        \rel, Pwhite(0.1, 2),
        \amp, 0.2, 
        \cleanupDelay, Pkey(\rel)
    ]
);

q = p.play;
)

Concerning the second demand, PbindFx is using its own event type based on ‘note’. However you are not the first to ask for different event types and this can be done by routing. In your use case a router synth can read from a bus where the monophonic one is playing to.

Of course there’s a fundamental difference to the first example: no overlapping as source is monophonic. However overlappings caused by fxs (echo, reverb) would be possible also in this case.

// synth for routing
(
SynthDef(\router, { |out = 0, inBus|
    Out.ar(out, In.ar(inBus, 2))
}).add;

a = Bus.audio(s, 2);
)

(
// groups to ensure node order
g = Group.new;
h = Group.after(g);

// start silently in group g
x = Synth(\source_no_env, [amp: 0, out: a], g);
)

// play monophonic and PbindFx in parallel
// a random rhythm makes data sharing necessary


(
p = Pbind(
	\type, \set,
	\ids, x.nodeID,
	// data sharing, router should get durs from monophonic
	\dur, Prand([1, 1, 2] / 4, inf).collect(~d=_),
	\args, #[freq, amp],
	\freq, Pwhite(50, 90).midicps,
	\amp, 0.1
);

q = PbindFx([
        \instrument, \router,
        // you have to allow reading from other buses
        \otherBusArgs, #[inBus],
        \inBus, a,
        \dur, Pfunc { ~d },
        \fxOrder, 1,
        \group, h
    ],[
        \fx, \wah_env,
        \mix, Pseq([0.2, 0.5, 0.7], inf),
        \cutOffMoveFreq, Pseq([1, 2, 5, 10], inf),
        // longer release times would be longer than source
        \rel, Pwhite(0.03, Pfunc { ~d }),
        \cleanupDelay, Pkey(\rel)
    ]
);

// time shift because of data sharing
q = Ptpar([0, p, 0.0001, q]).play;
)
2 Likes