Passing variable-sized array argument to a Synth

What is the correct way of defining a Synth which takes in it’s argument a variable sized array of inputs? For instance how could I define a Synth for additive synthesis, in which the frequencies are defined as an input array, so that it’s possible to pass different sized arrays of frequencies to the Synth?

There is no direct way to do that.

You can define multiple SynthDefs for different sizes, and select them by name.

Or you can define a SynthDef with a bigger array, and set the amp of the unused partials to 0.

Or a hybrid approach would be to define a separate SynthDef for, say, 10 partials, and 20, and 30, and so on, and choose by name the smallest SynthDef that would handle the number of partials for this note, and switch off the amp for the excess partials – this way would balance the desire not to create too many SynthDefs vs the desire not to waste too many oscillators.

hjh

1 Like

you can make a function that plays a function - like so:

a = {|array| { SinOsc.ar(array, 0, array.size.reciprocal / 10)}.play };
a.([300, 400, 444, 475])
a.([666, 655, 654])
1 Like

See miSCellaneous_lib’s tutorial “Event patterns and array args” which contains examples of that kind.

2 Likes

Do you have a direct link to that specific section?

Hi @amt - just open Supercollider’s help and type “Event patterns and array args” and you’ll see a link!

1 Like

The info is all in what James said and in the file, but not tailored literally to your question as you seem to prefer frequencies to partials. But that doesn’t change the principles. Either you take a SynthDef factory (described in helpfile Ex.1 at bottom) or you make a SynthDef with a max number of freqs, in that case you’d have to pass the number of freqs you need in addition. Here’s an example:


(
SynthDef(\add, { |out = 0, freqNum = 5, amp = 0.1, gate = 1, dampen = 1|
	var maxFreqNum = 30;
	// trick: indicator is array of 0/1 at control rate
	var indicator = { |i| i < freqNum } ! maxFreqNum;
	var freqs = \freqs.kr(0 ! maxFreqNum);
	var arr = { |i|
		SinOsc.ar(
			freqs[i],
			0,
			// avoid negative values as freqs can become loud !
			1 / ((i + 1) ** dampen.abs)
		)
	} ! maxFreqNum;
	// scramble spreading in stereo field, not necessary
	var signal = Splay.ar((arr * indicator).scramble);
	Out.ar(out, signal * EnvGen.kr(Env.asr(), gate, doneAction: 2) * amp)
}).add
)




x = Synth(\add, args: [freqs: [100, 300, 710, 900, 1500], freqNum: 5])

x.set(\freqNum, 2)

x.set(\freqNum, 3)

x.set(\freqNum, 4)

x.set(\freqNum, 5)

// still 5 freqs unequal 0

x.set(\freqs, [500, 1550])

x.set(\freqNum, 2)

x.release

Of course, you could specify the amplitudes with arrays as well.

1 Like