Mittwoch, 27. Februar 2013

Teile eines VST Plugins

Heyho,

In Teil eins unseres Workshops geht es mal darum, wie so ein VST Plugin aufgebaut ist.
Erstelle wir zuerst mal ein neues Projekt.

Wie das geht steht auf

 http://teragonaudio.com/article/Making-a-VST-plugin-from-scratch-with-Xcode.html

Eine grandiose Resource ;)

Wenn ihr das geschafft habt, ist das meiste schon getan.
Jetzt geht ihr auf den Tree in der linken Seite und klickt  ctrl + apfel auf source.
Dann auf "add existing file". Dann navigiert ihr zu eurem VST SDK. Bei "public.sdk" gibts den Ordner "samples". Da drinnen gibts 2 Files: again.h und again.cpp.
Beide Dateien auswählen und dem Projekt hinzufügen. WICHTIG: IN DAS PROJEKT KOPIEREN!

Gut. Anhand dieses Beispiels werden wir nun das Plugin veranschaulichen.

Beginnen wir mit der Datei "again.h":
In dieser Datei wird mal alles deklariert, was wir in unserer again.cpp Datei dann verwenden wollen.


//-------------------------------------------------------------------------------------------------------
// VST Plug-Ins SDK
// Version 2.4 $Date: 2006/11/13 09:08:27 $
//
// Category     : VST 2.x SDK Samples
// Filename     : again.h
// Created by   : Steinberg Media Technologies
// Description  : Stereo plugin which applies Gain [-oo, 0dB]
//
//  2006, Steinberg Media Technologies, All Rights Reserved
//-------------------------------------------------------------------------------------------------------

#ifndef __again__
#define __again__

//- Wir fügen die externe Klasse audioeffectx.h hinzu. Ohne die geht gar nix ;)

#include "public.sdk/source/vst2.x/audioeffectx.h"

//-------------------------------------------------------------------------------------------------------
//- Erstellen der Klasse, welche auf AudioEffectX zugreift. 
//- Der Name der Klasse ist AGain.

class AGain : public AudioEffectX
{
public:
AGain (audioMasterCallback audioMaster);
~AGain ();

//- Der Teil in dem dann unser Prozess passiert und die eigentliche DSP Arbeit.Für den Anfang...
// Processing
virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames);

//- Nun folgen die Anweisungen für den Programm Namen. Das kennt ihr aus den sogenannten "Presets" eines VST Plugins

// Program
virtual void setProgramName (char* name);
virtual void getProgramName (char* name);
//- Die Parameter: set, get, das Label, das Display, der Name der Parameter 
// Parameters
virtual void setParameter (VstInt32 index, float value);
virtual float getParameter (VstInt32 index);
virtual void getParameterLabel (VstInt32 index, char* label);
virtual void getParameterDisplay (VstInt32 index, char* text);
virtual void getParameterName (VstInt32 index, char* text);

//- Der Name des Plugins, dein Company Name, plugin ID und Version

virtual bool getEffectName (char* name);
virtual bool getVendorString (char* text);
virtual bool getProductString (char* text);
virtual VstInt32 getVendorVersion ();

//- Der geschützte Teil des plugins: Hier kommen unsere z.B. fader, values etc. die wir verwenden wollen. 
protected:
float fGain ;
char programName[kVstMaxProgNameLen + 1];
};

#endif


Das wars schon mit der again.h Datei! Mehr gibt es dazu vorerst nicht zu sagen.
Da wir nur einen Parameter im Plugin haben, verzichten wir gezielt auf "enum". Falls du nicht weißt was das ist, dann zerbrich dir an dieser Stelle nicht den kopf darüber. Dazu etwas später mehr.


Weiter gehts mit der "again.cpp" Datei!



//-------------------------------------------------------------------------------------------------------
// VST Plug-Ins SDK
// Version 2.4 $Date: 2006/11/13 09:08:27 $
//
// Category     : VST 2.x SDK Samples
// Filename     : again.cpp
// Created by   : Steinberg Media Technologies
// Description  : Stereo plugin which applies Gain [-oo, 0dB]
//
//  2006, Steinberg Media Technologies, All Rights Reserved
//-------------------------------------------------------------------------------------------------------

//- WICHTIG: Die Header Datei includen!!!

#include "again.h"


//-------------------------------------------------------------------------------------------------------

//- Erstelle eine neue Effekt Instanz

AudioEffect* createEffectInstance (audioMasterCallback audioMaster)
{
return new AGain (audioMaster);
}

//-------------------------------------------------------------------------------------------------------

//- Initialisiere das plugin

AGain::AGain (audioMasterCallback audioMaster)
: AudioEffectX (audioMaster, 1, 1) // 1 Programm, 1 Parameter->(fGain)!!
{
setNumInputs (2); // Zwei Eingangs Kanäle
setNumOutputs (2); // Zwei Ausgangs Kanäle
setUniqueID ('cis1'); // 4 Zeichen, zur Identifikation des Plugins im Host
canProcessReplacing (); // Unterstützung der Replacing Funktion
// canDoubleReplacing (); //mit doppelter Präzision - nicht so wichtig im Moment

fGain = 1.f; // fGain auf höchsten Wert initialisieren: 0 dB

vst_strncpy (programName, "Erser Eintrag!", kVstMaxProgNameLen); // Programmname
}

//- den Deconstructor vergessen wir mal am Anfang.
//-------------------------------------------------------------------------------------------------------
AGain::~AGain ()
{
// nothing to do here
}

//-------------------------------------------------------------------------------------------------------
//- Wir setzen unseren Programmnamen

void AGain::setProgramName (char* name)
{
vst_strncpy (programName, name, kVstMaxProgNameLen);
}

//-----------------------------------------------------------------------------------------
//- Wir lesen unseren Programmnamen
void AGain::getProgramName (char* name)
{
vst_strncpy (name, programName, kVstMaxProgNameLen);
}


//-----------------------------------------------------------------------------------------

//- Setzen der Parameter: Hier ist schon der erste kleine Unterschied zu dem Steinberg Template: Für den Fall, dass mehrere Parameter hinzugefügt werden sollen, habe ich hier gleich von Anfang an eine Switch Anweisung erstellt. Das ist wichtig für das korrekte erkennen und verarbeiten der Parameter. Ich gehe davon aus, dass ihr C++ ein wenig beherrscht und werde eine Switch Anweisung nicht näher erklären ;)
void AGain::setParameter (VstInt32 index, float value)
{
switch(index){
case 0: fGain = value;break;

}
}

//-----------------------------------------------------------------------------------------

//- Auslesen der Parameter - ebenfalls mit einer Switch Anweisung
float AGain::getParameter (VstInt32 index)
{
float v = 0;

switch(index){
case 0: v = fGain;break;
}
return v;
}

//-----------------------------------------------------------------------------------------

//- Der Name unseres Parameters fGain
void AGain::getParameterName (VstInt32 index, char* label)
{
switch(index){
case 0: vst_strncpy (label, "Gain", kVstMaxParamStrLen);break;
}
}

//-----------------------------------------------------------------------------------------

//- Anzeigen des veränderten Werts von fGain. Zu beachten ist hier die fertige Klasse dB2string(). Diese wandelt mir den angezeigten "float" Standard Wert 0-1 zu -oo zu 0 dB um. Klasse, nicht? :p  Du kannst dich ein wenig spielen und "dB2string" zu "float2string" umschreiben und schauen was dann passiert. Richtig: Es wir eine Fließkommazahl anstatt der dB angezeigt.

void AGain::getParameterDisplay (VstInt32 index, char* text)
{
switch(index){
case 0: dB2string (fGain, text, kVstMaxParamStrLen);break;
}
}

//-----------------------------------------------------------------------------------------
//- Natürlich wollen wir auch wissen was wir da ausgelesen haben. In diesem Fall: Dezibel
void AGain::getParameterLabel (VstInt32 index, char* label)
{
switch(index){
case 0: vst_strncpy (label, "dB", kVstMaxParamStrLen);break;
}
}

//------------------------------------------------------------------------

//- Dieser Teil gibt den Namen des Plugins aus. Hier: "Gain"
bool AGain::getEffectName (char* name)
{
vst_strncpy (name, "Gain", kVstMaxEffectNameLen);
return true;
}

//------------------------------------------------------------------------
//- Wie heisst unser Plugin? 
bool AGain::getProductString (char* text)
{
vst_strncpy (text, "Gain", kVstMaxProductStrLen);
return true;
}


//------------------------------------------------------------------------

//- DEIN Firmenname steht hier
bool AGain::getVendorString (char* text)
{
vst_strncpy (text, "YOUR COMPANY", kVstMaxVendorStrLen);
return true;
}

//-----------------------------------------------------------------------------------------

//- Unsere Produktversion. Wenn du z.B. an Version 1.1 arbeitest, gibst du bei return einfach "1100" ein! So einfach ist das ;)

VstInt32 AGain::getVendorVersion ()
return 1000; 
}

//-----------------------------------------------------------------------------------------

//- Jetzt kommen wir zum interessanten Teil, nachdem wir schon jede Menge an Code geschrieben haben. die Funktion processReplacing! 
void AGain::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames)
{
    float* in1  =  inputs[0]; //- Zeiger in1 auf input1
    float* in2  =  inputs[1]; //- das selbe auf in2
    float* out1 = outputs[0]; //- und auf output1
    float* out2 = outputs[1]; //- das selbe


//- Nun gibt es viele Möglichkeiten wie man die Daten verarbeitet. Hier verwenden wir ma eine while Schleife. Diese sagt folgendes (ungefähr): Während unsere Samples größer oder gleich 0 sind berechne den Inhalt! 

    while (--sampleFrames >= 0)
    {
        //- In der Schleife multiplizieren wir nun unsere Eingänge mit unserem Gain Fader. Vergesst nicht: hier geht es um einsen und nullen. Das heisst, unser Eingang ist immer EINS. Wenn  wir nun unseren Gain Fader auf die Hälfte einstellen, dann gibt er 0.5 zurück. Das hat nichts mit unserer Dezibel Klasse zu tun. Diese ist nur für unser Display verantwortlich! Wir bekommen also den Wert 1*0.5 = 0.5 zurück. 
        (*out1++) = (*in1++) * fGain;
        (*out2++) = (*in2++) * fGain;
    }
}




So das wars eigentlich schon. Wenn ihr nun in eurer IDE alles richtig gemacht habt, dann könnt ihr das mal kompilieren und das Plugin in euren VST Ordner kopieren.

Im nächsten Tutorial basteln wir uns eine kleine Stereoverbreiterung mit Phasenkorrektur!


Chris


  

Keine Kommentare:

Kommentar veröffentlichen