Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build a minimal VST3 host in C++

Tags:

c++

vst

I'm struggling to find a basic example on how to set up a minimal plugin host with VST 3.x SDK. The official documentation is absolutely criptic and brief, I can't get anywhere. I would like to:

  1. understand the minimal setup: required headers, interfaces to implement, ...;
  2. load a VST3 plugin (no fancy GUI, for now);
  3. print out some data (e.g. plugin name, parameters, ...).

That would be a great start :)

like image 314
Ignorant Avatar asked Jun 29 '14 16:06

Ignorant


People also ask

What is a VST3 host?

VST 3 Plug-in Development Host by Steinberg is an Audio Plugin Host and a Standalone Application for macOS and Windows. It functions as a Standalone Application.

How long does it take to make a VST plugin?

Depending on the scale of the project, the prototyping stage of creating vst plugins could last anywhere from a few hours to weeks or months. To make a vst plugin, one needs to first create and compile the code, this will be done in an IDE (integrated development environment).


Video Answer


2 Answers

Yeah, VST3 is rather mysterious and poorly documented. There are not many good examples partially because not many companies (other than Steinberg) actually care about VST3. But all cynicism aside, your best bet would be to look at the Juce source code to see their implementation of a VST3 host:

https://github.com/julianstorer/JUCE/blob/master/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp

There's a few other VST3-related files in that package which are worth checking out. Anyways, this should at least be enough information to get get you started with a VST3 host.

It's worth noting that Juce is GPL (unless you pay for a license), so it's a big no-no to borrow code directly from it unless you are also using the GPL or have a commercial license. Just a friendly reminder to be a responsible programmer when looking at GPL'd code on the net. :)

like image 74
Nik Reiman Avatar answered Sep 23 '22 23:09

Nik Reiman


Simple VST3 hosts already exist in the VST SDK. It is not difficult to augment them, but there are some things to keep in mind.

  • The samples under public.skd/vst-hosting in the VST SDK contain an EditorHost and and AudioHost. The first handles the GUI, the second handles the effect (the signal processing). You can combine the two. Neither is a full implementation.
  • VST objects are COM objects and so you have to make sure to set up the application context correctly, so that your COM objects persist between calls. EditorHost and AudioHost both do that in a couple of lines in a global context variable (look for pluginContext).
  • If you use separate calls to load and unload effects, process data, and so on, you have to keep COM object pointers, so they are not unloaded. For example, you may be tempted to ignore the Steinberg::Vst::Module module, since you don't need it once the effect is loaded, but you would have to keep a pointer to it somewhere globally or in the main application thread. If not, the automatic unloading of that pointer will also unload the plugin as well and subsequent calls to the plugin will fail.
  • The construction of VST effects is relatively simple. They consist of a component (the effect) and a controller (the GUI). Both are instantiated when Steinberg::Vst::PlugProvider is loaded (some effects do not have a GUI). Both examples above load a plugprovider. Once you load a plugprovider, you are essentially done.

The following code is sufficient to load a plugprovider (the whole effect). Assume returning -1 means an error:

std::string error;
std::string path = "somepath/someeffect.vst3";

VST3::Hosting::Module::Ptr module = 
    VST3::Hosting::Module::create(path, error);
if (! module)
    return -1;

IPtr<PlugProvider> plugProvider; 
VST3::Optional<VST3::UID> effectID = std::move(uid);
for (auto& classInfo : module->
    getFactory().classInfos())
{
    if (classInfo.category() == kVstAudioEffectClass)
    {
        if (effectID)
        {
            if (*effectID != classInfo.ID())
                continue;
        }
            plugProvider = owned(new 
                PlugProvider(module->getFactory(), 
                classInfo, true));
            break;
    }
}

if (! plugProvider)
    return -1;

After this, plugProvider->getComponent() and plugProvider->getController() give you the effect and GUI. The controller has to be displayed in a window, of course, which is done in EditorHost. These are the implementations of IComponent,IAudioProcessor and IEditController in the VST SDK.

The source/vst/testsuite part of the VST SDK will show you the full functionality of both of these parts (it will essentially give you the functional calls that you can use to do everything you want to do).

Note the module and plugprovider loaded in the code above. As mentioned above, if you don't keep the module pointer, there is no guarantee the plugprovider pointer will survive. It is difficult to keep track of what gets released when in the VST SDK.

like image 27
user12438479 Avatar answered Sep 23 '22 23:09

user12438479