No, nothing in the env that IEnvGen loads is modulatable thereafter. Everything is treated as ir
. So it’s even less flexible than the regular EnvGen in that regard. You can of course time-warp via the index in IEnvGen and externally modulate/map the levels it returns so something else. But basically none of the envelope classes in SC are any good for “change this right now” unless the segments are short and the evenlopes are replayed/retriggered or cycled using the loop node. Otherwise it’s more or less doing a “custom envelope” using Select among various Sweeps, pretty much like in vitreo’s solution. It’s a also a bit tricky to chain the triggers from on Sweep to the next. If you need a cycling envelope of this kind LocalIn and LocalOut can be used to pass the final segment trigger back to the first. A semi-custom envelope that I wrote that’s simple enough to demonstrate the bag of tricks is this two-segment one, which is just ramp and a hold. It seems like no big deal, until you consider what could or should happen in the current segment when the parameters change.
(Ndef(\ei, { arg t_go = 0, a1 = 0.2, a2 = 0.95, t2 = 8, t3 = 3;
var slope = (a2 - a1) / t2;
var swar = Sweep.kr(t_go + LocalIn.kr(1, 0), slope).clip(a1, a2);
var idse = (swar >= a2); // index for select
var tcon = Sweep.kr(idse); // time elapsed at "constant" amp hold
LocalOut.kr(idse * HPZ1.kr(tcon >= t3) > 0); // no trigs if in ramp-up seg
// added a bit of tremolo to hold segment so it's visible that it's not stuck
Select.kr(idse, [swar, SinOsc.kr(10, 0, 0.05, a2)]);
}))
Basically, the intent here is that when t2 is changed up or down, the slope in the ramp changes right now and implicitly the time left in the ramp, but it’s never a sudden jump. Conceptually the current time is considered as a fraction of t2 and that fraction is seamlessly used with the new t2. And likewise when the amplitude a2 is changed up that causes the ramp to go faster, although it may abruptly cut down the current amplitude if exceeds the valued a2 is changed to. Whereas in the hold segment, changing t3 downwards does do a cut-out of the segment, causing the whole envelope to re-cycle.
This code actually shows some semantic problems when changing the parameters of an envelope segment as it runs: e.g. what should happen when the end time is lowered below the time that has already elapsed? Just cut out or change the slope so that the end level (amplitude) is reached faster? It really depends on what you want for that particular knob, so that’s why probably there’s no such implementation in the SC library.
It’s also a bit tricky to make sure the external trigger t_go
does the right thing regardless in which segment the envelope is at. Basically some internal triggers need to be disabled when an external one happened already. Code like this gets hairy fast. It’s really more like making a circuit than (sequential) code. In my original code there was also a t1 that did something else, but I’ve removed it here for simplicity. Also the sudden downward changes of a2 are here as such for demonstration purposes. I actually use a LagUD with a larger down than up constant to smooth those too a little bit.