-
Notifications
You must be signed in to change notification settings - Fork 246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Addition: Implementing Save and Load Functionality for VST3 Plugin States #289
Conversation
Hi @Myuqou! Thanks for this contribution - this looks really great! I have a couple high-level suggestions before I think we can merge this:
Let me know if you'd like to make these changes or if you'd prefer me to do so; I'd be happy to make these changes in this PR if you like. |
As tempted as I am to take on the challenge, it would probably be a better idea for you to make the changes if you have the time as you are more familiar with the program. I wasn't sure if capturing the parameters was even a necessary step as in every test I conducted I was able to simply save and load the state information without running into any problems. If the copy of the parameters is not needed then that would make it much easier to just grab the state information and pass it back to Python. |
just wanted to chime in that I'm looking forward to using this feature! ...might even just dev off of this branch, since this is so useful |
@psobot Curious if you were still up for making the changes required to land this? Would be an awesome feature to have in Or alternatively, perhaps this PR? From a quick skim of that PR, it looks like it's closer ( I'm not sure if the 'separated read/write' approach in that PR is better than just a pure |
Given #297 just got merged, wondering if this PR is still relevant?
Docs:
|
I was reading a bit more about saving/loading state for VST3, and it sounds like there are 2 different kinds of state:
Am I right in assuming that previously we were able to access the 'processor state' (param values), and as of #297 we can now access the 'controller state'? Edit: Looking at the code in the PR (Ref) it calls
Those docs also mention these following different methods:
Looking at JUCE's code we can see the implementations for:
This tutorial may also be interesting for futher/deeper reading: |
Apologies for the delay - #297 has now been merged, exposing a |
Problem:
Some VST3 plugins don't expose all UI parameters to the host, hindering
programmatic manipulation without manual intervention. This is evident in
plugins like Native Instrument's Kontakt and Plogue's Sforzando, where
instrument or effect selection is confined to the editor window, posing
challenges for automated loading.
Additionally, issues arise with plugins featuring presets incompatible with
existing load methods, or being overly complicated in setting their parameters,
as evidenced in previous issue reports:
Save and Load Presets Automatically for VST3 Plugins? #187
Loading non .vstpreset files with load_preset function #245
VST plugin Program presets not accessible #257
Cannot load .fxp file for Serum #277).
Solution:
Implemented save_plugin_state and load_plugin_state methods in ExternalPlugin
to address the above issues. Leveraging JUCE's getStateInformation and
setStateInformation, these methods facilitate saving and loading plugin
configurations to/from disk in much the same way that a DAW would.
The save_plugin_state method also makes a copy of the accessible parameters
which the load_plugin_state reapplies twice, similar to how Pedalboard's
reinstantiatePlugin method works.
The binary state information is converted to a base64 string using JUCE, and
the recorded parameters are also converted to a string. The two data types are
combined, being separated by a pipe character, which is not used in the base64
encoding. The resulting character string is then saved to disk.
Using the new methods in Python is as simple as this example:
Later, to restore the plugin to the previously saved state:
plugin.load_plugin_state("path/to/your/directory/plugin.sav")
can name the file whatever they want. The data is just a character string
stored in what is essentially a text file.
Results:
I tested the new methods on the following VST3 plugins and they work flawlessly:
I do not have access to Serum, so I can't verify that this will address
Issue #277, but Vital is the OSS counterpart of Serum and I was able to load a
previously saved state, which included instrument presets, without any issue.
Potential Problems:
I am a beginner level, self taught programmer who has no experience working
on team projects, so I don't know if I followed all of the best practices when
writing this code. Reviewers should keep that in mind in case I messed
something up.
I noticed that Pedalboard's reinstantiatePlugin method goes through a number
of steps when loading a state back into the plugin after resetting it. I only
incorporated the part where, after the state is set, the parameters are
reassigned twice. I didn't run into any problems, but I am not familiar with
the situations that reinstantiatePlugin is trying to address so someone with
more experience need to verify that there isn't going to be an issue there.
The names of the parameter keys do not update if you switch instruments on an
existing plugin instance by loading a plugin state. I am not sure how to fix
this, but a best practice would be to load the parameter settings on a fresh
instance of the plugin.
There is currently no safeguard or error warning when if a user tries to load
a state into the wrong plugin. It's currently up to the user to keep their
saved state files organized. I am not sure how to fix this at this time.
Unfortunately, I couldn't test this on a Mac, so I can't guarantee
compatibility with AU plugins. In theory, it should work, but I don't want to
implement a feature I can't test. Updating the code for AU plugins should be
as simple as adding two lines for the pybind11 bindings.
I did not add any type hints or updates to the documentation as I don't feel
entirely confident about getting it right without causing more confusion.