Unity Integration 2.02
//--------------------------------------------------------------------
//
// This is a Unity behaviour script that demonstrates how to capture
// the DSP with FMOD.DSP_READ_CALLBACK and how to create and add a DSP
// to master channel group ready for capturing.
//
// For the description of the channel counts. See
// https://fmod.com/docs/2.02/api/core-api-common.html#fmod_speakermode
//
// This document assumes familiarity with Unity scripting. See
// https://unity3d.com/learn/tutorials/topics/scripting for resources
// on learning Unity scripting.
//
//--------------------------------------------------------------------
using System;
using UnityEngine;
using System.Runtime.InteropServices;
class ScriptUsageDspCapture : MonoBehaviour
{
private FMOD.DSP_READ_CALLBACK mReadCallback;
private FMOD.DSP mCaptureDSP;
private float[] mDataBuffer;
private GCHandle mObjHandle;
private uint mBufferLength;
private int mChannels = 0;
[AOT.MonoPInvokeCallback(typeof(FMOD.DSP_READ_CALLBACK))]
static FMOD.RESULT CaptureDSPReadCallback(ref FMOD.DSP_STATE dsp_state, IntPtr inbuffer, IntPtr outbuffer, uint length, int inchannels, ref int outchannels)
{
FMOD.DSP_STATE_FUNCTIONS functions = (FMOD.DSP_STATE_FUNCTIONS)Marshal.PtrToStructure(dsp_state.functions, typeof(FMOD.DSP_STATE_FUNCTIONS));
IntPtr userData;
functions.getuserdata(ref dsp_state, out userData);
GCHandle objHandle = GCHandle.FromIntPtr(userData);
ScriptUsageDspCapture obj = objHandle.Target as ScriptUsageDspCapture;
// Save the channel count out for the update function
obj.mChannels = inchannels;
// Copy the incoming buffer to process later
int lengthElements = (int)length * inchannels;
Marshal.Copy(inbuffer, obj.mDataBuffer, 0, lengthElements);
// Copy the inbuffer to the outbuffer so we can still hear it
Marshal.Copy(obj.mDataBuffer, 0, outbuffer, lengthElements);
return FMOD.RESULT.OK;
}
void Start()
{
// Assign the callback to a member variable to avoid garbage collection
mReadCallback = CaptureDSPReadCallback;
// Allocate a data buffer large enough for 8 channels
uint bufferLength;
int numBuffers;
FMODUnity.RuntimeManager.CoreSystem.getDSPBufferSize(out bufferLength, out numBuffers);
mDataBuffer = new float[bufferLength * 8];
mBufferLength = bufferLength;
// Get a handle to this object to pass into the callback
mObjHandle = GCHandle.Alloc(this);
if (mObjHandle != null)
{
// Define a basic DSP that receives a callback each mix to capture audio
FMOD.DSP_DESCRIPTION desc = new FMOD.DSP_DESCRIPTION();
desc.numinputbuffers = 1;
desc.numoutputbuffers = 1;
desc.read = mReadCallback;
desc.userdata = GCHandle.ToIntPtr(mObjHandle);
// Create an instance of the capture DSP and attach it to the master channel group to capture all audio
FMOD.ChannelGroup masterCG;
if (FMODUnity.RuntimeManager.CoreSystem.getMasterChannelGroup(out masterCG) == FMOD.RESULT.OK)
{
if (FMODUnity.RuntimeManager.CoreSystem.createDSP(ref desc, out mCaptureDSP) == FMOD.RESULT.OK)
{
if (masterCG.addDSP(0, mCaptureDSP) != FMOD.RESULT.OK)
{
Debug.LogWarningFormat("FMOD: Unable to add mCaptureDSP to the master channel group");
}
}
else
{
Debug.LogWarningFormat("FMOD: Unable to create a DSP: mCaptureDSP");
}
}
else
{
Debug.LogWarningFormat("FMOD: Unable to create a master channel group: masterCG");
}
}
else
{
Debug.LogWarningFormat("FMOD: Unable to create a GCHandle: mObjHandle");
}
}
void OnDestroy()
{
if (mObjHandle != null)
{
// Remove the capture DSP from the master channel group
FMOD.ChannelGroup masterCG;
if (FMODUnity.RuntimeManager.CoreSystem.getMasterChannelGroup(out masterCG) == FMOD.RESULT.OK)
{
if (mCaptureDSP.hasHandle())
{
masterCG.removeDSP(mCaptureDSP);
// Release the DSP and free the object handle
mCaptureDSP.release();
}
}
mObjHandle.Free();
}
}
const float WIDTH = 0.01f;
const float HEIGHT = 10.0f;
const float YOFFSET = 5.0f;
void Update()
{
// Do what you want with the captured data
for (int j = 0; j < mBufferLength; j++)
{
for (int i = 0; i < mChannels; i++)
{
float x = j * WIDTH;
float y = mDataBuffer[(j * mChannels) + i] * HEIGHT;
// Make sure Gizmos is enabled in the Unity Editor to show debug line draw for the captured channel data
Debug.DrawLine(new Vector3(x, (YOFFSET * i) + y, 0), new Vector3(x, (YOFFSET * i) - y, 0), Color.green);
}
}
}
}