spotify / pedalboard

🎛 🔊 A Python library for audio.

Home Page:https://spotify.github.io/pedalboard

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

VST plugin Program presets not accessible

petrikaj opened this issue · comments

I have tried to access and change iZotope's VST plugins' Program presets but it seems they are not exposed.

Parameters work ok.

Here's what MrsWatson prints out from plugin —display-info

mrswatson

Notice it's not part of the parameters.

Using plugin.show_editor() allows to access those presets and changing them will change the parameters accordingly after quitting the showeditor(/).

MrsWatson allows to change it while loading the plugin:
"mrswatson64 --plugin 'plugin_name,preset_name’ -i input.wav -o output.wav"

Looking at the MrsWatson source code, this seems to be where the 'Programs' is being printed:

It reads from:

  • data->pluginHandle->numPrograms
  • data->pluginHandle effGetProgramNameIndexed nameBuffer->data
  • data->pluginHandle effGetProgramName nameBuffer->data

Googling for effGetProgramNameIndexed, it seems to be part of the VST2 SDK or similar.

Eg. Here's a go package that implements bindings for it:

  • https://github.com/pipelined/vst2
    • Build vst2 plugins and hosts with Go

    • vst2 implements VST2 SDK API. It provides capabilities to build both VST2 hosts and plugins.

    • https://pkg.go.dev/github.com/pipelined/vst2
      • // EffGetProgramNameIndexed passed to get program name by index.
        // Index: program index.
        // Ptr: *[maxProgNameLen]uint8 buffer for program name.
        // Return: true for success.
        EffGetProgramNameIndexed

Pedalboard doesn't seem to support VST2, but not sure if there is an equivalent function in VST3. We can start by looking at the VST3 SDK:

Searching for effGetProgramNameIndexed doesn't seem to turn up any results there (neither does GetProgramName / ProgramName)

Clicking through from that repo lead me to:

And searching that repo for GetProgramName lead me to this definition:

IUnitInfo describes the internal structure of the plug-in.
- The root unit is the component itself, so getUnitCount must return 1 at least.
- The root unit id has to be 0 (kRootUnitId).
- Each unit can reference one program list - this reference must not change.
- Each unit, using a program list, references one program of the list.
    /** Component intern program structure. */
	/** Gets the count of Program List. */
	virtual int32 PLUGIN_API getProgramListCount () = 0;

	/** Gets for a given index the Program List Info. */
	virtual tresult PLUGIN_API getProgramListInfo (int32 listIndex, ProgramListInfo& info /*out*/) = 0;

	/** Gets for a given program list ID and program index its program name. */
	virtual tresult PLUGIN_API getProgramName (ProgramListID listId, int32 programIndex, String128 name /*out*/) = 0;

	/** Gets for a given program list ID, program index and attributeId the associated attribute value. */
	virtual tresult PLUGIN_API getProgramInfo (ProgramListID listId, int32 programIndex,
		CString attributeId /*in*/, String128 attributeValue /*out*/) = 0;
/** Basic Program List Description.
\see IUnitInfo
*/
struct ProgramListInfo
{
	ProgramListID id;				///< program list identifier
	String128 name;					///< name of program list
	int32 programCount;				///< number of programs in this list
};

Then we can find the definition for ProgramListID in the following:

typedef int32 ProgramListID;	///< program list identifier

So it definitely seems like the concept of 'programs' still exists in the VST3 SDK.


Looking at an example CLI app for using the vst-rs Rust bindings for VST2, they don't seem to print the 'programs' details either; but they do have a section called 'presets':

    // Get the plugin information
    let info = instance.get_info();

    println!(
        "Loaded '{}':\n\t\
         Vendor: {}\n\t\
         Presets: {}\n\t\
         Parameters: {}\n\t\
         VST ID: {}\n\t\
         Version: {}\n\t\
         Initial Delay: {} samples",
        info.name, info.vendor, info.presets, info.parameters, info.unique_id, info.version, info.initial_delay
    );

Tracing through the code a bit, I found the definition for Info, which again doesn't mention 'program', but does mention 'presets':

Tracing through the code a bit more I found this implementation of PluginInstance, which seems to equate presets with programs:

plug.info = Info {
  // ..snip..
  presets: effect.numPrograms,
  // ..snip..
  preset_chunks: flags.intersects(PluginFlags::PROGRAM_CHUNKS),
}

Looking at the vst3-sys Rust bindings for VST3: