doneAction code 2 here means exactly “free this synth when this envelop is done playing”. So, just change the doneAction on the shorter envelop to Done.none (code 0). There are semantically named constants for doneActions defined on the Done class, read that documentation for more information. Rewritten using them, your code would look like:
(
SynthDef(\perc1, {
arg out=0, pan=0, atkTimbr=0.001, relTimbr=0.2, levTimbr=0.5, atkTom=0.01, relTom=1, levTom=0.5, amp = 0.3;
var envTom, envTimbr, sigTimbr, sigTom, sig;
envTom = EnvGen.kr(Env.perc(attackTime:atkTom, releaseTime:relTom, level:levTom, curve:-4), doneAction: Done.freeSelf);
envTimbr = EnvGen.kr(Env.perc(attackTime:atkTimbr, releaseTime:relTimbr, level:levTimbr, curve:-4), doneAction: Done.none /* or leave this argument blank, as 0 is the default */);
sigTom = SinOsc.ar(100)*envTom;
sigTimbr = WhiteNoise.ar()*envTimbr;
sig = Mix.ar([sigTom + sigTimbr]);
Out.ar(out, Pan2.ar(sig, pan, amp));
}).add;
)
While there’s nothing really wrong with combining two sounds in one SynthDef you might think over the alternative of doing this via two different SynthDefs. Modularization has its benefits and you are more flexible in sequencing.