[VSTPlugins] Can't set many parameters at once - ERROR: non bolean in test

Hi!

I am not sure if the problem is regarding the VSTPlugins, the plugin itself (ambisonics 7th order with 64 channels) or some sort of client-server timming, but when I try to set many parameters of the VSTPluginController I am getting lots of error messages ERROR: non bolean in test. This is the code that I am using:

//Windows - SC 3.13.0
//vstplugin v0.5.4


~percussionSample = Buffer.read(s,"path/to/some/sample/percussionSample.wav");
~outOffset = 4 ; // interface bus offset
~numLoudspeakers = 25;
(
s.waitForBoot({

	Server.freeAll;
	s.newBusAllocators;
	s.boot;

	s.sync;

	// SynthDefs

	~order = 7; // set this to the order you want
	~numChannels = ((~order + 1)**2).asInteger;


	// 1 - Sound Source (Stereo)
	SynthDef(\sampler, { | out = 0, vol = 1.0, buf=0 |
		var sig;
		Out.ar(out, PlayBuf.ar(2, buf, BufRateScale.kr(buf),loop: 1.0, doneAction: Done.freeSelf)* vol);
	}).add;



	// 2 - directivity shaper encoder (mono -> ~numChannels) - coverts a mono signal into a ambisonics ~numChannels signal
	SynthDef.new(\directivityEncoder, { | bus = 0 |
		ReplaceOut.ar(bus, VSTPlugin.ar(In.ar(bus, 2), ~numChannels));
	}).add;

	// 3 - helper Synth (throws audio from ambi bus to ambi master bus)
	SynthDef.new(\ambiThrow, { | from, to |
		Out.ar(to, In.ar(from, ~numChannels));
	}).add;

	// 4 - all round decoder (~numChannels -> ~numLoudspeakers) - reads from 'bus' and sums into 'out'
	SynthDef.new(\allraDecoder, { | bus, out = 0 |
		Out.ar(out, VSTPlugin.ar(In.ar(bus, ~numChannels),~numLoudspeakers));
	}).add;

	// Paralel Bus AmbiFX- ambisonics insert FX (replaces input with output)
	SynthDef.new(\ambiFX, { | bus = 0, bypass |
		ReplaceOut.ar(bus, VSTPlugin.ar(In.ar(bus, 2), ~numChannels, bypass));
	}).add;


	s.sync;

	// create ambisonic master section

	// bus + group
	~ambiMasterBus = Bus.audio(s, ~numChannels);
	~ambiMasterGroup = Group.new;
	// binaural decoder (writes to master output)
	~decoder = VSTPluginController(Synth(\allraDecoder, [\bus, ~ambiMasterBus, \out, ~outOffset], // INTERFACE CHANGE!!!!
		target: ~ambiMasterGroup, addAction: \addToTail)).open("AllRADecoder");
	// a group for ambisonic master effects
	~ambiMasterFXGroup = Group.before(~decoder.synth);

	s.sync;

	// load decoder preset
	~decoder.readProgram("some/path/to/your/preset/preset-decoder.fxp");
	s.sync;

	// create ambisonic busses

	//add ambi groups *before* master group!
	~numBus = 1; 
	~ambiBus = Array.newClear(~numBus);
	~ambiGroup = Array.newClear(~numBus);
	~encoder = Array.newClear(~numBus);
	~numBus.do { |i|
		~ambiBus[i] = Bus.audio(s, ~numChannels);
		~ambiGroup[i] = Group.before(~ambiMasterGroup);
		// sound source (head)
		Synth.new(\sampler, [\out, ~ambiBus[i], \vol, 0.03 / ~numBus, \buf, ~percussionSample], ~ambiGroup[i], addAction: \addToHead);

		// encoder (after sound source)
		~encoder[i] = VSTPluginController(Synth(\directivityEncoder, [\bus, ~ambiBus[i]],
			target: ~ambiGroup[i], addAction: \addToTail));
		// open plugin and randomize azimuth

		~encoder[i].open("DirectivityShaper", action: { |self|
			"encoder loaded".postln;
			self.set(11, rand(7.0));
			self.set(12, 0.5);

			self.set(19, rand(7.0));
			self.set(20, 0.5);

			self.set(27, rand(7.0));
			self.set(28, 0.5);

			self.set(35, rand(7.0));
			self.set(36, 0.5);
		});

		// throw to master section (after encoder)
		Synth(\ambiThrow, [\from, ~ambiBus[i], \to, ~ambiMasterBus], target: ~ambiGroup[i], addAction: \addToTail);

	};

	s.sync;

	// move around with the VST editor:
	~encoder.do(_.editor);
	~encoder.do(_.gui);

	//configure the decoder
	//~decoder.do(_.editor);

	s.sync;

})
)

and here is the error message:

ERROR: Non Boolean in test.
RECEIVER:
   nil

PROTECTED CALL STACK:
	Meta_MethodError:new	000001EDA977DEC0
		arg this = MustBeBooleanError
		arg what = nil
		arg receiver = nil
	Object:mustBeBoolean	000001EDA848CDC0
		arg this = nil
	VSTPluginGui:prParamChanged	000001EDAAC54C80
		arg this = a VSTPluginGui
		arg index = 31
		arg value = 1.0
		arg display = High-pass
	a FunctionDef	000001EDA9B8FD40
		sourceCode = "<an open Function>"
	a FunctionDef	000001EDAC1717C0
		sourceCode = "<an open Function>"
	Function:prTry	000001EDA9B93140
		arg this = a Function
		var result = nil
		var thread = a Thread
		var next = nil
		var wasInProtectedFunc = false

CALL STACK:
	MethodError:reportError
		arg this = <instance of MustBeBooleanError>
	< closed FunctionDef >
		arg error = <instance of MustBeBooleanError>
	Integer:forBy
		arg this = 0
		arg endval = 32
		arg stepval = 2
		arg function = <instance of Function>
		var i = 30
		var j = 15
	SequenceableCollection:pairsDo
		arg this = [*34]
		arg function = <instance of Function>
	Scheduler:seconds_
		arg this = <instance of Scheduler>
		arg newSeconds = 210.3493235
	Meta_AppClock:tick
		arg this = <instance of Meta_AppClock>
		var saveClock = <instance of Meta_SystemClock>
	Process:tick
		arg this = <instance of Main>
^^ The preceding error dump is for ERROR: Non Boolean in test.
RECEIVER: nil

I’ve also tried to set the parameters in other parts of the code instead of doing it at the VSTPluginController.open() initialization, for example, after the penultimate s.sync with ~encoder.do(_.set(11, 0.0)) but I still get the same error.

Any ideas how to solve this?

Thanks a lot!

Hi, I can reproduce this. The culprit is the .gui call right after .open. This is a bug! I just pushed a fix to develop. In the meantime, here’s a workaround:

~encoder[i].open("DirectivityShaper", action: { |self|
    "encoder loaded".postln;
    // ... parameters ...
    defer { self.gui };
});

Thanks for the report!


Side note: you cannot reliably use s.sync after VSTPluginController.open for subsequent operations; you must use the action function for this purpose. (For a technical explanation, see Possible race condition between "Server.sync" and "VSTPluginController.open" (#84) · Issues · Pure Data libraries / vstplugin · GitLab). I’ve already clarified the documentation on the develop branch.

So instead of

s.sync;

// load decoder preset
~decoder.readProgram("some/path/to/your/preset/preset-decoder.fxp");

it should rather be:

~decoder = VSTPluginController(Synth(\allraDecoder, [\bus, ~ambiMasterBus, \out, ~outOffset], // INTERFACE CHANGE!!!!
		target: ~ambiMasterGroup, addAction: \addToTail)).open("AllRADecoder", action: { |self|
    // load decoder preset
    self.readProgram("some/path/to/your/preset/preset-decoder.fxp");
});

Also, in your code snippet, only the s.sync after the SynthDefs is necessary, all other instances are redundant.

1 Like

@Spacechild1 Thanks a lot!!!

yes, I was inserting s.sync thoughout the whole code to see if it solved the problem… I remember that for something strange that I was doing inserting two subsequent s.sync apparently solved some issue :upside_down_face:

BTW, is it possible to get a list of all the parameters and of the ranges of a plugin? or is that only accessibly through the SC GUI?

Sure! See VSTPluginDesc.parameters. You can get it either from the plugin dictionary (VSTPlugin.plugins) or with VSTPluginController.info (only after the plugin has been loaded).

The parameter range is always normalized between 0.0 and 1.0.

1 Like

Thanks! I made a mistake because some of the parameters are displayed in the GUI with their own value, for instance the directivity order (1-7).