!j development
Programming Article:

Designing VST plugins completely 'visual' with Borland® C++Builder®

by !jdev
©2003-2006 !j development division audio
This article is copyrighted. All rights reserved. Don't publish entirely or parts without explicit permission.

Vision: Imagine, you could develop native VST plugins based on a modular visual component library with drag and drop and complete access to the C/C++ source code.



The image above shows our VCL extension inside C++Builders component palette. About 25 components and controls encapsulate the entire VST 2.3 SDK including the VSTGUILib 2.2.

Introduction

We have seen so many Visual Component Library (VCL®) extensions for Borland C++Builder® on the Windows® platform, but not even one for building VST® plugins with Steinbergs Virtual Studio Technology. There may be some stuff available for Delphi, but not as a complete integration of the VST SDK and even no one such a concept for C++Builder.

Normally one uses Microsoft's® Visual C++® to build VST plugins on Windows, because the core Interface (provided by Steinberg®) is supplied for this compiler. This leads in some difficulties - even for beginners - because the core VST interface is pure (platform independent) C/C++ hack and the development of the graphical user interface (GUI) for VST plugins must be done also with rough source code based programming and linked resource files.
The current state is absolutely unsatisfactory, because the developer has no possibility to "see" what he is designing in realtime. He codes GUIs rather than design it. This is time consuming and the result often somehow "ugly".

The developer also has to spend quite allot time to understand the often unsatisfactory documented VST and VSTGUILib header files and to understand all the nifty things around the interfaces. One has often to develop a minimalist debug-able host application to debug and somehow comfortable design the plugins interface, because most of the hosts applications don't support designing and debugging of plugins directly or make it very difficult. Plugins are even not directly executable and need a host application to execute. This finally results in endless compiling, loading and testing the plugins on the host applications on each little change of the plugins source code. Especially the GUI development can lead into pure horror with this.

Note: There are some other visual design techniques out there, where the user can create VST plugins on demand by using modular elements. But the result is neither a native plugin nor has the user access to the source code. Mostly the possibilities are limited by the availability of third party components and the direct support and implementation of such building systems. Those techniques are not part of the discussion here.

So it would be a good thing to do something with the "magic" Borland Visual Programming techniques, where you simply drag and drop some components on a form and compile it to a ready to use plugin application. In this way, the developer can concentrate to the really important things, like DSP coding and the (realtime) visual design of the user interface. Of course this will be neither platform independent, nor compiler independent but very productive with platform specific development. In this case Windows specific.

Borland's compilers ( or better: Integrated Development Environments (IDEs) ) do an excellent job in supporting developers with true "Visual Design". No matter which Borland IDE you use (Delphi or C++Builder), all use the VCL or similar component libraries. The VCL has its roots on Object Pascal (initially developed for Delphi) and is also completely implemented into C++Builder. The VCL is an extendable component based code library with full designtime support.

The entire Borland concept is in our opinion somehow better than the Microsoft Visual Basic® or Visual C++® or C# concept, because the Borland component system is not limited to external COM objects (ActiveX) or Microsoft's new .NET Framework. You design components more in the manner of "reusable code" or code libraries, which can be directly compiled into the final applications and plugins.

The clou is, that you can use also VCL components written in Object Pascal inside C++Builder and write your own either in Object Pascal or even C/C++ ( this is not possible vice versa with Delphi ). Reuse of code libraries, visual or none-visual is a cake with Borland C++Builder and predestined for our project. Nevertheless our components project will be designed 100% in pure C++.

The Project

Step1: To realize our project, we need at first to encapsulate Steinbergs core VST Interface.
The plan was to design easy to use modular components, which can be dropped to a standard VCL form (the window). The components (4 connectable base components) encapsulate the entire skeleton of a ready to use VST 2.3 plugin. This is also supports VST and MIDI events and synthesizers.

The four base VST components are:

- TVSTEffectX, the effect base component
- TVSTEventDispatcher, optional component to provide VSTEvent, VSTMidiEvent support
- TVSTSysExProvider, an additional extension to provide SysEx support with VST
- TVSTParameter, the base component for handling the parameters of a VST plugin

NEW:

A few days after the release of the Steinberg VST Module Architecture, we have started the development of a new component:

- TVSTModule, the new MIDI module base component

With this component and the VSTGUI components below, you can design new MIDI plugins for Steinberg's VST Module Architecture. The usage differs not so much from the development of normal VST plugins with our component package. You design MIDI modules completely visual with C++Builder, using the VSTGUILib in realtime.
We also prepare a startup Template for VST Module plugins.

Note: The "T" before the components class name is a Borland VCL naming convention.

The Template

The project requires at least, that C++Builder is able to generate a DLL project, which is 100% compatible with the host applications (mostly developed with Microsoft's compilers). Off course is C++Builder able to do that.

We generate a DLL template project in Visual C++ style, include VCL support and add some initializations code to prepare the VST entry point, the "main" function. Then we add a module definition file to rename the per default generated "_main" export symbol to "main". This is necessary, because C++Builder adds normally an underscore to export functions. But the hosts scan only for "main" functions and not "_main".

Inside the main function we initialise our main component and create the audio effect class with its own VCL driven Editor. ( Previously we have included a Form (window) to the project dropped our VST base components on this Form. )

This is all. If we compile the project, we have at least a complete VST plugin with its own window, which does actually nothing special, but prepares all the functionality needed for the VST audio process, for instance MIDI automation, programs and banks, SysEx support multi output and so on. All aspects of our VST plugin can now be edited completely "visual" with C++Builders property editor.

//---------------------------------------------------------------------------
// ©2003 !j development VST®ToolKit. All rights reserved.
// BUFFERSCOPE 2 for Borland C++Builder® 5/6
//---------------------------------------------------------------------------

#include <vcl.h>
#include <windows.h>
#pragma hdrstop
#pragma option -a8

/*---------------------------------------------------------------------------
VST SDK (Version 2.3)
©1999, Steinberg Soft und Hardware GmbH, All Rights Reserved.
©2002, Steinberg Media Technologies AG, All Rights Reserved.
©2003, Steinberg, The Audio Group of Pinnacle Systems Inc.
All Rights Reserved.
---------------------------------------------------------------------------*/

#include "AEffect.h"
#include "AudioEffect.cpp"
#include "audioeffectx.cpp"

#include "Unit1.h"
//---------------------------------------------------------------------------
static AudioEffect *effect = NULL;
//---------------------------------------------------------------------------

extern "C"{ AEffect* __cdecl main (audioMasterCallback audioMaster); }
AEffect *main (audioMasterCallback audioMaster)
{
    if ( !audioMaster(0, audioMasterVersion, 0, 0, 0, 0) )
    return NULL;


    TEditor* Editor = new TEditor(NULL);
    if (Editor)
    {
        effect = Editor->VSTPlugin->Create(audioMaster);
        if (!effect)
        {
            delete Editor;
            ShowMessage("VSTPlugin::main: The effect class for BufferScope2 could not be \n\                created.");
            return NULL;
        }
        return effect->getAeffect();
    }
    ShowMessage("VSTPlugin::main: The editor class for BufferScope2 could not be created.");
    return NULL;
}

//---------------------------------------------------------------------------
#pragma argsused
void* hInstance = NULL;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
    hInstance = hinstDLL;
    return TRUE;
}
//---------------------------------------------------------------------------


This works, because our underlying VST component is a really complex wrapper class, which has some heavy built in logic to do all the generic stuff for us.

But the principe should be very clearly here: We want to provide an easy to use "drag and drop" component and a simple generic template to make building VST plugins on Microsoft Windows with Borland C++Builder a snap.

This can be the result of our ready to use project. You see the Borland C++Builder 5 visual designing a VST plugin, including a main window, a separate about box and a trace window for special debug diagnostics, all design based on the standard VCL and our extensions to it. The example shows the downloadable example application called "BufferScope2", which is a simple but impressive MIDI automate able volume leveler effect with inbuilt stereo oscillograph and error tracing. The plugin supports all basic Windows elements, like windows, popup menus, text fields, hints, list boxes and so on.

Step 2: To complete our component library for VST, we have also developed a VCL extension with graphical controls based on the Steinberg VSTGUILib, an optional GUI framework for VST plugins. We will encapsulate and extend the about 20 controls for a very easy usage while designtime with C++Builder. The user drops those controls on a VSTCFrame base component on the C++Builder Form and designs the visual appearance of the entire plugin GUI in WYSIWYG mode.

The controls will be connected with the base plugin components via the C++Builder object inspector and only a few lines of additional code create a very complex functionality for our plugin. The encapsulated objects are fully accessible while runtime, so the core developer works like usually with the VST SDK and VSTGUILib code.
Additionally we have extended the possibilities of the VSTGUILib to load JPEG images while design- and runtime from files. Skin able interfaces are easy to implemented, based on this technique.

Never was is so easy to develop new plugins for VST. What formerly was done in months, we can do now inside a few hours.

Following VSTGUILib components are available:

- TVSTCFrame, base component for all VSTGUI controls
- TVSTCViewContainer, encapsulates CViewContainer for designtime support
- TVSTCCanvas, encapsulates CDrawContext for designtime support
- TVSTCKnob, encapsulates CKnob for designtime support
- TVSTCOnOffButton, encapsulates CCOnOffButton for designtime support
- TVSTCParamDisplay, encapsulates CParamDisplay for designtime support
- TVSTCTextEdit, encapsulates CTextEdit for designtime support
- TVSTCOptionMenu, encapsulates COptionMenu for designtime support
- TVSTCAnimKnob, encapsulates CAnimKnob for designtime support
- TVSTCVerticalSwitch, encapsulates CVerticalSwitch for designtime support
- TVSTCHorizontalSwitch, encapsulates CHorizontalSwitch for designtime support
- TVSTCRockerSwitch, encapsulates CRockerSwitch for designtime support
- TVSTCMovieBitmap, encapsulates CMovieBitmap for designtime support
- TVSTCMovieButton, encapsulates CMovieButton for designtime support
- TVSTCAutoAnimation, encapsulates CAutoAnimation for designtime support
- TVSTCVerticalSlider, encapsulates CVerticalSlider for designtime support
- TVSTCHorizontalSlider, encapsulates CHorizontalSlider for designtime support
- TVSTCSpecialDigit, encapsulates CSpecialDigit for designtime support
- TVSTCKickButton, encapsulates CKickButton for designtime support
- TVSTCSplashScreen, encapsulates CSplashScreen for designtime support
- TVSTCVuMeter, encapsulates CVuMeter for designtime support

Note: It is also possible to use other GUI libraries for our plugin. The "Bufferscope2" plugin uses for instance our !j development PlusControls library, a high quality GUI framework, based on Microsoft's new GDI+ interface. There are much more things possible (i.e. antialiased text and vector graphics and real alpha blending) than the platform independent VSTGUILib can offer.

Step 3: A VST plugin is not much worth, if we have no variety of basic audio processing classes. Finally we want to code new audio plugins, which are somehow useful. So we design additionally a independent VCL extension with some ready to use DSP algorithms and ready to use complete "engines". This library should be extendable and independent from our VST plugin components. One can imagine the DSP Lib as a kind of modular DSP source code components.

For a basic set of DSP opcodes, the following components are currently being adapted:

- TBuffer,
- TInterpolator,
- TMixer,
- TPitchConverter,
- TVAOscillators,
- TWavetable,
- TWavetableOscillator,
- TSVFilter6db,
- TSVFilter12db,
- TSVFilter24db,
- TLFO,
- TEnvelope,
- TModMatrix,
- TFFT,
- TReverb,
- TDelay,
- TChorus,
- TPhaser,
- TDistortion,
- TLimiter,
- TEqualizer,
- ...



One can download the compiled BufferScope2 visual example effect plugin created with C++Builder 5: BufferScope2.dll
Tip: Use the right mouse button to invoke an option menu for several operation modes.

There is also a demonstration application for the different widgets of the VSTGUI lib. This application is also created with C++Builder 5: VSTControls.zip
This program includes a first demonstration of our VarioSkin© tool for the CBuilder VST component library described in this article. An example *.ini file for loading a generic user interface for an imaginary plugin (including the images) is attached.