Hi everyone -
I’ve been haunting the forum the past couple of weeks with a few questions about envelopes. I thought I understood them much better than I apparently do and I appreciate everyone’s time in helping me get a few of the nuances under control. It encompasses a number of subjects that I’ve been a little weak on, so it’s been a great amount of learning.
In any event, I’ve arrived at what I think is the final bit of code for this project. I’ve tried to boil this down several times and I think this might be the most concise description:
I have a tone with an envelope that is tied to a window opening.
When I open the window, I would primarily like the tone to fade in and sustain itself at a releaseNode, unless otherwise specified. At other times, I will want to supply a alternate envelope that does not sustain.
While the window is open, I would like the option of “triggering” the envelope - clicking a button and having the envelope play from beginning to end - but I would also like the act of closing the window to trigger a “release”, accompanied by a doneAction, and presumably a gateOff.
This is a pretty convoluted process - and I’m not sure there is a way to do it as simply as I’ve laid out below. I can imagine an alternate path with switchable envelopes and/or multiple SynthDefs - and I’ll take that route, if the consensus is that the attached approach is goofy - but I am just trying to bear down on some concepts instead of relying on workarounds. Let me know! Thanks for all help.
(
var win, envel, envView, skew1=1, skew2=1, envTimeBasis=1, gateButton;
win = Window("", Rect(100, 100, 200, 200)).front;
win.onClose_({
//this is a 5 second fadeout to test before attempting to graft the drawn envelope.
//it seems to produce a "burst" effect", so be wary.
x.set(Env([0.5, 0.5, 0], [0, 10], [1, -1]));
x.set(\gate, 0);
x.set(\dAction, 2);
});
SynthDef("r", {|gate=1, dAction = 0|
var env, envSig, envArray;
var sig = SinOsc.ar(400, 0.1);
envArray = Env(
[0, 0.1, 1, 0.1, 0],
[0.1, 0.1, 0.1, 0.1],
[1, 1.neg, 1, 1.neg], 1);
env = \env.kr(envArray);
envSig = EnvGen.kr(env, gate, doneAction: dAction);
sig = sig * envSig;
Out.ar(0, sig);
}).add;
x = Synth("r", [\gate, 1]);
//in theory, i would like this to function as a "trigger" button - but i'm not sure what the best way of writing that would be, since i want to use both functionalities.
gateButton = Button(win, Rect(10, 150))
.states_([["gate on", Color.rand, Color.rand], ["gate off", Color.rand, Color.rand]])
.action_({|v|
if (v.value == 0){
x.set(\env, envView);
x.set(\gate, 1);
}
{
x.set(\env, envView);
x.set(\gate, 0);}
///gate off seems to play a reverse of the envelope?
});
//default values
envView = Env([0, 0.5, 1, 0.5, 0], [0.25, 0.25, 0.25, 0.25], [2, -2, 2, -2]);
envel = EnvelopeView(win, Rect(50, 50, 100, 100))
.keepHorizontalOrder_(true)
.drawLines_(true)
.selectionColor_(Color.red)
.drawRects_(true)
.resize_(5)
.step_(0.005)
.setEnv(envView)
.action_({
envel.value.postln;
envView = Env(envel.value[1], envel.value[0].differentiate.drop(1)*envTimeBasis,[skew1, skew2.neg, skew2, skew1.neg] );
x.set(\env, envView);
});
)