VSTPlugin v0.2 test release

Hi, I’m happy to announce a test release of VSTPlugin v0.2. You can download binaries here: https://git.iem.at/pd/vstplugin/-/releases

If possible, please report bugs at https://git.iem.at/pd/vstplugin/issues

Otherwise just leave them here in the comments.

Enjoy!


Changelog:

features
  • VST2 shell plugin support (e.g. “Waves”)
  • (experimental) VST3 support including sample accurate automation and auxiliary inputs/outputs for side-chaining
  • soft-bypass
  • potential macOS GUI editor for Supercollider (see https://github.com/supercollider/supercollider/pull/4499)
  • faster search/probe (parallel)
  • cache search/probe results in a file to speed up subsequent searches
  • VSTPluginController: ‘set’ and ‘get’ now also accept parameter names instead of indices.
  • VSTPlugin.ar now accepts an ‘info’ argument, which allows ‘params’ to contain parameter names instead of indices. You can also ommit the name/path argument in VSTPluginController.open.
  • *Msg versions for all relevant methods to enable NRT synthesis and bundling.
  • You don’t have to wait anymore between creating a Synth and calling ‘open’, e.g.: VSTPluginController(Synth(\vst)).open("myPlugin");
changes
  • deprecated ‘parameterNames’ and ‘parameterLabels’ in plugin info. The info has now a member called ‘parameters’ which is an Array of parameter info Events (with ‘name’ and ‘label’ being the only members so far).
bug fixes
  • fixed possible crasher bugs when the UGen is freed while asynchronous commands are still running
internal changes
  • use .ini like syntax for plugin info
  • hard-bypass prefers the plugin’s bypass method
  • single event loop shared by all plugins
  • many changes to the OSC interface, UGen arguments and plugin info file structure
4 Likes

Thanks a million Christof ! Can’t wait to try this new version when I’m back from holidays ! Cheers

excitement! looking forward to trying…

Is this expected behavior? When I set the parameter of a VSTPlugin to something inside the synth, whether a single value or an LFO, this does not get ‘set’ until I send the .set message after the synth is playing, which then sets the value to whatever was in the synth. For example,

(
SynthDef('noise', {
	Out.ar(0, PinkNoise.ar(0.8.dup) * Decay.ar(Impulse.ar(3)))
}).add;

SynthDef(\insert, { arg bus;
	var lfo = SinOsc.ar(0.2).range(0, 1);
    ReplaceOut.ar(bus, VSTPlugin.ar(In.ar(bus, 2), 2, params: [0, lfo]));  
}).add;
)

~noise = Synth('noise')

// search of available VST plugins in the default VST search paths
VSTPlugin.search;

// create the synth:
~synth = Synth(\insert, [\bus, 0], 1, 'addToTail');
// get a handle to the VSTPlugin:
~fx = VSTPluginController(~synth);

// open a plugin by name/key (might require VSTPlugin.search!)
~fx.open("ValhallaShimmer", info: true);
// alternatively, you can open a plugin by its file path 
// (this only works if the file contains a single plugin, like most VST2.x plugins)
// ~fx.open("/path/to/plugin", info: true);

~fx.get(0, {arg f; f.postln}) // still 0.5

~fx.set(0, 0) // start the lfo for some reason

// show the GUI:
~fx.gui;
// etc.

Also is there a way to get all the parameters’ default values (for a preset)? Something like…

~fx.getParameterValues; // returns array [0.5, 0.2, etc.] with default params 0 -> 0.5 and 1 ->  0.2 and so on

Is this expected behavior?

Are you on Linux? There was a problem with a GCC + “-ffast-math” which broke parameter automation via UGen inputs: Can't set.synth in v. 0.2 test (#38) · Issues · Pure Data libraries / vstplugin · GitLab This has been fixed in latest develop. You can just pull from there and build from source. Thanks for testing!

Sure. Usually, it’s best to get the raw plugin state as Int8Array (~fx.getProgramData / ~fx.setProgramData) because it’s more compact and plugins might contain additional state beyond their parameter values.

If you really want to obtain the individual parameter values, you can use ~fx.getn. The values are passed as an array to action and you can optionally specifiy start index and number of parameters. ~fx.get(action: { |v| v.postln }); will simply get and print all parameters. Note that if a plugin has lots of parameters, you might have to use several calls to get with appropriate offset and count because OSC messages have a size limit. On the other hand, getProgramData transfers the data via a temp file, so it’s always reliable.

I am on Mac OS X…

alright, then it probably also broke with clang :-/ here’s a macOS snapshot from develop: https://git.iem.at/pd/vstplugin/-/jobs/7149/artifacts/download does this work? (ignore the Supernova binary for now)

Can you help me parse the Int8Array? I don’t have much experience with them…

Works great!!! Thanks!

cool! don’t hesitate to report further issues or ask any questions.

Woot woot!
Got my all time favourite plugin working inside SC which makes me immensely grateful and happy.

How do I read and write presets without using the gui?

Great to hear! Have a look at readProgram/writeProgram and setProgramData/getProgramData.

I am working mostly in NRT and I have noticed that I am able to run plugins without booting the server and without evaluating VSTPlugins.search as the plguins will read from the plugins.ini file. However, in the language, VSTPlugins.plugins still evaluates to nil so I cannot get information about the plugins, mainly the parameter list. Is there any way to search without booting the server?

I am working mostly in NRT

great to hear the NRT features are actually being used :slight_smile:

I have noticed that I am able to run plugins without booting the server and without evaluating VSTPlugins.search as the plguins will read from the plugins.ini file.

To clarify: this is only true if you have done VSTPlugins.search at least once, so the plugins.ini file really exists. But even without the cache file you can open plugins by referring to their absolute or relative filename - which is not necessarily the same as the plugin name! This only works if the file contains a single plugin, so it doesn’t work for VST2 shell plugins or VST3 modules containing several plugins.

However, in the language, VSTPlugins.plugins still evaluates to nil

Yes, because VSTPlugin.search also asks the Server to transmit the search results to the Client, otherwise the dictionary is empty. Note that each Server has it’s own plugin dictionary because
a) it might require a specific set of plugins (e.g. by providing a directory argument to VSTPlugin.search)
b) it might run on a different computer with different plugins installed.

Is there any way to search without booting the server?

Unfortunately, this is not possible, because the language client doesn’t know the exact location of the UGen and its accompanying files, so I can’t call the probe executable. If you really want to search for plugins, you need to open a Server instance. What I could provide is a class method like VSTPlugin.readPlugins which just parses the local plugins.ini and returns a dictionary instance which the user can store in some variable. (I can’t store it in VSTPlugin.plugins because it doesn’t belong to a specific Server instance.) You would still need to call VSTPlugin.search at least once, because otherwise you don’t have plugins.ini, but then you can get the plugin info without booting a Server. Would this make sense?

This would be awesome!

And yes everything is working really great. You have no idea the headache this saves me from trying to run 3rd order ambisonics with 20+ channels into stereo or even mono VSTs.

1 Like

@Daniel_Peterson VSTPlugin.readPlugins is now available on latest develop! It returns a dictionary containing the locally cached plugin info. You can pass the plugin info to VSTPlugin.ar; this allows you to use parameter names instead of indices in the params argument and you can also omit the path argument in VSTPluginController.openMsg. These features have been already available for RT synthesis, but now they also work with NRT synthesis.

@Spacechild1 Thanks! It works really great.

I am having so much fun with this and I am immensely grateful that this exists.

I have run VSTPlugin.search and, I am aware that this is most likely for my own safety but I still need to ask this I’m sorry:

Any way I can get around certain plugins being black-listed?
Maybe if I understood more about why they’ve been put on this black list I could deal with it better.
Might it have something to do with how certain plugins introduce tons of latency? I would be ok with that.

Thanks again for your amazing work on this.