DoneAction for "ringing" UGens (Klank, Pluck, etc.)

Hello! I have a simple question – what is the best way to achieve doneAction:2 for UGens that “ring out,” such as Klank, Pluck, etc.? The actual envelope of the synth comes from the decay times of Klank, not an EnvGen.

I’m able to get “freeSelf” by using an Env that is longer than the Klank decay times but isn’t actually in the signal path. This works well but it feels a little hacky. Is there a better way to do this?

(\klankB, {
	var env, exciter, sig;

	// env is only used to free self:
	env =[1, 1, 0], [6, 1]), doneAction:2);

	exciter =, 0.03,;
	sig =`[\[800, 1071, 1400, 1650]), nil, [5, 2, 3, 1]], exciter);\, (sig * \;

I would use DetectSilence !

I always add a second envelope that is decayTime longer than the one we are hearing. It might not even need to be multiplied by the sound. That envelope has the doneAction. The one you already has, does not.


I’ve used it in the past exactly for this, but one needs to reconsider their Ugens once the release time (and inter-“event” time) gets below 10ms or so, because DetectSilence can become unreliable in those circumstances, in my (limited) experience, even with tuning DetectSilence.time which defaults to 100ms.

Hi Sam – I’m confused. It sounds like my example code does exactly what you described. The variable “env” is not in the signal path (not multiplied by the audio signal) – it is longer than the audible envelope and has the DoneAction.

Oh. Sorry. Yeah, hacky, but correct. I would also have an env over the sound that does not release, but that is just me.

The DetectSilence solution suggestion also works, but not if there might be silence before all is done, like if the sound is triggered multiple times.


Yes, this is a problem more often encountered if your synth is multi-channel and the decay/release times are not the same for each channel. You need to “or” the channels before you detect silence in that case. If your synth really produces “internal” pauses, i.e. can resume sound on the same channel, that may be a good reason reconsider its architecture, i.e. does it have to be a “mega synth” like that, or can you use the Even system to get the pauses (and have a simpler synth). I’ve actually used “mega synths” for quite a while with Dseq etc. but I found they can be more cumbersome to debug than client-side (sclang) “chunking” into Events.

Very cool. I love finding new super-useful UGens. Thanks Geoffroy!