A plug-in's audio processing core.
On this page
Algorithm definition
Algorithm processing in AAX plug-ins is handled via a C-style algorithm processing callback (see code below.) Each Effect variation in a plug-in must register an algorithm entrypoint in the plug-in
description, and the host will call this entrypoint to render a buffer of audio samples.
SMyPlugIn_Alg_Context * const inInstancesBegin [],
const void * inInstancesEnd)
{
}
#define AAX_CALLBACK
Definition: AAX.h:285
Algorithm memory management
This callback pattern is designed such that plug-in algorithms may be easily loaded in remote memory spaces on a variety of devices and quickly re-compiled for different operating environments without significant changes to the code, and this design goal informs the algorithm's memory management techniques.
When the AAX host calls a plug-in's algorithm callback, it provides a block of memory describing the state of the plug-in. This block of memory, known as the algorithm's context, can be thought of as the algorithm's interface to the outside world: when another part of the plug-in interacts with the algorithm, it does so by posting information to the algorithm's context.
struct SDemoDist_Alg_Context
{
int32_t * mCtrlBypassP;
float * mCtrlMixP;
float * mCtrlInpGP;
float * mCtrlOutGP;
SDemoDist_DistCoefs * mCoefsDistP;
SDemoDist_FiltCoefs * mCoefsFiltP;
CSimpleBiquad * mBiquads;
float* * mInputPP;
float* * mOutputPP;
float* * mMeterTapsPP;
};
It is important to note that, in most circumstances, algorithm callbacks do not own their own memory. The algorithm and its memory is managed entirely by the host or shell environment, and relies on the host-provided context structure for all state information.
If persistent memory is required, algorithms can register for block(s) of persistent state date via the
AAX_IComponentDescriptor::AddPrivateData() API (as in SDemoDist_Alg_Context::mBiquads above.) A plug-in may store state data in the resulting
"private data" context fields and this data will be restored by the host when the algorithm is next called. See the
Persistent algorithm memory section below for more information.
Communicating with the algorithm
Plug-ins communicate with their algorithms via a buffered, host-managed message system. The host guarantees that messages posted to this system will be delivered to the applicable context field and that the algorithm's context is up to date every time the component is entered.
This system utilizes a static data routing scheme that is defined in the plug-in's describe method. Once the routing scheme has been defined, the plug-in may post packets of data to its algorithm using
AAX_IController::PostPacket().
In order to reference the fields in its algorithm's context, the plug-in's host-side code uses unique identifiers generated with the
AAX_FIELD_INDEX macro:
enum EDemoDist_Alg_PortID
{
eAlgPortID_BypassIn =
AAX_FIELD_INDEX (SDemoDist_Alg_Context, mCtrlBypassP)
,eAlgPortID_CoefsDistIn =
AAX_FIELD_INDEX (SDemoDist_Alg_Context, mCoefsDistP)
,eAlgPortID_CoefsFilterIn =
AAX_FIELD_INDEX (SDemoDist_Alg_Context, mCoefsFiltP)
,eDemoDist_AlgFieldID_AudioIn =
AAX_FIELD_INDEX (SDemoDist_Alg_Context, mInputPP)
,eDemoDist_AlgFieldID_AudioOut =
AAX_FIELD_INDEX (SDemoDist_Alg_Context, mOutputPP)
,eAlgFieldID_MeterTaps =
AAX_FIELD_INDEX (SDemoDist_Alg_Context, mMeterTapsPP)
};
#define AAX_FIELD_INDEX(aContextType, aMember)
Compute the index used to address a context field.
Definition: AAX.h:323
See
Description callback for more information about registering context fields and defining a plug-in's message routing scheme.
Algorithm initialization
The following events occur before the AAX host begins calling a plug-in's algorithm:
- The Effect's data model is initialized
- An initial call to AAX_IEffectParameters::ResetFieldData() is made for each private data block in the algorithm.
- An initial call to AAX_IEffectParameters::GenerateCoefficients() is made and coefficient packets are dispatched to each of the algorithm's data ports based on the default model state.
- All packets are delivered and initial algorithm context state is set
- If one has been registered, the algorithm's optional initialization callback is called with the default context
- (Algorithmic processing begins)
Private data initialization
To initialize an algorithm's private data blocks,
AAX_IEffectParameters::ResetFieldData() is called on the host for each block in the algorithm. The host uses this method to acquire a default initialized memory block for each private data port, which is then copied into the algorithm's memory pool and provided to its context.
Optional initialization callback
If any additional initialization or de-initialization steps are required for proper operation of the algorithm, an optional initialization routine may be registered and associated with the algorithm's processing callback. This initialization routine will be called in the same device / memory space as the algorithm's processing context. The initialization callback is provided with the algorithm's default context and is called both before every new instance of the Effect begins its algorithm render callbacks and before every instance is destroyed.
This initialization routine is provided in
Describe as an argument to the platform's
AddProcessProc
registration method:
- Host Compatibility Notes:
- As of Pro Tools 10.2.1 an algorithm's initialization calllback routine will have up to 5 seconds to execute.
Algorithm processing
Once the algorithm has been initialized and processing begins, the algorithm function is called regularly by the host audio engine. The algorithm may read the context data provided by the host and is responsible for writing data to all of the samples in its output buffers each time it is executed.
- Note
- The data in an algorithm's output buffers is not initialized before the algorithm is called, thus the algorithm must always write data into all output samples. This is to ensure equivalent behavior between all platforms, some of which do not have the resource budget to pre-initialize output data buffers.
Persistent algorithm memory
An AAX plug-in algorithm may contain one or more private data ports in its context. These are the only context fields in which an algorithm may store persistant state data.
Private memory characteristics
Each private data port is a pointer to a preallocated block of memory. The size of each port is defined during Describe when the port is registered. On DSP systems, the plug-in may request that the data block be placed in the chip's external memory.
Once private data is allocated by the plug-in host or DSP shell, it will not be relocated or re-allocated until the algorithm is destroyed (see
Optional initialization callback)
Private data port registration
Private data initialization
AAX_IEffectParameters::ResetFieldData() is called on the host for both Native and DSP plug-ins. For DSP plug-ins, the initialized data block is copied to the DSP by the AAX host following the initialization callback. The initialization callbacks for a plug-in's private data blocks are called after all host modules have been initialized and before the algorithm's optional initialization callback.
Private data communication
It is possible to transfer data to and from the algorithm's private data blocks using the
AAX_IPrivateDataAccess interface, which is available in a TimerWakeup context through the
AAX_IEffectDirectData interface. For more information about this API, see auxinterface_directdata_privatedataaccess.
Example algorithm callback
As a final example, the code below describes a simple audio processing component. The component's context contains one message pointer to receive incoming "gain" parameter values, as well as one audio data input, "pdI", and one audio data output, "pdO". Additionally there is a message pointer to receive "bypass" on/off values. The host calls the component each time a new input sample buffer must be processed, and each time the component is called the host ensures that all context fields are up-to-date.
SMyPlugIn_Alg_Context * const inInstancesBegin [],
const void * inInstancesEnd)
{
SMyPlugIn_Alg_Context* AAX_RESTRICT instance = inInstancesBegin [0];
for (SMyPlugIn_Alg_Context * const * walk = inInstancesBegin; walk < inInstancesEnd; ++walk)
{
instance = *walk;
const SMyPlugIn_CoefsGain* const AAX_RESTRICT coefsGainP = instance->mCoefsGainP;
const int32_t bypass = *instance->mCtrlBypassP;
const float gain = coefsGainP->mGain;
for (int ch = 0; ch < kNumChannelsIn; ch++)
{
for (int t = 0; t < kAudioWindowSize; t++)
{
float* const AAX_RESTRICT pdI = instance->mInputPP [ch];
float* const AAX_RESTRICT pdO = instance->mOutputPP [ch];
if ( pdI && pdO )
{
pdO [t] = gain * pdI [t];
if (bypass) { pdO [t] = pdI [t]; }
}
}
}
}
}
Port Types and Behavior
In this section, we will examine the various kinds of ports that can be used by the algorithm component in an AAX plug-in:
-
Standard message input
-
Internal state storage
-
Metering output
-
Environment variable retrieval
-
Other functionality enhancement
Standard message input
Most ports will function as pointers to incoming data. This data can have any type. For example, an algorithm's context may include a port of type float* to receive incoming float data and another port of type SMyCustomStructure
* to receive incoming SMyCustomStructure
data.
Like all registered context fields, input ports are managed by the hosting environment such that they always point to the most recently received data at the time that the algorithm callback is entered. The algorithm may not store or alter data in a standard message input port: this data is available as read-only input. If data is stored in the space allocated for the port's data then the result will be undefined behavior.
Internal state storage
Most plug-ins require local data to be accessible to their algorithms. These may be static data, such as lookup tables, or dynamic data, such as coefficient smoothing history or delay lines. In the DemoDist sample plug-in, SDemoDist_Alg_Context::mBiquads
is an example of this type of port: it is not modified by any other component and DemoDist_AlgorithmProcessFunction()
relies on the mBiquads
data persisting between processing calls.
A component that has registered a private data field is given access to a block of private data. Although the memory in this block will be allocated by the host, its data is fully owned by the component. Because this data is considered private to its parent component, other components cannot overwrite or target this data. Plug-ins that need to transmit data directly between their algorithms' private data ports and their other modules may use the
AAX_IEffectDirectData interface, which provides an API for reading from or writing to this data from outside of the algorithm callback.
The plug-in's data model includes an initialization function that is called by the AAX host at the time of plug-in instantiation and "reset" events. This initialization method is called on the host for both Native and DSP plug-ins. Since this method is part of the plug-in's data model, it has direct access to plug-in state information.
Metering output
Plug-in metering ports are populated with an array of float values, or 'taps'. One tap is provided per plug-in meter. The algorithm writes per-buffer peak values to this port and the AAX host applies standardized ballistics to these values. Both raw and processed meter values are available to the plug-in's GUI.
Environment variable retrieval
Another use of ports is to receive data from the AAX host describing the execution environment. For example, an algorithm may include a port to receive the number of samples in its processing window or the sample rate. These services are provided automatically by the host once the component registers ports for them.
Other functionality enhancement
An algorithm component may use ports to gain additional functionality that is provided by the host. For example, an algorithm that will be compiled for accelerated environments may take advantage of the TI chip's Direct Memory Access functionality by registering a DMA port. The host will then allow this port to access memory directly using
AAX's DMA APIs.
Additional Information
For information about optional features for the algorithm processing callback, see the following
Additional AAX features documentation: