Please help with this easy task

why this code outputs
The preceding error dump is for ERROR: Primitive ‘_BasicNew’ failed.
Index not an Integer
RECEIVER: Array
SynthDef(\m, {
|freq = 440, sins = 2|
SinOsc.ar(freq, mul: (1/sins))!(sins);
}).add

You can’t multichannel expand with a control, so
!(sins) will not work. Sorry, I’m typing on my phone.
What are you trying to do exactly?

i just want to evaluate a function sins number of times and get array of ugens

here is a really basic additive synthesis approach:


(
SynthDef(\simpleAdditive, {
	
	var numPartials = 64;
	var partials = (1..numPartials);
	
	var inharmonicity = (1 + (partials * partials * \inharmonicity.kr(0))).sqrt;
	var tilt = (log2(partials) * \tilt.kr(-3)).dbamp;
	
	var freqs = \freq.kr(110) * partials * inharmonicity;
	
	var sig = SinOsc.ar(freqs, { Rand(0, 2pi) } ! numPartials);
	
	sig = (sig * tilt).sum;
	
	sig = sig * \amp.kr(-15.dbamp);
	
	sig = Pan2.ar(sig, \pan.kr(0));
	Out.ar(\out.kr(0), sig);
}).add;
)

x = Synth(\simpleAdditive);

x.set(\inharmonicity, 0.005);
x.free;

as @mjsyts has been saying you cannot use an argument for changing the number of partials you are initially defining in the SynthDef. they are fixed with SynthDef evaluation.

But, why? even in this example it would be handy to change number of partials via argument

synthdef has args, its just intuitive you can use dup with argument

because the SynthDef graph is fixed with SynthDef evaluation. By changing numPartials you are creating more or less instances of SinOscs which are changing the SynthDef graph. I think someone else can explain this way better then me, but here is a way to filter out the partials (move the Mouse from left to right to go from 100 hz to 8000 hz):

(
SynthDef(\additiveLPF, {
	var cutoff, inharmonicity, tilt, lpf;
	var sig, freqs, numPartials, partials;

	numPartials = 64;
	partials = (1..numPartials);

	// harmonic tension
	inharmonicity = (1 + (partials * partials * \inharmonicity.kr(0.01))).sqrt;

	// frequency spectrum
	freqs = \freq.kr(100) * partials * inharmonicity;
	sig = SinOsc.ar(freqs, { Rand(0, 2pi) } ! numPartials);

	// 3db/octave spectral tilt
	tilt = (log2(partials) * \tilt.kr(-3)).dbamp;

	// LPF
	cutoff = MouseX.kr(100, 8000);
	lpf = ((log2(freqs) - log2(cutoff)) * \lpfSlope.kr(-12)).min(0).dbamp;

	sig = (sig * tilt * lpf).sum;

	sig = sig * \amp.kr(-35.dbamp);
	
	sig = Pan2.ar(sig, \pan.kr(0));

	Out.ar(\out.kr(0), sig);
}).add;
)

s.freqscope;

x = Synth(\additiveLPF);
x.free;
1 Like

that makes sense, i think there always was workaround about that, but i thought i could do it in synthdef, i tried to make default detuned synth with dup, now i just cant imagine how to change number of voices, i will look on sccode and inspect

No, it has controls. The fact that they are written like function arguments is a rather confusing shortcut.

Think of them more like buses but rather than using a bufnum to identify the value, you use a Symbol.

One way around this is to write a function that creates synthdefs, but the you have a synthdef for each unique number of voices.

Within one SynthDef, you cannot add or destroy voices dynamically. This has never been supported in SC3, and never will be. This is what “fixed graph” means – once you build a SynthDef, its structure is set in stone and you can’t make it bigger or smaller.

You can build a new def, and replace the Synth node (but there may be some discontinuity in the output).

You can make a SynthDef for one voice, and dynamically create and destroy Synth nodes, one for each voice (but phase correlation is not guaranteed).

dietcv’s “lpf” solution keeps the same number of voices continuously, but silences some of them. All the voices exist (nothing is created or destroyed on the fly), but you can dynamically mute them.

hjh

Btw: Pure Data and Max/MSP both have similar restrictions on dynamic creation and destruction of voices.

Pd has [clone]; MSP has [poly~]. Both of these create n copies of a saved patch. To change n, you have to rebuild the object (which will interrupt any voices that are currently playing). You can switch voices’ CPU usage on and off (like adding and removing Synths in SC) but if you didn’t create enough voices initially, you can’t fix it without an audible glitch. (Here, SC’s Synth node model is more flexible.)

Recent MSP has multichannel audio objects (and this is coming in Pd). You can send a message to an “mc.” object to change its number of channels but, according to documentation, this will not take effect until you switch the audio engine off and on again! So this is somewhat short of transparently expanding or contracting the audio graph.

It sounds like it should be handy and easy to do (to change the graph size by a synth argument), but it’s actually very hard; even Cycling 74, with full-time paid developers, didn’t try to make that work.

hjh

1 Like

Damn this is very interesting, im not even was aware you can do something like negative log2 of ratios to decrease volume, oh now i understand per octave i just read that, thats smart

@nathan has a video about this “subtractive approach” to additive synthesis which you would find in razor: https://www.youtube.com/watch?v=C2C0nqtIHRg