Envelope retriggering in a single Synth instance

I’m a beginner in SC. Using the below SynthDef as an example, what are some ways to trigger the envelope in a predefined rhythmic way while maintaining the RLPF modulation, i.e. only creating once instance of the synth?

I would like to make just general percussion sequences. So far with patterns, particularly Pbind and Pseq, I find that they make a new instance of the Synth every time, cutting off the modulation progress and starting over.

(
SynthDef(\simple, {
var src, env;
src = WhiteNoise.ar(0.2);
src = RLPF.ar(src,SinOsc.kr(0.1,mul:400,add:600));
env = EnvGen.ar(Env([0,1,0],[0.1,0.3]));
src = src * env;
Out.ar(0,src!2);
}).add;
)

When I imagine what I’d like to create in SuperCollider, I imagine lots of modulation using UGens. I’m just stuck on this step of how to feed rhythmic 1’s and 0’s into a single Synth instance.

Thanks

There are several ways of doing this, but it sounds like you want to use patterns?
In that case you should have a look at Pmono, it is used to change the arguments of a single synth instance over time

Here’s an example

(
s.waitForBoot({
	var pattern;
	var player;

	SynthDef(\simple, {
		| out=0, mygate |
		var env, sig;
		sig = WhiteNoise.ar(0.2);
		sig = RLPF.ar(sig,SinOsc.kr(0.1,mul:400,add:600));
		env = EnvGen.ar(Env([0, 0, 1,0],[0, 0.1, 0.3]), gate:mygate, doneAction:Done.none);
		sig = sig * env;
		Out.ar(out,sig!2);
	}).add;

	s.sync;

	pattern = Pmono(\simple,
		\mygate, Pseq([1, 0], inf).trace,
		\dur, Pseq([0.25, 0.5, 0.25], inf),
	);

	player = pattern.play;
});
)

Some caveats:

  • if you name the SynthDef/Pmono argument “gate” instead of “mygate” it won’t work (and I don’t understand myself why - I suspect there’s some special handling of an argument with name “gate” inside the Pmono class but I’d have to dig deeper to find out.). “mygate” is a name I made up on the spot, you can choose your own instead.

  • when retriggering an envelope, the first segment is not repeated as it is considered an “initial value” only output at the very first trigger (see documentation for Env). So I’ve added an extra segment in front.

  • FYI (in case you didn’t know yet :slight_smile: ): you can use “.trace” to show the output of patterns in the post window while it’s being generated; to see what is ongoing inside the SynthDef (i.e. on the server) you can print the output of UGens to the post window using “.poll” instead.

I’ll have a look at that, thanks!

Legend! Thank you so much, it’s working well, but I guess you knew that :slight_smile:

So now I’m using a pattern to determine the values of the ‘gate’ arg in the EnvGen in the SynthDef. However, this takes two beats to do, so if I want to use patterns to control, say, the frequency of the oscillator, I put any value (here 0) in between the values I actually want the synth to play. This makes it a bit confusing so I wonder if there are alternatives. Sending the 1’s and 0’s from a pattern through a control bus maybe? I’m not sure how to implement that. Help is appreciated.

(
SynthDef(\simple, {|out=0, hertz, mygate|
var env, sig;
sig = SinOsc.ar(hertz,mul:0.2);
env = EnvGen.ar(Env([0,0,1,0],[0,0.1,0.1]), gate:mygate);
sig = sig * env;
Out.ar(0,sig!2);
}).add;
)

(
~pattern = Pmono(\simple,
\mygate, Pseq([1,0], inf),
\dur, Pn(0.5, inf),
\hertz, Pseq([400, 0, 500, 0, 600, 0], inf),
);
)

~pattern.play;

Could you check my recent reply under this post?

Could you check my recent reply under this post? I’m not sure how to tag people.

You can tag people by typing the @ sign and then selecting a name from a popup menu.

There’s a special convention in supercollider where synth argument names that start with t_ have the effect of autonomously going to 0 even if you don’t explicitly ask them to do so. (I assume that t_ stands for trigger?). More technically, argument names starting with t_ are turned into a TrigControl.

Here’s my example rewritten with a trigger argument. Note that this time I can just send a stream of 1 into the t_mygate argument, and because of the t_ it will still act as a trigger, which I’ve visualized by adding a .poll in the SynthDef.

(
s.waitForBoot({
	var pattern;
	var player;

	SynthDef(\simple, {
		| out=0, t_mygate |
		var env, sig;
		sig = WhiteNoise.ar(0.2);
		sig = RLPF.ar(sig,SinOsc.kr(0.1,mul:400,add:600));
		env = EnvGen.ar(Env([0, 0, 1,0],[0, 0.1, 0.3]), gate:t_mygate.poll, doneAction:Done.none);
		sig = sig * env;
		Out.ar(out,sig!2);
	}).add;

	s.sync;

	pattern = Pmono(\simple,
		\mygate, Pseq([1], inf),
		\dur, Pseq([0.25, 0.5, 0.25], inf),
	);

	player = pattern.play;
});
)

You can read some more about this t_ and other stuff in the helpfile for SynthDef, in the section about UGen Graph Functions and Special Argument Forms.

Thanks, this is very helpful.
I found that for some reason I had to replace t_mygate with t_trig, only then did it work.
Again, thanks!

Or you can use the named control style and write \trig.tr

1 Like