Changing atk/rel in EnvGen within a running synth?

Hello, i was wondering if you create a synthesizer, you can .set the synth to another frequency. However this does not work for the atk, rel, dec, level or any other parameters of a EnvGen. Is there a possibility to change, lets say the atk of a running synth, and therefore make it take slower or faster to rise to the targeted level? Let me clarify this in a simple code example:

//add a synth
(
SynthDef(\env_tester,{
	arg amp=0.2,atk=10,rel=1,cur=3,freq=187.4;
	var sig;
	sig = SinOsc.ar(freq,mul:6).tanh;
	sig = sig * Env.perc(atk,rel,1,cur).ar*amp;
	Out.ar(0,sig)
}).add
)

//start synth
x = Synth(\env_tester);
//changing frequency works
x.set(\freq,93.7)
//changing a running env does not work
x.set(\atk,1)
//only works when initiatingt the env with the proper atk
x = Synth(\env_tester,[\atk,1]);

So you see I run a Synth with an atk=10 and assume after 3 seconds I change the atk to 1. Then the Envelope should continue from the current position but take proportionally less time to get to the targeted level. after 3 seconds, the level should be at 30%, therefore it should only take 0.7 seconds to get there if i set the atk to 1. When trying it, it does not do so. Is there any smart way to get to this point?

Thank you very much!!

Nodes for envelopes are only updates at the start of each segment. So in the case of Env.perc you can only change the rel segment while in the atk segment.

Check this out for inspiration though: Restart Envelopes without creating new SynthDef instance

Thank you for sending the link. This post unfortunately specifically restarts the Env from the beginning, even though it implements a way, that the env continues from the current point where it restarts.
I’m wondering if something similar would be possible but restart the env from the segment where it got changed. otherwise, if I change the release parameter, it will restart from the beginning once again.

I’m not sure I get the question right. Isn’t attack happening at the start by deffinition?

If you want to modify a parameter from one value to another at a specific rate in a running synth, I would use either Lag, .lag() or Line.

Mh, thanks for the response, but I don’t think that could be helpful.

I want to modulate the rel/atk/decay parameters for example at the same time while a note is in play. so lets say i play a note and release it but when i played it, it was at a release time of 10 seconds. now i turn a knob down to 1 second, and the same note that i released previously, now releases at 1 second.

the problem is: the node has already been released, meaning the envelope already started the release segment. therefore i cannot change the release time. Also it needs to be a continous release. meaning: if the release time at first was 10 seconds, and after 5 seconds I turn it down to 1 seconds, it changes from 50% down to 0% at a faster rate. (prefereable at 0.5 seconds, because have of the release segment was already triggered, but I’m also fine with 1 seconds, it already helps me a lot.)

mmm… have you tried with an input bus?

(
SynthDef(\env_tester,{
	var amp = \amp.kr(0.2);
        var atk = \atk.kr(10);
        var rel = \in.kr(1); // or In.kr(\in.kr(1))
        var cur = \cur.kr(3);
        var freq = \freq.kr(187.4);
	var sig;
	sig = SinOsc.ar(freq,mul:6).tanh;
	sig = sig * Env.perc(atk,rel,1,cur).ar*amp;
	Out.ar(0,sig)
}).add
)

Or maybe with DC.kr

How exactly do you mean? I don’t understand how this can be useful for me. I dont see what your code Changed?
If i run the same commands as previously, then the atk or release arguments don’t change the running segment of an envelope.


(
SynthDef(\env_tester,{
	var amp = \amp.kr(0.2);
        var atk = \atk.kr(10);
        var rel = \in.kr(1); // or In.kr(\in.kr(1))
        var cur = \cur.kr(3);
        var freq = \freq.kr(187.4);
	var sig;
	sig = SinOsc.ar(freq,mul:6).tanh;
	sig = sig * Env.perc(atk,rel,1,cur).ar*amp;
	Out.ar(0,sig)
}).add
)

//start synth
x = Synth(\env_tester,[\freq, 93.7, \atk, 10, \in, 1]);
//changing a running env does not make the atk rise faster because the segment already started.
x.set(\atk,1)

Im using this stateless window for granular / pulsar synthesis maybe its also useful for this task:

(
var statelessWindow = { |levels, times, curve, phase|
	var x = 0;
	var window = times.size.collect({ |i|
		var x2 = x + times[i];
		var result = (phase >= x) * (phase < x2) * phase.lincurve(x, x2, levels[i], levels[i+1], curve[i]);
		x = x2;
		result;
	}).sum;
	window = window * (phase < 1);
	window;
};

SynthDef(\env_tester,{
	var tFreq = \tFreq.kr(1);
	var trig = Impulse.ar(tFreq);
	var phase = Sweep.ar(trig);
	var window = statelessWindow.([0, 1, 0], [\atk.kr(0.5), \rel.kr(0.5)], [4.0, -4.0], phase);
	var sig = SinOsc.ar(\freq.kr(187.4));
	sig = (sig * \boost.kr(3).dbamp).tanh;
	sig = sig * window;
	sig = Pan2.ar(sig, \pan.kr(0), \amp.kr(0.25));
	Out.ar(\out.kr(0), sig)
}).add
)

x = Synth(\env_tester);

x.set(\atk, 0.01);
2 Likes

It was just an idea, I didn’t try the code. I meant using an input bus to modulate the attack using another node to control it, for example:

k = Bus.control(s, 1);
Synthdef(\controller, { Out.kr(\out.kr(k), DC.kr(\amt.kr(1)) }).add;
(Synthdef(\env_tester, ...).add);

x = Synth(\env_tester, [in: k]);
c = Synth(\controller);
c.set(\amt, 5);
c.set(\amt, 0.5);

But, again, I was just pointing out ideas to try. I haven’t tried it. I don’t know if this would work.