two sclang features that i don’t recommend using: mul
/add
arguments, and the Mix
class.
SinOsc.ar(440, 0, 0.1)
and SinOsc.ar(440) * 0.1
do the same thing, but the latter is far more readable. you don’t have to know the argument list of SinOsc.ar
to be able to tell what the 0.1
is doing. * 0.1
is how you multiply by 0.1
anywhere else in sclang.
Mix(array)
and array.sum
do the same thing, but array.sum
is more sclang idiomatic, and Mix
confuses you into thinking it’s a UGen (which it is not — check the source code).
both of these are historical artifacts of a less smart synthdef optimizer. the mul
and add
arguments of ugen classes compile to MulAdd
ugens (via the .madd
method), which used to be faster than the BinaryOpUGens +
and *
. however, now the SynthDef compiler is much smarter and is capable of optimizing a * b + c
into MulAdd(a, b, c)
. many newer ugens don’t even have mul
/add
arguments.
similarly, Mix
is intended to optimize a sum into a tree of Sum3
, Sum4
, and +
ugens. however, now writing a + b + c + d
is optimized to Sum4(a, b, c, d)
, and the efficiency benefits of Mix
are no longer relevant.
there are no current plans to deprecate either one, but i advise against using them. they are both remnants of older versions of SC, and all they do now is offer additional, unnecessary ways to do things.
i get that mul
and add
arguments in particular are a tough habit to kick, since they’re introduced in literally day 1 of SC, but i have faith that we all can collectively reach BinaryOpUGen nirvana.
EDIT: more reasons not to use mul/add
thinking about this more, i have just recently discovered another, more compelling reason to avoid mul
and add
. their behavior on multichannel expansion is inconsistent with other parameters when dealing with nondeterministic ugens. a demonstration:
{ LFNoise0.ar(freq: [100, 100], mul: 1) }.plot(0.2);
{ LFNoise0.ar(freq: 100, mul: [1, 1]) }.plot(0.2);
why does the first line of code generate two different random signals, but the second one the same signal duplicated? because internally, this is happening:
{ LFNoise0.multiNew(\audio, [100, 100]) * 1 }.plot(0.2);
{ LFNoise0.multiNew(\audio, 100) * [1, 1] }.plot(0.2);
in the first line, LFNoise0.multiNew
is multichannel-expanding and generating two different copies of LFNoise0
. but in the second line, the multichannel expansion happens in the madd
stage, and the same copy is being multiplied by 1 twice. in this way, mul/add parameters are “special”. or in other words, inconsistent and confusing.
another problem that’s more of a developer concern than a user concern is that, since mul
and add
arguments conventionally must come last, it is not possible to add new arguments to a ugen.