Dynamic Triggers

Hello. Im searching for a way to send a trigger but be able to emphasize how strong the trigger is. So a trigger with a 2.0 value would be louder than a trigger of 0.5. However the trigger of 0.5 shouldn’t overwrite the previous amplitude, but rather catapult the amplitude by a certain amount upwards and slowly decaying with a certain release time towards zero. Maybe also with a loudness cap.
Im not exactly sure how implement this. I guess maybe something similiar to a Compander.ar that takes Impulses (like Triggers) as control or some steadily decreasing function that can be added values.
I’ve written an example as a further explanation, however this example is obviously flawed and i explain it within the comment.

(


SynthDef(\test_sin,{
	var sig, e, tr;
	tr = \t_gate.kr(1);
	e = EnvGen.kr(Env.perc(\atk.kr(0.01),\rel.kr(1)),gate:tr);
	sig = SinOsc.ar(\freq.kr(440))!2;
	/*
	the next line would set the amp
	of the envelope, however when a
	trigger of a higher amplitude
	wouldve been set at the same time
	the lower amp trigger would overwrite
	the Latch. this behavior is not wanted
	*/
	sig = sig * Latch.kr(tr,tr);


	Out.ar(\out.kr(0),sig*e*\amp.kr(1));
}).add;

Pmono(\test_sin,
	\gate, Pseq([1,0.35],inf),
	\amp, 0.8,
	\dur, 1,
).play;
)

Does anybody know if there is a solution to this problem or has an idea?
Thank you very much!!

You’d want a Decay ugen: Decay | SuperCollider 3.12.2 Help

Decay has zero attack. Decay2 is one way of getting a slower attack, but the parameters behave sort of unintuitively/unmusically in my book, so I prefer the combination of Decay and then a .lag or .lagud.

1 Like

Oh I see, Decay is as an integrator. Yes that makes sense and works very well. Thank you very much.
I’ve created an example solution where i send 2 triggers with an amplitude of 0.5 immediately after each other which behave the same as a single trigger of amplitude 1. So for completion reasons i just add the example:

(
SynthDef(\test_sin,{
	var sig, e, tr;
	tr = \t_gate.kr(1);
	e = Decay.kr(tr,1);
	sig = SinOsc.ar(\freq.kr(440))!2;

	Out.ar(\out.kr(0),sig*e*\amp.kr(1));
}).add;

Pmono(\test_sin,
	\gate, Pseq([1,0.5,0.5,0.5],inf),
	\amp, 0.8,
	\dur, Pseq([1,0.001,0.999,1],inf),
).play;
)

Unrelated… But (I’m pretty sure, away from pc so can’t test) when you have a trigger rate control you don’t need the \t_ bit (unless doing args as controls), you can instead use \gate.tr.

That’s correct – checked this morning – there are 3 ways to make a trigger control:

  • t_gate in a SynthDef function arg list.
  • \t_gate.kr in the SynthDef body. (I was surprised that “symbol.kr” uses the rate prefix.)
  • \gate.tr in the SynthDef body.

When setting the value in a Synth() or set() arg array, the t_gate versions should be written t_gate but in patterns, it should be just gate (though “gate” is not normally sent, see msgFuncKeepGate). Dropping the prefix in patterns/events is a bit weird, making it one of the reasons why some have recommended against SynthDef function arg lists completely. (For triggers, I tend to agree with that, though for normal controls, I still use the arg list.)

The gate.tr version would be addressed as gate everywhere, which sidesteps the t_ weirdness.

hjh

1 Like

Actually when reconsidering the problem:
I think it would be interesting to have the option to cap the integration part of being only able to integrate up to a certain value. So that the Maximum input of the Decay (or maximum value from which to decay from) could be fixed and for example only reach a value of 1. Sure one can clip the decay but it would delay the decay.

I mean its not super important but if anyone has an Idea, I’m glad to hear.

Once again to clarify I show the problem in Code, 3 triggers are sent at (approximately) the same time, but im looking for a fix to make the sound be the same in the following example:

(
SynthDef(\test_sin,{
	var sig, e, tr;
	tr = \t_gate.kr(1);
	e = Decay.kr(tr,1).poll.clip(0,1);
	sig = SinOsc.ar(\freq.kr(440))!2;

	Out.ar(\out.kr(0),sig*e*\amp.kr(1));
}).add;

Pmono(\test_sin,
	\gate, Pseq([1,1,1,1],inf),
	\amp, 0.8,
	\dur, Pseq([1,0.001,0.001,0.001,0.997],inf),
).play;
)