Skip retriggering with incomplete release?

Is there an elegant or recommended way to ignore a trigger/gate signal when a monophonic envelope’s release phase has not finished? I want to wait to reach the final before it is “ready” to receive more triggers/gates.

I managed to wire something up with LocalIn/LocalOut and a DetectSilence on the envelope itself, but it felt hacky and the delay introduced by the local bus caused timing problems.

Just confirming, is it a gated envelope?

If you know the duration that the envelope should be closed to new triggers, you can measure the time using, 1) (or .ar) – if it’s a gated envelope, then the timer should start when releasing, so <= 0, 1).

So the “gate mask” would be:

  • Triggered envelope:, 1) > totalEnvDuration;
  • Gated envelope: <= 0, 1) > releaseDuration.

But you’ll need another condition for the first one, so I guess it’ll be like this (untested), for a trigger:

// in the SynthDef
arg ......., t_trig, ......;
var trigMask = (( < 0) + (, 1) > totalDur)) > 0,
eg =, t_trig * trigMask, ...);

+ is a logical-or here, and * is logical-and: the trigger will be passed (“and true”) if it’s never been triggered before or enough time has passed, and suppressed (“and false”) otherwise.

That’s a good way to do it. LocalIn/Out delay should be on the order of 1.5 ms only. I’d expect DetectSilence to be too slow for this purpose: why not just eg <= 0?


1 Like

In case the env is not gated and its duration is known (james’ first case), there is also a simple implementation with Trig1:

    // Trig1 ignores subsequent trigs for envDur secs after each trig
    var trig =\,envDur);, trig, timeScale:envDur);
1 Like

I tried the simpler one first and it worked beautifully. Thank you both!

Ah, I didn’t realize DetectSilence might be what was slowing things down. I tried something along the lines of the eg <= 0 you mentioned, but I got an error about using a Boolean in a Synth.

FYI, for my purposes, it didn’t matter whether it was gated. I could have gone either way.

eg <= 0 gives you a signal that is 1 when the envelope is off, and 0 when it’s active.

You want triggers to be suppressed when the envelope is active.

So, trig * ( <= 0) means… envelope not active, triggers OK, trig * 1… envelope active, triggers not OK, trig * 0. if is not needed (and shouldn’t be used) here.


1 Like
SynthDef(\trig_eg, { |out, t_trig, time = 4, freq = 440, amp = 0.1|
	var sig = * amp,
	feedbackEg =,
	maskedTrig = t_trig * (feedbackEg <= 0),
	eg =, 0.99), maskedTrig, timeScale: time);;
	t_trig.poll(t_trig * (maskedTrig <= 0), "trigger rejected");, (sig * eg).dup);

a = Synth(\trig_eg);
a.set(\t_trig, 1);  // first should play

a.set(\t_trig, 1);  // second, while note is sounding
trigger rejected: 1

a.set(\t_trig, 1);  // third, when silent, no problem