Auto-restoring a VSTPlugin "main fx" style state

Hello everyone

Something I realised today is that I would like my VSTPlugin instances that I use as “main output fx” in SuperCollider to be restored fully after CmdPeriod. Today I think I figured it out.

The below script will take the list of vst plugin names you want and create an fx chain after group 1 and automatically re-spawn it after cmdperiod and then re-set all of the parameters from before. The parameters are saved every 15 seconds by a Tdef. What do you think?

(
s.boot;

s.doWhenBooted{
    SynthDef(\insert, { arg bus;
        ReplaceOut.ar(bus, VSTPlugin.ar(In.ar(bus, 2), 2));
    }).add;

    // May be necessary:
    // VSTPlugin.search();
}
)
(
var pluginNames = [
    "TEOTE.vst3",
    "Elephant.vst3",
];

~autosaveSeconds = 15; // Interval between autosaves
~pluginControllers = Array.newClear(pluginNames.size);
~pluginControllersParams = ~pluginControllersParams ?? {IdentityDictionary.new};

~savePluginParams = {
    ~pluginControllers.do{|pgc|
        var name = pgc.info.key;

        "Saving params for %".format(name).postln;
        ~pluginControllersParams.put(name, Array.newClear(pgc.numParameters));
        pgc.numParameters.do{|ind|
            pgc.get(ind, {|val|
                ~pluginControllersParams[name][ind] = val;
            })
        }
    }
};

Tdef(\vst_param_saver, {
    loop {
        ~autosaveSeconds.wait;
        ~savePluginParams.value();
    }
});

~initVSTPlugins = {

    ~vstSynths = pluginNames.collect{ Synth(\insert) };

    pluginNames.do{|vstname, fxIndex|
        var savedParams = ~pluginControllersParams[vstname.asSymbol] ?? [];

        "Adding vstplugin % to servertree".format(vstname).postln;

        ~pluginControllers[fxIndex] = VSTPluginController(
            ~vstSynths[fxIndex]
        );

        // Tell the server to open this plugin in the synth
        ~pluginControllers[fxIndex].open(vstname, action: {
            var setArgs = savedParams.collect{|paramval, index| [index, paramval] }.flatten;

            // Open plugin gui
            ~pluginControllers[fxIndex].editor;

            // Set parameters to old values
            ~pluginControllers[fxIndex].set(*setArgs.postln);

            // Restart autosaver
            Tdef(\vst_param_saver).play;
        }, verbose: true);

    }
};

~initVSTPlugins.value();

ServerTree.add(~initVSTPlugins);

)
3 Likes

And here’s a variation that writes the settings as presets instead

(
s.boot;

s.doWhenBooted{
    SynthDef(\insert, { arg bus;
        ReplaceOut.ar(bus, VSTPlugin.ar(In.ar(bus, 2), 2));
    }).add;

    // May be necessary:
    // VSTPlugin.search();
}
)
(
var pluginNames = [
    "TEOTE.vst3",
    "Elephant.vst3",
];

~sessionName = "myFunkysession";

~autosaveSeconds = 10; // Interval between autosaves
~pluginControllers = Array.newClear(pluginNames.size);
~pluginControllersParams = ~pluginControllersParams ?? {IdentityDictionary.new};

~savePluginParams = {
    ~pluginControllers.do{|pgc|
        var vstname = pgc.info.key;
        var savePreset = ~sessionName ++ vstname;

        "Saving preset for %".format(vstname).postln;
        pgc.savePreset(savePreset);

    }
};

Tdef(\vst_param_saver, {
    loop {
        ~autosaveSeconds.wait;
        ~savePluginParams.value();
    }
});

~initVSTPlugins = {

    ~vstSynths = pluginNames.collect{ Synth(\insert) };

    pluginNames.do{|vstname, fxIndex|
        var savedParams = ~pluginControllersParams[vstname.asSymbol] ?? [];

        "Adding vstplugin % to servertree".format(vstname).postln;

        ~pluginControllers[fxIndex] = VSTPluginController(
            ~vstSynths[fxIndex]
        );

        // Tell the server to open this plugin in the synth
        ~pluginControllers[fxIndex].open(vstname, action: {
            var loadPreset = ~sessionName ++ vstname;

            // Open plugin gui
            ~pluginControllers[fxIndex].editor;

            if(~pluginControllers[fxIndex].info.findPreset(loadPreset).isNil.not, {
                // Set parameters to old values
                ~pluginControllers[fxIndex].loadPreset(loadPreset);
            });

            // Restart autosaver
            Tdef(\vst_param_saver).play;
        }, verbose: true);

    }
};

~initVSTPlugins.value();

ServerTree.add(~initVSTPlugins);

)
1 Like

You can also use getProgramData, store the resulting data in a dictionary and then restore it with setProgramData.