Is iteration inside a SynthDef not allowed? What does this error mean? ERROR: Non Boolean in test

I am trying to write a SynthDef that can write to multiple buffers, depending on the numChannels argument. I wanted it to be more flexible regarding the number of channels used. I wanted it to behave similarly with one channel as with several, provided I allocate a bunch of buffers in order. It works fine without the “.do”-loop but gives me this cryptic error-message: “ERROR: Non Boolean in test.” when I try to evaluate this snippet.

Is this not allowed or is there a way to do this and make it work?

SynthDef(\bufWrite, {
    var numChannels = \numChannels.kr(1);
    var in = In.ar(\in.kr(0), numChannels);
    in.do({|channel, i|
        BufWr.ar(
            channel,
            \buf.kr(0) + i,
            Phasor.ar(
                1, 
                BufRateScale.kr(\buf.kr + i) * \rate.kr(1), 
                0,
                BufFrames.kr(\buf.kr + i)
            )
        );
    });
}).add;

numChannels cannot be a SynthDef argument.

This is a very common question. Use the forum search and you’ll find a lot of answers.

hjh

An honest question is what part of my question is common? I did not know the \numChannels was a reserved symbol until you told me. What do you suppose I search for?

numChannels isn’t reserved.

It can’t be a SynthDef argument because a SynthDef’s structure must be 100% predetermined. The server has no power to change the structure. If you try to change your synth from 2 to 3 channels, it means creating more UGens = different structure = not supported within one SynthDef.

This should definitely be mentioned in the SynthDef help file. Probably in the tutorial series too.

For your case, I think it would be best to have one SynthDef for one channel, another for two channels etc. These can be mass-produced in a loop:

(1..10).do { |numCh|
    SynthDef(("bufWrite" ++ numCh).asSymbol, {
        var in = In.ar(\in.kr(1), numCh);
        ...
    }).add;
};

Then you have SynthDefs bufWrite1, bufWrite2 etc.

hjh

Thanks for the explanation, what you wrote was identical to the SynthDef Issues-paragraph in the documentation FAQ. I was convinced that I had done something similar befor, but that was static. Perhaps it could be solved by using SynthDef.wrap?

SynthDef.wrap would be a less convenient way to write the same design as my suggestion.

It doesn’t sidestep the fixed-structure requirement, because there is no way anywhere in SC to sidestep that at the level of SynthDef. It would be possible to write a class for a higher level object that constructs a SynthDef on demand with the right number of channels (could be a big job to handle general cases!), but the SynthDef itself must be a fixed structure.

hjh