From 530a1144d14d95a8888bf6849761299d5f3afa20 Mon Sep 17 00:00:00 2001 From: Emil Winebrand Date: Tue, 25 Jan 2022 23:16:59 +0200 Subject: [PATCH 1/6] added preset loading capability for VST3 plugins --- pedalboard/ExternalPlugin.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/pedalboard/ExternalPlugin.h b/pedalboard/ExternalPlugin.h index 6394deea..006c4a14 100644 --- a/pedalboard/ExternalPlugin.h +++ b/pedalboard/ExternalPlugin.h @@ -226,6 +226,31 @@ template class ExternalPlugin : public Plugin { } } + struct PresetVisitor: juce::ExtensionsVisitor{ + std::string presetFile; + bool result; + PresetVisitor(std::string file){ + presetFile = file; + } + void visitVST3Client (const juce::ExtensionsVisitor::VST3Client& client) override{ + result = false; + juce::File fl(presetFile); + juce::MemoryBlock mb; + + if (fl.loadFileAsData(mb)){ + result = client.setPreset(mb); + } + } + }; + + + bool loadPresetData(std::string stateFile) { + PresetVisitor visitor {stateFile}; + pluginInstance->getExtensions(visitor); + return visitor.result; + } + + void reinstantiatePlugin() { // If we have an existing plugin, save its state and reload its state later: juce::MemoryBlock savedState; @@ -793,6 +818,10 @@ inline void init_external_plugins(py::module &m) { ss << ">"; return ss.str(); }) + .def("load_preset", + &ExternalPlugin::loadPresetData, + "Load a VST3 preset file .vstprest format " + "return false if fails") .def_property_readonly_static( "installed_plugins", [](py::object /* cls */) { return findInstalledVSTPluginPaths(); }, From cf9eabd07ccbf09c01b67122304979809f8175ea Mon Sep 17 00:00:00 2001 From: Emil Winebrand Date: Wed, 26 Jan 2022 09:35:23 +0200 Subject: [PATCH 2/6] Added preset loading testing --- tests/presets/CHOWTapeModel.vst3.vstpreset | Bin 0 -> 1700 bytes tests/test_external_plugins.py | 25 +++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/presets/CHOWTapeModel.vst3.vstpreset diff --git a/tests/presets/CHOWTapeModel.vst3.vstpreset b/tests/presets/CHOWTapeModel.vst3.vstpreset new file mode 100644 index 0000000000000000000000000000000000000000..e95a3d755cb071497aa81d0dad4c644864858d1e GIT binary patch literal 1700 zcma)-&rcIU6vt;R54tUAj3ge61aHOzp+6{)NNfw`U^FR+#@jNmv+aa#ciEk`z^NA# z{|x>NZlV`G7*8g8GH9X~661xFiFG<%7TzvI=dy?S%=dlYn|W`aJz2|Xgpg8sajCLA zote+fWtU5paz0m>D=g2>=1YaV{LZ}`mXKUk>QS2s=J|wZ_o}7U(qp1s;U>{WVYALU zhRIw}CvDnjF{0^1^2p?ii(mIXVo(Q@)eLG2 z#7V&;%%v3vCn&;}51k>B?Fr2`; z^<%AwFn}6$Pi0hnyEkWUVI~Q6V}trW!pQ2umsdzCB{AW#jYeoo>5=1=ci4Oqc(X=% z6X|tRpROMwyU?txQTu;-H=$>x+m&u){6h5JsKXA{9!*V5i}9u*L1)_p$obfVAlrYq_}2 zW5M1($`W{KIKF?8%QV=0$EbPEIr-p-aGES~M9uEtt$ExE+eWok@nGURzBgUHwdhpr zzB!SD`*b~gx>%{oX(t Date: Thu, 27 Jan 2022 09:02:12 +0200 Subject: [PATCH 3/6] Update pedalboard/ExternalPlugin.h Co-authored-by: Peter Sobot --- pedalboard/ExternalPlugin.h | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/pedalboard/ExternalPlugin.h b/pedalboard/ExternalPlugin.h index 006c4a14..779f6a28 100644 --- a/pedalboard/ExternalPlugin.h +++ b/pedalboard/ExternalPlugin.h @@ -226,19 +226,21 @@ template class ExternalPlugin : public Plugin { } } - struct PresetVisitor: juce::ExtensionsVisitor{ - std::string presetFile; - bool result; - PresetVisitor(std::string file){ - presetFile = file; - } - void visitVST3Client (const juce::ExtensionsVisitor::VST3Client& client) override{ - result = false; - juce::File fl(presetFile); - juce::MemoryBlock mb; + struct PresetVisitor : public juce::ExtensionsVisitor { + const std::string presetFilePath; + + PresetVisitor(const std::string presetFilePath): presetFilePath(presetFilePath) { } + + void visitVST3Client(const juce::ExtensionsVisitor::VST3Client& client) override { + juce::File presetFile(presetFilePath); + juce::MemoryBlock presetData; + + if (!presetFile.loadFileAsData(presetData)) { + throw std::runtime_error("Failed to read preset file: " + presetFilePath); + } - if (fl.loadFileAsData(mb)){ - result = client.setPreset(mb); + if (!client.setPreset(presetData)) { + throw std::runtime_error("Plugin returned an error when loading data from preset file: " + presetFilePath); } } }; From 39118378c78ae791ea27c4e36e585371d35ba8c3 Mon Sep 17 00:00:00 2001 From: emilio1234 Date: Thu, 27 Jan 2022 09:02:37 +0200 Subject: [PATCH 4/6] Update pedalboard/ExternalPlugin.h Co-authored-by: Peter Sobot --- pedalboard/ExternalPlugin.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pedalboard/ExternalPlugin.h b/pedalboard/ExternalPlugin.h index 779f6a28..1183abe0 100644 --- a/pedalboard/ExternalPlugin.h +++ b/pedalboard/ExternalPlugin.h @@ -822,8 +822,7 @@ inline void init_external_plugins(py::module &m) { }) .def("load_preset", &ExternalPlugin::loadPresetData, - "Load a VST3 preset file .vstprest format " - "return false if fails") + "Load a VST3 preset file in .vstpreset format.", py::arg("preset_file_path")) .def_property_readonly_static( "installed_plugins", [](py::object /* cls */) { return findInstalledVSTPluginPaths(); }, From d5447c3e3c021dbbb1c1cc7373e39f6eafeb8b07 Mon Sep 17 00:00:00 2001 From: emilio1234 Date: Thu, 27 Jan 2022 09:03:07 +0200 Subject: [PATCH 5/6] Update pedalboard/ExternalPlugin.h Co-authored-by: Peter Sobot --- pedalboard/ExternalPlugin.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pedalboard/ExternalPlugin.h b/pedalboard/ExternalPlugin.h index 1183abe0..11f239e4 100644 --- a/pedalboard/ExternalPlugin.h +++ b/pedalboard/ExternalPlugin.h @@ -246,10 +246,9 @@ template class ExternalPlugin : public Plugin { }; - bool loadPresetData(std::string stateFile) { - PresetVisitor visitor {stateFile}; + void loadPresetData(std::string presetFilePath) { + PresetVisitor visitor {presetFilePath}; pluginInstance->getExtensions(visitor); - return visitor.result; } From dd2bb2fcd8f6734ab18cb619c6e8e88911c3db9d Mon Sep 17 00:00:00 2001 From: Peter Sobot Date: Thu, 27 Jan 2022 23:00:25 -0500 Subject: [PATCH 6/6] Ran clang-format and black. --- pedalboard/ExternalPlugin.h | 44 ++++++++++++++++++---------------- tests/test_external_plugins.py | 24 ++++++++++--------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/pedalboard/ExternalPlugin.h b/pedalboard/ExternalPlugin.h index 11f239e4..14a52d8f 100644 --- a/pedalboard/ExternalPlugin.h +++ b/pedalboard/ExternalPlugin.h @@ -227,31 +227,34 @@ template class ExternalPlugin : public Plugin { } struct PresetVisitor : public juce::ExtensionsVisitor { - const std::string presetFilePath; - - PresetVisitor(const std::string presetFilePath): presetFilePath(presetFilePath) { } - - void visitVST3Client(const juce::ExtensionsVisitor::VST3Client& client) override { - juce::File presetFile(presetFilePath); - juce::MemoryBlock presetData; - - if (!presetFile.loadFileAsData(presetData)) { - throw std::runtime_error("Failed to read preset file: " + presetFilePath); - } + const std::string presetFilePath; - if (!client.setPreset(presetData)) { - throw std::runtime_error("Plugin returned an error when loading data from preset file: " + presetFilePath); - } + PresetVisitor(const std::string presetFilePath) + : presetFilePath(presetFilePath) {} + + void visitVST3Client( + const juce::ExtensionsVisitor::VST3Client &client) override { + juce::File presetFile(presetFilePath); + juce::MemoryBlock presetData; + + if (!presetFile.loadFileAsData(presetData)) { + throw std::runtime_error("Failed to read preset file: " + + presetFilePath); } - }; + if (!client.setPreset(presetData)) { + throw std::runtime_error( + "Plugin returned an error when loading data from preset file: " + + presetFilePath); + } + } + }; void loadPresetData(std::string presetFilePath) { - PresetVisitor visitor {presetFilePath}; - pluginInstance->getExtensions(visitor); + PresetVisitor visitor{presetFilePath}; + pluginInstance->getExtensions(visitor); } - void reinstantiatePlugin() { // If we have an existing plugin, save its state and reload its state later: juce::MemoryBlock savedState; @@ -820,8 +823,9 @@ inline void init_external_plugins(py::module &m) { return ss.str(); }) .def("load_preset", - &ExternalPlugin::loadPresetData, - "Load a VST3 preset file in .vstpreset format.", py::arg("preset_file_path")) + &ExternalPlugin::loadPresetData, + "Load a VST3 preset file in .vstpreset format.", + py::arg("preset_file_path")) .def_property_readonly_static( "installed_plugins", [](py::object /* cls */) { return findInstalledVSTPluginPaths(); }, diff --git a/tests/test_external_plugins.py b/tests/test_external_plugins.py index 40f0b162..6503d31a 100644 --- a/tests/test_external_plugins.py +++ b/tests/test_external_plugins.py @@ -189,30 +189,32 @@ def test_at_least_one_parameter(plugin_filename: str): assert get_parameters(plugin_filename) + @pytest.mark.parametrize( - "plugin_filename,plugin_preset", [ - (plugin,os.path.join(TEST_PRESET_BASE_PATH, plugin+".vstpreset")) - for plugin in AVAILABLE_PLUGINS_IN_TEST_ENVIRONMENT \ - if os.path.isfile(os.path.join(TEST_PRESET_BASE_PATH, plugin+".vstpreset")) - ]) + "plugin_filename,plugin_preset", + [ + (plugin, os.path.join(TEST_PRESET_BASE_PATH, plugin + ".vstpreset")) + for plugin in AVAILABLE_PLUGINS_IN_TEST_ENVIRONMENT + if os.path.isfile(os.path.join(TEST_PRESET_BASE_PATH, plugin + ".vstpreset")) + ], +) def test_preset_parameters(plugin_filename: str, plugin_preset: str): # plugin with default params. plugin = load_test_plugin(plugin_filename) - default_params = { - k: v.raw_value for k, v in plugin.parameters.items() if v.type == float - } - + default_params = {k: v.raw_value for k, v in plugin.parameters.items() if v.type == float} # load preset file plugin.load_preset(plugin_preset) - for name, default in default_params.items(): actual = getattr(plugin, name) if math.isnan(actual): continue - assert actual != default, f"Expected attribute {name} was {actual} supposed to be different from default {default}" + assert ( + actual != default + ), f"Expected attribute {name} to be different from default ({default}), but was {actual}" + @pytest.mark.parametrize("plugin_filename", AVAILABLE_PLUGINS_IN_TEST_ENVIRONMENT) def test_initial_parameters(plugin_filename: str):