VSTPlugin v0.5.4 released!

Is there a “best practices” way to allocate VSTs to different cores ?
I have a pretty multi-core machine (which is great!) but it looks like supercollider allocates everything to one CPU by default.

I know that I’m going to have to go down the route of supernova to get this to be more efficient, but wanted to check to see if with VSTs specifically if there was a best way to do this.

Is there a “best practices” way to allocate VSTs to different cores ?

You just have to open the plugin with multiThreading: true to make use of the internal DSP thread pool. Note that the output will be delayed by one block! (The reason is that multi-threading is implemented as asynchronous “pipelining”, i.e. the plugin processing is moved to a helper thread and the result is collected at the next block.) This can be a problem with long serial FX chains where the individual delays would quickly add up. The multiThreading option is really meant for offloading individual “heavy” plugins. For that use case, it works pretty well.

If you have more complex FX chains that you need to parallelize without delay, you would have to use Supernova with ParGroups.

Brilliant! This is (for now) just for heavy synths, nothing complex in the FX chain.

I’ll file a bug if this is unexpected behavior, but … if I have several single-threaded plugins already loaded and then I go to load an instrument as multithreaded, all of the single-threaded plugins close/are freed.

if I have several single-threaded plugins already loaded and then I go to load an instrument as multithreaded, all of the single-threaded plugins close/are freed.

Hmmm… I am not able to reproduce this. I guess there are more variables involved. Please open a bug report!

1 Like

I’ve got SC 3.13 up and running in native arm64 on my M1 mbp. I’d like to use VSTPlugin but I’m having a hard time figuring out how to get it set up.

I’m not a dev and I’ve never built from source before, and I was confused by the instructions in the README until i had the realization that they might be outdated for my use case, since they seem to have been written before the native M1 build of SuperCollider became available. Then I tried using the scripts provided by @madskjeldgaard to automatically build from source, but the build failed and returned an error.

$ ./vstplugin.sh arm64
Building vstplugin for architecture arm64
./vstplugin.sh: line 26: /vstplugin/.git-ci/get_vst2.sh: No such file or directory
./vstplugin.sh: line 29: /vstplugin/.git-ci/get_vst3.sh: No such file or directory
./vstplugin.sh: line 33: cmake: command not found

It would be lovely if somebody could provide compiled binaries for M1.

I’m not a dev and I’ve never built from source before, and I was confused by the instructions in the README until i had the realization that they might be outdated for my use case

The README is up to date and M1 is explicitly mentioned. However, the project has a couple of dependencies and you have to follow the README closely. The first problem I see is that you don’t have cmake installed.

Unfortunately, there are no “official” macOS ARM binaries yet, but I have already set up a CI pipline. Here you can grab universal macOS binaries for the latest develop branch: https://git.iem.at/pd/vstplugin/-/jobs/43581/artifacts/download?file_type=archive.

1 Like

@john-d-murphy Still waiting for the bug report :wink:

1 Like

Yep! I know! I’ve been sick and I’ve had a final project due for school. I’ll get it to you!

Put in an issue!
I was able to recreate it today - sorry for the noisy log, I picked a bad synth to load.

Not sure if this is the right thread, but: I am wondering, if it is somehow possible to generate and send MIDI events to the VSTPlugin Ugen at audio rate (such as mc.midiplayer~ in Max)?

Hi, MIDI events can be sent at any rate if scheduled as OSC bundles (the \vst_midi Event type does this automatically).

2 Likes

mc.midiplayer~ accepts audio signals as input and produces (presumably accurately-timed) MIDI messages for vst~ as output. There is no exact analog to this in SuperCollider.

However, messages to the server are timestamped. I confirmed through testing that the timestamp accuracy for VSTPlugin is accurate within control blocks. (I set control block size to 512 – block duration is 512/48000 = 0.01066667 – then I sequenced notes with a non-multiple 0.065 seconds between notes. Because it’s a non-multiple, if timing were quantized to control blocks, you’d see ~0.06 then ~0.07. Instead, the performance of the MIDI notes was consistent, proving that we get sub-control-block accuracy without doing anything special.)

That is, SC’s timing model is better than Max’s; we don’t need Max’s “audio-rate sequencing” workaround for good timing.

hjh

1 Like

Neither does Pd, BTW! I haven’t really checked, but I think Max/MSP cannot do this because the message scheduler runs independently from DSP processing. In Pd, on the other hand, the scheduler runs synchronously to DSP processing, so [vstplugin~] can simply use the logical time to generate the necessary offset.

2 Likes

This came as a surprise to me in Pd – I thought Pd’s control messages were quantized to control blocks, but [delay] and similar objects do schedule according to logical time, with sub-block accuracy.

My SC test goes like this:

s.options.blockSize = 512;  // ~= 0.01 or 0.011 sec
s.boot;

(
SynthDef(\vst, { |out = 0|
	Out.ar(out, VSTPlugin.ar(numOut: 2));
}).add;

SynthDef(\offsetOut, { |out = 0, freq = 440, amp = 0.1|
	var sig = SinOsc.ar(freq) * EnvGen.ar(Env.perc(0.001, 0.08), doneAction: 2);
	OffsetOut.ar(out, sig * amp);
}).add;

SynthDef(\normalOut, { |out = 0, freq = 440, amp = 0.1|
	var sig = SinOsc.ar(freq) * EnvGen.ar(Env.perc(0.001, 0.08), doneAction: 2);
	Out.ar(out, sig * amp);
}).add;
)

// prepare VST: run these one by one
a = Synth(\vst);

c = VSTPluginController(a);

c.open("Vital.vst3");

c.editor;

… and set up a synth patch with a very short envelope (like 10 ms decay, 0 sustain).

~normalOutBus = Bus.audio(s, 1);
~offsetOutBus = Bus.audio(s, 1);
~vstBus = Bus.audio(s, 2);
a.set(\out, ~vstBus);

(
p = Ppar([
	Pbind(
		\instrument, \normalOut,
		\freq, 880,
		\dur, 0.065,  // at 44.1 kHz, maybe 0.064 or 0.063 would be better
		\amp, 0.1,
		\out, ~normalOutBus
	),
	Pbind(
		\instrument, \offsetOut,
		\freq, 440,
		\dur, 0.065,  // at 44.1 kHz, maybe 0.064 or 0.063 would be better
		\amp, 0.1,
		\out, ~offsetOutBus
	),
	Pbind(
		\type, \vst_midi, \vst, c,
		\freq, 220,
		\dur, 0.065,  // at 44.1 kHz, maybe 0.064 or 0.063 would be better
		\amp, 0.8
	)
]).play;
)

// record some of that
b = Buffer.alloc(s, s.sampleRate, 3);

{ RecordBuf.ar(In.ar([~normalOutBus, ~offsetOutBus, ~vstBus], 1), b, loop: 0, doneAction: 2) }.play(s.defaultGroup, 1000, addAction: \addAfter);

// wait 1 sec, then
p.stop;

b.write(thisProcess.nowExecutingPath.dirname +/+ "23-0819-vst-timing.wav", headerFormat: "wav", sampleFormat: "int16");

[b, ~normalOutBus, ~offsetOutBus, ~vstBus, a].do(_.free);

Then in the file, channel 0’s notes are quantized to block boundaries, 1’s notes match the equally-spaced timestamps, and 2’s notes come from VSTPlugin.

… and conspicuously, in the first channel, occasionally there is a longer time delta (i.e. poor timing has been reproduced) that is not found in the OffsetOut and VST channels, which are in perfect sync (i.e. VSTPlugin doesn’t suffer from that problem).

@pikseliahky Conclusion: It’s done correctly for you, so, don’t worry about it.

hjh

2 Likes

That is great, thank you very much for your explanations!

Hi! First time poster here! :hugs:

I’m trying to run the VSTPlugin extension in SC and running into some issues when I run VSTPlugin.search;. I’m on an M1 mac.

Taking a step back, here are my steps to have gotten this far.

I first tried to download the mac binary for VSTPlugin-0.54 here.

When I extract that into my Extensions folder, follow the steps to workaround macOS Gatekeeper, and compile my class library, I get this error/warning:

*** ERROR: dlopen '/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin.scx' err 'dlopen(/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin.scx, 0x0002): tried: '/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin.scx' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64')), '/System/Volumes/Preboot/Cryptexes/OS/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin.scx' (no such file), '/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin.scx' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64'))'
*** ERROR: dlopen '/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin_supernova.scx' err 'dlopen(/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin_supernova.scx, 0x0002): tried: '/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin_supernova.scx' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64')), '/System/Volumes/Preboot/Cryptexes/OS/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin_supernova.scx' (no such file), '/Users/kevin/Library/Application Support/SuperCollider/Extensions/VSTPlugin/plugins/VSTPlugin_supernova.scx' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64'))'

So I used sc-plugins-build-scripts from this post to build with arm64. Thank you @madskjeldgaard! I copied the resulting folder into my Extensions folder and that allowed it to compile without errors. However, I noticed that there wasn’t a plugins folder in there.

In any case, whether I compiled the Extension extracted from the binary or that I compiled with the script, I get this error when I run VSTPlugin.search::

FAILURE IN SERVER /cmd failed
ERROR: Failed to read tmp file!

It looked like the same issue as this but without the same resolution.

Would anyone be able to offer any guidance as to the next troubleshooting steps? Thanks!

1 Like

Hi, when I released VSTPlugin v0.5.4, our CI system did not have a machine that could produce macOS ARM binaries. Luckily, this has changed, but I forgot to upload new binaries to the release page.

I just added links for universal macOS binaries: v0.5.4 · Pure Data libraries / vstplugin · GitLab

Please try and report back!

3 Likes

This worked great!! Thank you so much @Spacechild1! :heart:

1 Like

Glad to hear it works!

1 Like