Embarrassing newb question

They are an alternative to declaring args at the top of the function. You can search for namedcontrols in the help files to read more. This style of declaring args has some benefits over the normal way - not so much in this case, but when you use arrays of values in a synthdef.

Here is the same synthdef written with normal style arg-declarations. Notice also that I am using the shorter syntactic alternative to EnvGen.kr(Env…) in both cases.

(
SynthDef(\blips,{ arg trigrate = 12, loT = 0.05, hiT = 0.1, atk = 0.1, rel = 1, gate = 1, amp = 1, rate = 10;
	var sig, tig, mulenv, env;
	tig = Dust.kr(trigrate);
	mulenv = Env.perc(0.01, TRand.kr(loT, hiT, tig)).kr(gate:tig);
	sig = SinOsc.ar(LFNoise0.kr(rate).range(400,2000)) * mulenv;
	env = Env.asr(atk, 1, rel).kr(2, gate);
	Out.ar(0, sig!2 * 0.3 * env * amp);
}).add;
)

Im still far to new to really know the befits of one style over the other but did I find namedcontrols had an ease when it came to reading the code.

FWIW, when I use this style of control-input declaration for arrays, I usually write out NamedControl.kr(\name, value) precisely because \name.kr is not self-documenting i.e. likely to confuse new users. Pedantic? Maybe… but good for readability, especially since I declare inputs at the top instead of interpersing them throughout the SynthDef body. (I also use function args for “normal” – single-value control-rate – inputs.)

I also try to be consistent, when writing about SC, to refer to synth inputs as “inputs” or “control inputs” and not “args” – because they’re different from function args.

hjh

1 Like

Don’t be. I’ve learned a lot from questions that I’ve asked and that others have asked. Often what seems easy/simple to one person is also not at all obvious to another. And if the question really is easy then someone will have the thirty seconds required to answer it.

2 Likes

ok then here goes…haha
I know that mul and add are super important. I able to understand how mul works as an amplitude multiplier for on signals. And I can see how add can offset a sig on a scope… but I am little unclear as to why you would need to offset… would love to get how to use add unpacked a bit.

Here’s another opinionated but IMO helpful thread from @nathan on this topic:

In general, audio signals should not be offset – DC is bad for speakers.

Control signals may have an arbitrary range, however, which need not be centered on 0. In that case, an offset may be necessary (whether you write it with add or +).

(FWIW I hardly ever use mul/add at all anymore.)

hjh

In general, adding a constant to a signal can be useful when applying distortion (I think it makes odd harmonics?).
Something like this…

var snd = ...;
snd = snd + 0.5; // offset
snd = snd.tanh; // non-linear process (waveshaping)
snd = snd - 0.5; // reset offset

But you probably shouldn’t use the mul and add arguments in the UGens, they are remnants of an old optimisation.

tanh on its own makes odd harmonics: a sine wave (before) becomes more like a square wave after. I think an offset before distortion makes the resulting “square” wave more like a pulse wave where pulse width != 0.5.

“Shouldn’t” may be a bit strong; I’d say certainly there’s no good reason to prefer mul/add over math operators, and probably some good reasons to prefer the math operators – but people can do as they like.

hjh

It’s interesting to see that recently, more and more people are attempting to establish a uniform coding style in SuperCollider. I don’t recall this happening before. Even in small stylistic details like this.

Interesting so are you primarily only scaling your signals down at that the output…

This is fine, as long as I am the one deciding what that uniform style will be :wink:

Tongue in cheek there. Everyone has different priorities. For me, “no mul/add” barely makes the list at all, while inconsistent indentation and spacing concretely make it harder to read code and help with questions here, so I more often remark on that. I personally am not at all a fan of \symbol.kr inline synth input definition, but I know some people like it very much, so I keep my mouth shut (though, if that ever became part of a strongly encouraged or enforced coding style, then I wouldn’t keep quiet). And so on… try to strike a friendly balance.

hjh

Yes, I know some extreme cases that the person recreates the syntax, changing all operators for functions application and composition. But he also writes “I don’t realistically expect anyone to use it”. But it’s out there, some people use it probably.

That’s actually fun and healthy, the community discuss and see alternatives.

still learning and and wanted to create a simple
synth that has random decay values. here is what I was thinking it would map out like.


and here is the code I was trying

(
SynthDef(\test,{
	var sig, env, trig, rand;
	trig = Dust.kr(12);
	rand = Trig.ar(trig,exprand (0.01, 2));  // this line is not the ticket 
	env  = EnvGen.ar(Env.perc(0.001,rand), gate: trig,doneAction:0);
	sig  = SinOsc.ar(mul:env);
	Out.ar(0,sig!2 * 0.1);
}).play;
)

please advise… its something like re-using dust in the perc release value but with a range ?

exprand is language side only. Its result will be hardcoded into the synth and not change.

TExpRand.kr(0.01, 0.2, trig) is what you wanted.

hjh

def closer but for some reason I was expecting more a mix for very short sounds with little to 0 decay…

(
SynthDef(\test,{
	var sig, env, trig, rand;
	trig = Dust.kr(6);
	rand = Trig.ar(trig,ExpRand(0,1)); //needs to be on a control buss?
	env  = EnvGen.ar(Env.new([0,1,0],[0.01,rand]), gate: trig,doneAction:0);
	sig  = SinOsc.ar(mul:env);
	Out.ar(0,sig!2 * 0.1);
}).play;
)

Trig isn’t the UGen that you want for this case, not in any way. Trig takes a trigger value and extends it in time (making a gate out of it). It is not sample-and-hold, and not “perform the op upon trigger.”

See my post earlier today. TExpRand.

(The other issue there is that ExpRand, by design, grabs one random value at the start of the synth, and then never changes. It will be different between synth instances but only one value per synth. That’s why you’re not hearing variation. If you want a sequence of random values following a trigger, that is “triggered ExpRand” = TExpRand.)

hjh

1 Like

ah got it ! thank you
excited to mess with TExpRand

I only said that from a desire to decrease the amount of stuff new users have to learn, and to make sure the things they do learn are the simplest, most valuable, and don’t have any weird surprises hidden in them.

There are 20+ years of different approaches in supercollider, supporting all of these approaches is great and helps preserve art and keep users across decades, requiring new users to learn all of these isn’t.

My dream is for a majority of people to agree on what this smaller, more concise subset of supercollider might be, so that all the docs and tutorial can be rewritten in a similar style, reducing the ‘steepness’ and ‘length’ of the learning curve that turns away many.


There is also this chunk of code in SCDocHTMLRenderer that hides the mul and add arguments, but only when the help file doesn’t explicitly mention them with the argument tag.

// ignore trailing mul add arguments
if(currentMethod.notNil) {
	currentNArgs = currentMethod.argNames.size;
	if(currentNArgs > 2
	and: {currentMethod.argNames[currentNArgs-1] == \add}
	and: {currentMethod.argNames[currentNArgs-2] == \mul}) {
		currentNArgs = currentNArgs - 2;
	}
} {
	currentNArgs = 0;
};
2 Likes

Isn’t that more or less the case? I would need to know how strict and how much personal room your dream would bring. (maybe give examples to clarify?) It’s a balance.