Develop a native DSP audio plug-in
Learn how to create your own native DSP plug-in.
Read time 5 minutesLast updated 22 days ago
You can use the native Digital Signal Processing (DSP) plug-in to process audio and expose parameters for a user to experiment with audio effects. The example plug-ins that Unity provides are a good place to experiment with plug-ins and to get ideas about parameters you need.
To develop a native audio plug-in for Unity:
1. Create an audio plug-in file
To create an audio plug-in file:
-
Download the latest audio plug-in SDK.
-
In the folder, go to NativeAudioPlugins > NativeCode. The native example plug-in .cpp files are located here.
-
You can duplicate one of the plug-in .cpp files so you can use it as a template for your own plug-in, work directly in one of the example plug-in files (for example,), or create your own .cpp file.
Plugin_Equalizer.cpp -
Includein your file if it's not already there.
AudioPluginUtil.h
2. Define your parameters in your audio plug-in file
Create a list of parameters that would be useful for your user to interact with when they use your plug-in. To add your parameters to your plug-in:
-
In your plug-in .cpp file, define your parameters as enum values. For example:enum Param{ P_FREQ, //Frequency parameter P_MIX, //Mix parameter P_NUM //An extra value to keep track of length of the enum};
-
Create an array ofand set its size to be the number of parameters you have:
UnityAudioParameterDefinitionsint numparams = P_NUM;definition.paramdefs = new UnityAudioParameterDefinition [numparams]; -
Use thefunction to register each of your enum values.
RegisterParameterint InternalRegisterEffectDefinition(UnityAudioEffectDefinition& definition){ int numparams = P_NUM; definition.paramdefs = new UnityAudioParameterDefinition [numparams]; RegisterParameter(definition, "Frequency", "Hz", 0.0f, kMaxSampleRate, 1000.0f, 1.0f, 3.0f, P_FREQ); RegisterParameter(definition, "Mix amount", "%", 0.0f, 1.0f, 0.5f, 100.0f, 1.0f, P_MIX); return numparams;}
The following table gives an overview of the function, its parameters, and how it's used in the code example above:
RegisterParameterParameter type and name | Variable in example code | Description |
|---|---|---|
| | The UnityAudioEffectDefinition structure contains an array of UnityAudioParameterDefinition. The RegisterParameter function inserts your parameter definition as an entry into this array. |
| | The display name you want to give the parameter. |
| | The type of the value. |
| | The minimum value of the parameter. |
| | The maximum value of the parameter. |
| | The default and initial value of the parameter. |
| | Scale factor for the display of parameters only. For example, the percentage in the example code has a minimum value of 0, a maximum value of 1, and a scale factor 100.0f. This means that although the actual value is between 0 and 1, the value that is shown in the GUI in Unity is between 0% and 100%. |
| | Maps parameters to sliders. |
| | Enum value to assign these values to. |
Unity generates a default GUI from these basic parameter definitions.
3. Instantiate your native audio DSP plug-in
To create the instance of your plug-in, use the function. Unity calls the function as soon as it creates your plug-in. It can be null.
CreateCallbackCreateCallbackstruct EffectData{ struct Data { float p[P_NUM]; // Parameters float s; // Sine output of oscillator float c; // Cosine output of oscillator }; union { Data data; unsigned char pad[(sizeof(Data) + 15) & ~15]; };};
UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK CreateCallback( UnityAudioEffectState* state){ EffectData* effectdata = new EffectData; memset(effectdata, 0, sizeof(EffectData)); effectdata->data.c = 1.0f; state->effectdata = effectdata; InitParametersFromDefinitions( InternalRegisterEffectDefinition, effectdata->data.p); return UNITY_AUDIODSP_OK;}
The object stores data it receives from the host and passes the data to all callback functions. The data it stores includes:
UnityAudioEffectState-
the sampling rate
-
the total number of samples processed (for timing)
-
whether the plug-in is bypassed
4. Unload your native audio DSP plug-in
To free the plug-in instance, use the function. Unity calls the function just before it frees the plug-in and also frees any data associated with this specific instance of the plug-in. After this, no further callbacks related to the instance happen.
ReleaseCallbackReleaseCallbackUNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ReleaseCallback( UnityAudioEffectState* state){ EffectData::Data* data = &state->GetEffectData<EffectData>()->data; delete data; return UNITY_AUDIODSP_OK;}
5. Handle audio processing in your plug-in
To handle the processing of audio, use the function. Unity repeatedly calls the function with a block of input audio to read from and an output block to write to.
ProcessCallbackProcessCallbackThe following code gives an example of a sine-wave being multiplied to all channels:
UNITY_AUDIODSP_RESULT UNITY_AUDIODSP_CALLBACK ProcessCallback( UnityAudioEffectState* state, float* inbuffer, float* outbuffer, unsigned int length, int inchannels, int outchannels){ EffectData::Data* data = &state->GetEffectData<EffectData>()->data; float w = 2.0f * sinf(kPI * data->p[P_FREQ] / state->samplerate); for(unsigned int n = 0; n < length; n++) { for(int i = 0; i < outchannels; i++) { outbuffer[n * outchannels + i] = inbuffer[n * outchannels + i] * (1.0f - data->p[P_MIX] + data->p[P_MIX] * data->s); } data->s += data->c * w; // cheap way to calculate a sine-wave data->c -= data->s * w; } return UNITY_AUDIODSP_OK;}
The function is a helper function that casts the field of the state variable to the in the structure.
GetEffectDataeffectdataEffectData::DataCustomize your GUI and import your audio plug-in into Unity
If you want to customize how Unity displays your plug-in parameters, refer to Customize the GUI for your audio plug-in.
To import your plug-ins into Unity, refer to Use your native DSP plug-in and GUI in Unity.