AudioEffect

#include <AudioEffect.hpp>
class AudioEffect;

Needs to be defined by the audio effect and is called to create the audio effect object instance.

Universal Basic Methods

There is a basic set of methods that your plug should support (with *). These are all found in the AudioEffect class.

Version 1.0
    Host -> Plug

setParameter *
getParameter *
process *
processReplacing *
dispatcher
open
close
getProgram *
setProgram *
setProgramName *
getProgramName *
getParameterLabel *
getParameterDisplay *
getParameterName *
getVu
getChunk
setChunk
setSampleRate
setBlockSize
suspend
resume


Internal / Tools

getAeffect
setEditor
setUniqueID
setNumInputs
setNumOutputs
hasVu
hasClip
canMono
canProcessReplacing
setRealtimeQualities
setOfflineQualities
setInitialDelay
programsAreChunks
dB2string
Hz2string
ms2string
float2string
long2string


Plug -> Host

setParameterAutomated
getSampleRate
getBlockSize
getMasterVersion
getCurrentUniqueId
masterIdle
isInputConnected
isOutputConnected




Constructor and Destructor


AudioEffect

AudioEffect (audioMasterCallback audioMaster, long numPrograms, long numParams);

Create an AudioEffect object. The constructor of your class is passed a parameter of the type audioMasterCallback. The actual mechanism in which your class gets constructed is not important right now, but effectively your class is constructed by the hosting application, and the host passes an object of type audioMasterCallback that handles the interaction with the plug-in. You pass this on to the base class's constructor and then can forget about it.

A few flags, and identifiers must be set and you declare your class's input & output requirements at construction time.

audioMaster
numPrograms The number of programs.
numParams The number of parameters.

Example :

MyPlug::MyPlug (audioMasterCallback audioMaster)
: AudioEffectX (audioMaster, 1, 1)
// 1 program, 1 parameter only
{
myParameter = 1.0;
// stereo in :
setNumInputs (2);

// stereo out :
setNumOutputs (2);

// identify
// (you must change this for other plugs!) :
setUniqueID ('MyPl');

// makes sense to feed both inputs
// with the same signal :
canMono ();

// supports both accumulating
// and replacing output :
canProcessReplacing ();

// default program name :
strcpy (programName, "Default");
}


See also :


~AudioEffect

virtual ~AudioEffect();

Destroy an AudioEffect object.

Example :

MyPlug::~MyPlug ()
{
// nothing to do here
}

Processes


Processes

Never call any Mac OS 9 functions (or other functions which call into the OS) inside your audio process function; this will crash the system when your plug is run in MP (multiprocessor) mode. if you must call into the OS, you must use MPRemoteCall () (see Apples' documentation), or explicitly use functions which are documented by Apple to be MP safe.

On Mac OS X read the system header files to be sure that you only call thread safe functions.


process

virtual void process (float **inputs, float **outputs, long sampleFrames);

Audio processing in the plug is accomplished by one of 2 methods, namely process, and processReplacing. The process method must be provided, while the second one is optional (but it is highly recommended to always implement both methods). While process takes input data, applies its pocessing algorithm, and then adds the result to the output (accumulating), processReplacing overwrites the output buffer. The host provides both input and output buffers for either process method.

The reasoning behind the accumulating version (process) is that it is much more efficient in the case where many processors operate on the same output (aux-send bus), while for simple chained connection schemes (inserts), the replacing method is more efficient.

The plug has to over-ride both these two possible member functions that actually do the work. These are repeatedly called by the host application, each time with a new block of data.

inputs An array of pointers to the data.
outputsuts An array of pointers to where the datacan be written to.
sampleFrames How big the block is.

Example :

void MyPlug::process (float **inputs, float **outputs, long sampleFrames)
{
float *in1 = inputs[0];
float *in2 = inputs[1];
float *out1 = outputs[0];
float *out2 = outputs[1];

while (--sampleFrames >= 0)
{
(*out1++) += (*in1++);
(*out2++) += (*in2++);
}
}

See also :


processReplacing

virtual void processReplacing (float **inputs, float **outputs, long sampleFrames);

Audio processing in the plug is accomplished by one of 2 methods, namely process, and processReplacing. The process method must be provided, while the second one is optional (but it is highly recommended to always implement both methods). While process takes input data, applies its pocessing algorithm, and then adds the result to the output (accumulating), processReplacing overwrites the output buffer. The host provides both input and output buffers for either process method.

The reasoning behind the accumulating version (process) is that it is much more efficient in the case where many processors operate on the same output (aux-send bus), while for simple chained connection schemes (inserts), the replacing method is more efficient.

inputs An array of pointers to the data.
outputsuts An array of pointers to where the datacan be written to.
sampleFrames How big the block is.

Example :

void MyPlug::processReplacing (float **inputs, float **outputs, long sampleFrames)
{
float *in1 = inputs[0];
float *in2 = inputs[1];
float *out1 = outputs[0];
float *out2 = outputs[1];
while (--sampleFrames >= 0)
{
(*out1++) = (*in1++);
(*out2++) = (*in2++);
}
}

See also :


Parameters

Parameters are the individual parameter settings the user can adjust. A VST host can automate these parameters.


setParameter

virtual void setParameter (long index, float value);

Set parameter <index> to <value>.

index The index of the parameter.
value A float between 0.0 and 1.0 inclusive.

Note :

Parameter values, like all VST parameters, are declared as floats with an inclusive range of 0.0 to 1.0. How data is presented to the user is merely in the user-interface handling. This is a convention, but still worth regarding. Maybe the VST-host's automation system depends on this range.

Example :

void MyPlug::setParameter (long index, float value)
{
switch (index) {
case kMyTag :
myParameter = value;
break;
default :
break;
}
}

getParameter

virtual float getParameter (long index);
index The index to the parameter.
return The value of the parameter. Should be a float between 0.0 and 1.0 inclusive.

Return the value of parameter <index>.

Example :

float MyPlug::getParameter (long index)
{
float value = 0.0;

switch (index)
{
case kMyTag :
value = myParameter;
break;
default :
break;
}
return (value);
}

setParameterAutomated

virtual void setParameterAutomated (long index, float value);

Called after a control has changed in the editor, as from CControlListener's valueChanged method.

index The index of the parameter.
value A float between 0.0 and 1.0 inclusive.

Note :

An important thing to notice is that if the user changes a parameter in your editor (which is out of the host's control Ðbecause we are not using the default string based interface), you should call... setParameterAutomated (index, (float) newValue);. This ensures that the host is notified of the parameter change, which allows it to record these changes for automation.

Note that setParameterAutomated calls the plug's setParameter, and in the case of an AEffGuiEditor, the editor's setparameter will also be called after setParameterAutomated.

Example :

void MyPlugEdit::setParameter (long index, float value)
{
MyPlug::setParameter (index, value);

if (editor)
(editor)->setParameter (index, value);
}

See also :


getParameterDisplay

virtual void getParameterDisplay (long index, char *text);

Stuff <text> with a string representation ("0.5", "-3", "PLATE", etc...) of the value of parameter <index>.

index The index of the parameter.
text A string.

Example :

void MyPlug::getParameterDisplay (long index, char *text)
{
float2string (fMyParameter, text);
}

getParameterName

virtual void getParameterName (long index, char *text)

Stuff <text> with the name ("Time", "Gain", "RoomType", etc...) of parameter <index>.

index The index of the parameter
text A string up to 8 chars.

Example :

void MyPlug::getParameterName (long index, char *label)
{
	if (index == 0)
		strcpy (label, "my name0");
	else if (index == 1)
		strcpy (label, "my name1");
}

getParameterLabel

virtual void getParameterLabel(long index, char *label)

Stuff <label> with the units in which parameter <index> is displayed (i.e. "sec", "dB", "type", etc...).

index The index of the parameter
text A string up to 8 chars.

Example :

void MyPlug::getParameterLabel (long index, char *label)
{
if (index == 0)
strcpy (label, "my label0");
else if (index == 1)
strcpy (label, "my label1");
}

Programs

Programs are a complete set of parameters that refer to the current state of the plug-in. Banks are a collection of Program objects.


getProgram

virtual long getProgram ();

Return the index to the current program.

return The number of the current program.

setProgram

virtual void setProgram (long program);

Set the current program to <program>.

program The number of the program.

Note :

Don't forget to call this from the constructor.


setProgramName

virtual void setProgramName (char *name);

Stuff the name field of the current program with <name>. The program name is displayed in the rack, and can be edited by the user.

name A string up to 24 chars.

Note :

Please be aware that the string lengths supported by the default VST interface are normally limited to 24 characters. If you copy too much data into the buffers provided, you will break the host application.

Example :

void MyPlug::setProgramName (char *name)
{
strcpy (myProgramName, name);
}

getProgramName

virtual void getProgramName (char *name);

Stuff name with the name of the current program.

name A string at least 24 chars.

Example :

void MyPlug::getProgramName (char *name)
{
strcpy (name, programName);
}

dispatcher

virtual long dispatcher (long opCode, long index, long value, void *ptr, float opt);

open

virtual void open ();

close

virtual void close ();

getVu

virtual float getVu ();

getChunk

virtual long getChunk (void** data, bool isPreset = false);

Returns byteSize.


setChunk

virtual long setChunk (void* data, long byteSize, bool isPreset = false);

setSampleRate

virtual void setSampleRate (float sampleRate);

setBlockSize

virtual void setBlockSize (long blockSize);

This is called by the host, and tells the plug that the maximum blocksize passed to either process method will be <blockSize>.

Note :

process (float** ins, float** outs, long sampleFrames)

means you must process exactly sampleFrames number of samples, and not more! for instance

void MyPlug::setBlockSize (long blockSize)
{
// assume blockSize is 1024
myBlockSize = blockSize;
}

void MyPlug::process (float** ins,
float** outs, long sampleFrames)
{
// assume sampleFrames is 1

float* in = ins[0];
float* out = outs[0];
// long frames = myBlockSize; // KILLER!
long frames = sampleFrames; // OK: you should always use the passed sampleFrames value
while (--frames >= 0)
*out++ += *in++ * gain;
// boom on 2nd sample... if "long frames = myBlockSize;" is used
}

Using myBlockSize instead of sampleFrames can write wildly into memory because the host may provide buffers of smaller size (e.g. Peak when reaching the end of a file) than stated in setBlockSize. Again, setBlockSize only tells you the maximum that you will have to expect in process (or processReplacing), but the ampleFrames argument passed to the process function, as well as the buffers provided there, might be only 1 sample, for instance.

See also :


suspend

virtual void suspend ();

This method is called when the effect is turned off by the user.

Example :

void MyPlug::suspend ()
{
memset (myBuffer, 0, myBufferSize * sizeof(float));
}

The buffer gets flushed here because otherwise pending data would sound again when the effect is switched on next time.

See also :


resume

virtual void resume ();

This method is called when the effect is turned on by the user.

See also :


Setup

Method that are called at construction time.


setUniqueID

virtual void setUniqueID (long iD)

Must call this! Set the plug's unique identifier. The host uses this to identify the plug-in, for instance when it is loading effect programs and banks. On Steinberg Web Page you can find an UniqueID Database where you can record your UniqueID, it will check if the ID is already used by an another vendor. You can use CCONST('a','b','c','d') (define in VST 2.0) to be platform independent to initialize an UniqueID.

iD The plug's identifier.

Example :

#define   kUniqueID 'MyPl'
// or (with VST 2.0 include file)
#define kUniqueID CCONST('M','y','P','l')

MyPlug::MyPlug (audioMasterCallback audioMaster)
: AudioEffectX (audioMaster, 1, 1)
{
...
setUniqueID (kUniqueID);
...
}

setNumInputs

virtual void setNumInputs (long inputs);

Set the number of inputs the plug will handle.

inputs The number of inputs.

Note :

This number is fixed at construction time and can't change until the plug is destroyed.

Example :

setNumInputs (2);

In case of stereo input.

See also :


setNumOutputs

virtual void setNumOutputs (long outputs);

Set the number of outputs the plug will handle.

outputs The number of outputs.

Note :

This number is fixed at construction time and can't change until the plug is destroyed.

Example :

setNumOutputs (2);

In case of stereo output.

See also :


hasVu

virtual void hasVu (bool state = true);

return vu value in getVu (); > 1. means clipped


hasClip

virtual void hasClip (bool state = true);

return > 1. in getVu () if clipped


canMono

virtual void canMono (bool state = true);

Tells the host that it makes sense to use this plug-in as a 1 in / 2 out device. When the host has mono effects sends and has a stereo bus for the effect returns, then the host can check this flag to add it to the list of plug-ins that could be used in this way.


canProcessReplacing

virtual void canProcessReplacing (bool state = true);

Plug supports in place output (the processReplacing method is implemented).

See also :


programsAreChunks

virtual void programsAreChunks (bool state = true);

Program data are handled in formatless chunks.


setRealtimeQualities

virtual void setRealtimeQualities (long qualities);

number of realtime qualities (0: realtime).


setOfflineQualities

virtual void setOfflineQualities (long qualities);

number of offline qualities (0: realtime only)


setInitialDelay

virtual void setInitialDelay (long delay);

For algorithms which need input in the first place.


Inquiry


getSampleRate

virtual float getSampleRate ();

getBlockSize

virtual long getBlockSize ();

Host communication (Plug -> Host)


getMasterVersion

virtual long getMasterVersion ();

getCurrentUniqueId

virtual long getCurrentUniqueId ();

masterIdle

virtual void masterIdle ();

isInputConnected

virtual bool isInputConnected (long input);

There is no negotiation currently, thus numOutputs (or numInputs) must not change at any time. A vst plug is taken to be a device with a fixed number of i/o pins. How these are beeing used depends on the application. In cubase/nuendo :

It might be useful if makers of other hosts want to document connection schemes differing from these.

The plug can inquire isInputConnected and isOutputConnected in order to suit the routing. Also the speakerArrangement information can be useful. Later vst implementations may support dynamic pin connection and negotiation.

input The index of the input, starting at 0 (e.g. left=0, right=1).

Note :

This method should be called from resume rather than from the constructor.


isOutputConnected

virtual bool isOutputConnected (long output);

Tools


dB2string

virtual void dB2string (float value, char *text);

Stuffes <text> with an amplitude on the [0.0, 1.0] scale converted to its value in decibels.

Example :

1.0 maps to 0 dB and 0.0 to -oo dB.


Hz2string

virtual void Hz2string (float samples, char *text);

Stuffes <text> with the frequency in Hertz that has a period of <samples>.

Example :

44100 will map to 1.0 if sampleRate is set to 44.1 kHz.


ms2string

virtual void ms2string (float samples, char *text);

Stuffes <text> with the duration in milliseconds of <smaples> frames.


float2string

virtual void float2string (float value, char *string);

Stuffes <text> with a string representation on the floating point <value>.


long2string

virtual void long2string (long value, char *text);

Stuffes <text> with a string representation on the integer <value>.



Protected Members


float sampleRate;

AEffEditor *editor;
audioMasterCallback audioMaster;
long numPrograms;
long numParams;
long curProgram;
long blockSize;

AEffect cEffect;


Copyright ©2003 Steinberg Media Technologies GmbH. All Rights Reserved.