DEVELOPER NOTES: SONAR X3 VST3 Internals

Introduction

SONAR X3 has numerous enhancements and updates to the VST engine, including rich support for the VST3 specification. This article is intended primarily for VST plugin developers to gain a better understanding of the features supported by SONAR and to write plugins that integrate better with SONAR. While the VST3 documentation covers typical information for plugin developers, it does not explain plugin to host integration in much detail. This article attempts to bridge that gap and explain some of the VST3 specific features are implemented in SONAR. Please also see this article that is more intended for end users.

Automatic VST2 to VST3 migration in SONAR

For plugin vendors who have a large base of VST2 plugins and wish to provide a smooth migration path to VST3, its recommended to implement support for automatic migration of a VST2 plugin saved in a prior project to its VST3 equivalent.

This capability will allow SONAR X3 to detect a compatible VST3 plugin while loading a project and automatically transition the VST 2.4 plugin to its compatible VST3 counterpart.  This capability must be supported by both the plugin vendor as well as the host. Currently Waves and Celemony support this protocol with their plugins.

Besides automatic migration, another benefit of this protocol is that SONAR will automatically filter out the compatible VST2 versions from its plugin menus and only show the newer VST3 version of the plugin. This avoids user confusion since there is only one choice to pick from. (This filtering logic can be disabled from the VST preferences in SONAR)

Automatic Migration Process

The logic for automatic migration relies on the VST3 plugin to advertise its compatibility with a VST2 plugin counterpart.
If the VST3 plugin advertises compatibility, SONAR will automatically swap in the VST3 plugin equivalent at load time and the VST3 plugin will get passed the VST2 plugin chunk to load its state from. There are two ways by which SONAR detects compatibility between VST2 and VST3 plugins:

Compatible FUID opcode

VST2 plugins built with Steinberg’s VST3 to VST2 wrapper advertise themselves as VST3 compatible via a custom vendor specific opcode. This opcode allows retrieving the VST3 FUID from a VST2 plugin that supports it. This is how SONAR X3 retrieves the FUID from a VST2:

#define STEINBERG_VST2WWRAPPER (‘stCA’) // vendor specific opcode for steinberg VST2 wrapper opcodes

// Check if there is a compatible VST3 clsid suggested by the VST2 plugin (via the stCA vendorspecific call)

// This is available only if the plugin was a VST3 wrapped with Steinberg’s VST2 wrapper which supports this, or if the VST2 has a custom implementation of this opcode.

// Get compatible VST3 ‘FUID’

Steinberg::TUID clsidVST3Compatible = {0};

effect->dispatcher( effect, effVendorSpecific, STEINBERG_VST2WWRAPPER, ‘FUID’, &clsidVST3Compatible, 0 );

Steinberg::FUID fuid( clsidVST3Compatible );

 

Special custom generated FUID (preferred method)

You can also signal compatibility by using a special custom generated UID for your kVstAudioEffectClass and kVstComponentControllerClass components, based on its VST 2 UniqueID (4 characters) and its Plug-in name like this:

Please refer to convertVST2UID_To_FUID from the VST 3.5.2 SDK for details on how to create the custom FUID:

VstSDK352/doc/vstsdk/faq.html#faqVst2

Note that this method requires some planning since the VST3 FUID needs to be based on the VST2 plugin’s UID and this cannot be changed once plugins are in the field.

How SONAR X3 loads a compatible VST2 plugin into a VST3

The host will call IComponent::setState() and IEditController::setComponentState() passing it a specially formatted FXB stream. This is done by passing a special private ‘VstW’ chunk which is used to tell the VST3 that its loading a VST2 chunk. This ‘VstW’ chunk is followed by the actual VST2 fxBank chunk that contains the persisted data.

The VST3 plugin can extract the VST2 plugin state from this data by reading in the fxBank chunk. Please refer to the topic “Q: How can I support projects which were saved with the VST 2 version of my Plug-in?” in the VST3 SDK from /VstSDK352/doc/vstsdk/faq.html#faqVst2q2

 

Silent audio buffer processing

SONAR X3 supports the silentAudio flag. This is passed to the plugin in the processinfo structure. The plugin should check for buffers that are flagged as silent and skip any expensive processing.

Parameter automation

VST3 has a fairly elaborate implementation for parameter automation with separation of the controller and processor allowing parameters to be sent independently to the user interface and the processor.

Parameter changes are typically stored in a ParameterChangeTransfer ring buffer for thread safety and dispatched to the controller and processor. Parameter changes are normally sent to the plugin via a queue in the Process call.

The host may also send parameters to the plugin when no processing is active via a special “flush parameters” process call. This happens when the audio engine has been stopped in SONAR and the user manipulates an envelope or the user interface widget to change a plugin parameter. In this call numInputs and numOutputs of Steinberg::Vst::AudioBusBuffers are zeroed as well as numSamples. Plugin’s should expect and properly handle this call.

VST3 also supports sample accurate plugin automation. Parameters sent to the plugin are stamped with an intra buffer sample offset for each change, allowing for for sample accurate processing. Plugins should respect the sampleOffset member in the ParameterChange structure whenever possible to allow automation to be buffer size independent.

Plugin Parameter categorization

VST3 plugins can expose categorization for parameters. This is done via the VST3 unit info API. SONAR X3 queries the plugin for its UnitInfo via the call to IUnitInfo::getUnitInfo.

Essentially the plugin needs to expose all its parameter units, specifying a parameter unit ID. This can be specified in a hierarchical way so a particular param unit can have an ID and a parent ID.

From the plugin point of view in the plugin initialize() function it should call addUnit( Unit& unit ) to create the unit definitions for all parameters as many times as necessary for each parameter unit definition. Then when you create the actual parameters (via parameters.addParameter()) you have to reference the unit ID’s defined above. This allows creating a hierarchical representation of all the parameters. 

There is some explanation in the VST3 SDK here:

VstSDK352/doc/vstinterfaces/vst3Units.html

VST Presets

VST3 plugins (and VST2 plugins as well) support two types of presets. Built in factory presets as well as external file based presets. Factory presets or programs as they are often called are exposed as an indexed list and set via a special program change parameter in VST3. (In VST2 this was done via the effSetProgram call).

Factory Presets (programs)

Factory programs can be enumerated using the IUnitInfo::getProgramListInfo API or via the IEditController::getParameterInfo API with the program change parameter ID.
Setting a factory preset is done the same way as any other VST parameter but by using the program change parameter ID (flags = Vst::ParameterInfo::kIsProgramChange)

Bi-Directional setting of programs

Plugin’s must support bi-directional setting of factory programs. i.e. i.e. the user can change a factory preset from SONAR’s UI (the picker at the top of the effects view) or directly from the plugin UI itself.

When a preset is changed from SONAR’s UI, we send a parameter change with the programParameterID (flagged by Vst::ParameterInfo::kIsProgramChange). This call should update the current program as well as update the plugins UI and internal state appropriately.
Additionally a preset may be changed from the plugin UI itself. In this case the plugin update its internal state and additionally send a notification of this preset change to the host application (SONAR). If this notification is not sent, then the host will not be aware of this change and its state will be out of sync with the plugin.
It is not very clearly documented but the supported way to handle bi-directional communications is for the plugin to send a to call begin/endEdit with the program change parameter ID itself when the program is changed from the plugin UI. Alternatively it can call IUnitHandler::notifyProgramListChange. Either of these notifications will allow SONAR a chance to respond to this change and update its UI.  NOTE: in the endEdit call we expect the current preset value to be updated to what the user set it to.
(I have cross checked with Steinberg that this is the desired logic that plugin’s should implement for bi-directional support)

Preset Files

VST settings can also be saved as preset files. In VST3 preset files have the .vstpreset extension. Details about the format can be found in the VST3 SDK.

 

VST Scanning source code and diagnostics

SONAR X3 has a new implementation for VST scanning that allows VST plugins to be scanned and detected automatically in the background. You can read more about it here. The primary purpose of scanning is to allow SONAR to manage and cache the list of available plugins on the system to avoid unnecessary enumeration of plugins each time the application loads.

Compatibility problems may arise during VST scanning if a plugin corrupts the state of the scanner, since the process may hang or stop. SONAR attempts to detect these problems and flag these plugins so that they do not crash future attempts.

In the spirit of transparency and code sharing to aid plugin developers integrating with SONAR X3, here is a link to some VST3 Scan Source Code. The code has been simplified for readability but essentially reflects the primary operations performed by SONAR’s VST3 scanner.

For diagnostic purposes, the VST scanner can also be run outside SONAR from the command line. This allows capturing a log of the scan process.  Here are some instructionsto capture logging info from the scanner.

—————————————————————————————————

1) Manually delete the plugin VST Inventory entry (or entries) at

HKEY_CURRENT_USER\Software\Cakewalk Music Software\SONAR Producer\Cakewalk
VST X64\Inventory\c:/program files/cakewalk/vstplugins/<dllname.dll>

or

HKEY_CURRENT_USER\Software\Cakewalk Music Software\SONAR Producer\Cakewalk
VST\Inventory\c:/program files/cakewalk/vstplugins/<dllname.dll>

2) Open command prompt as admin (Windows + x in Windows 8 and then click
Command Prompt (admin))

3) Navigate to the Shared Utilities directory. Keep in mind this can
change between systems. For me, I had to type the following:

cd C:\Program Files\Cakewalk\Shared Utilities

Make sure to change the path depending on the setup.

4) Press Enter. It should then display that directory.

5) Type in the following, verbatim, and press enter (easier to copy and
paste… note you must paste by right-clicking):

VstScan.exe/Log/VSTRegPerUser/VSTRegKey:”Software\Cakewalk Music Software\SONAR Producer\Cakewalk VST X64″

(keep in mind this might change if you are running 32-bit SONAR. If so, it would be:

VstScan.exe/Log/VSTRegPerUser/VSTRegKey:”Software\Cakewalk Music Software\SONAR Producer\Cakewalk VST”

6) Wait for the Scan to complete

7) Afterwards, navigate to Shared Utilities folder and look for “VstScan.log”.  Note: if the log file
is empty you may have to manually register ttslogger.dll from the folder “C:\Program Files\Cakewalk\Shared Utilities” using regsvr32 ttslogger.dll.

 

Support

If you are a third-party developer and would like to contact Cakewalk regarding plug-in compatibility questions, please contact us via this form 

Summary

Implementing automatic migration greatly simplifies the process for users to migrate their projects containing VST2 plugins to VST3 versions of the same plugins.

By default SONAR will automatically filter compatible VST2 versions of plugins from its plugin menus and only show the newer VST3 version of the plugin.

The automatic migration protocol is not proprietary to SONAR and works in any VST3 host that supports it.

Changelog:

1/30/04: Added section on VST presets

1/25/04: Added information on scan diagnostics

 

Published by

Noel Borthwick [Cakewalk]

Chief Technology Officer