Most Wwise SDK functions are available in Unity through the AkSoundEngine
class. Think of it as the replacement of C++ namespaces AK::SoundEngine
, AK::MusicEngine
, and so on. See API Limitations for changes made in the API binding compared to the original SDK. For more complex situations, you'll need to call Wwise functions from code. In the API, the GameObjectID
in all functions is replaced by the Unity flavor of the GameObject. At runtime, an AkGameObj component is automatically added to this GameObject, unless you have already manually added it before.
Using numeric IDs instead of strings for Events and Banks
The native Wwise API allows you to use strings or IDs to trigger events and other named objects in the Wwise project. You can still do this in the C# world by converting the file Wwise_IDs.h
to Wwise_IDs.cs
. Click Assets > Wwise > Convert Wwise SoundBank IDs. You need to have Python installed to make this work.
Sending MIDI to Wwise
MIDI can be sent to Wwise by filling the AkMIDIPost
members of AkMIDIPostArray
class and calling any of the following methods:
The following is a basic script that sends MIDI messages to the sound engine:
public class MyMIDIBehaviour : UnityEngine.MonoBehaviour
{
private void Start()
{
AkMIDIPostArray MIDIPostArrayBuffer = new AkMIDIPostArray(6);
AkMIDIPost midiEvent = new AkMIDIPost();
midiEvent.byType = AkMIDIEventTypes.NOTE_ON;
midiEvent.byChan = 0;
midiEvent.byOnOffNote = 56;
midiEvent.byVelocity = 127;
midiEvent.uOffset = 0;
MIDIPostArrayBuffer[0] = midiEvent;
midiEvent.byOnOffNote = 60;
MIDIPostArrayBuffer[1] = midiEvent;
midiEvent.byOnOffNote = 64;
MIDIPostArrayBuffer[2] = midiEvent;
midiEvent.byType = AkMIDIEventTypes.NOTE_OFF;
midiEvent.byOnOffNote = 56;
midiEvent.byVelocity = 0;
midiEvent.uOffset = 48000 * 8;
MIDIPostArrayBuffer[3] = midiEvent;
midiEvent.byOnOffNote = 60;
MIDIPostArrayBuffer[4] = midiEvent;
midiEvent.byOnOffNote = 64;
MIDIPostArrayBuffer[5] = midiEvent;
SynthEvent.PostMIDI(gameObject, MIDIPostArrayBuffer);
}
}
Offline Rendering in Unity
The Unity integration exposes the offline rendering feature within the Wwise SDK and simplifies how audio samples can be retrieved.
| Caution: Care must be taken to ensure that only the asynchronous AkSoundEngine.LoadBank and AkSoundEngine.UnloadBank APIs are used from the main thread when offline rendering is enabled. See Custom Scheduling of Audio Rendering for details. |
AkSoundEngine.StartDeviceCapture
sets up a specific output audio device for capture so that the number of available samples can be determined by calling AkSoundEngine.UpdateCaptureSampleCount
and the audio samples can be retrieved by calling AkSoundEngine.GetCaptureSamples
.
The following example illustrates how to use the Unity integration to perform offline audio rendering in conjunction with Unity's screen capture functionality. With this functionality implemented, one can easily perform a multiplexing post-processing step to combine the captured audio samples and video frames into a movie.
public abstract class WwiseOfflineRenderer : UnityEngine.MonoBehaviour
{
public bool IsOfflineRendering { get; set; }
public bool StartWithOfflineRenderingEnabled = false;
private bool IsCurrentlyOfflineRendering = false;
public float FrameRate = 25.0f;
protected ulong OutputDeviceId = 0;
public abstract string GetUniqueScreenshotFileName(int frameCount);
public abstract void ProcessAudioSamples(float[] buffer);
protected void Start()
{
OutputDeviceId = AkSoundEngine.GetOutputID(AkSoundEngine.AK_INVALID_UNIQUE_ID, 0);
if (StartWithOfflineRenderingEnabled)
{
IsOfflineRendering = true;
Update();
}
}
private void LogAudioFormatInfo()
{
var sampleRate = AkSoundEngine.GetSampleRate();
var channelConfig = new AkChannelConfig();
var audioSinkCapabilities = new Ak3DAudioSinkCapabilities();
AkSoundEngine.GetOutputDeviceConfiguration(OutputDeviceId, channelConfig, audioSinkCapabilities);
UnityEngine.Debug.LogFormat("Sample Rate: {0}, Channels: {1}", sampleRate, channelConfig.uNumChannels);
}
protected void Update()
{
if (IsOfflineRendering != IsCurrentlyOfflineRendering)
{
IsCurrentlyOfflineRendering = IsOfflineRendering;
if (IsOfflineRendering)
{
#if UNITY_EDITOR
AkSoundEngineController.Instance.DisableEditorLateUpdate();
#endif
LogAudioFormatInfo();
AkSoundEngine.ClearCaptureData();
AkSoundEngine.StartDeviceCapture(OutputDeviceId);
}
else
{
AkSoundEngine.StopDeviceCapture(OutputDeviceId);
#if UNITY_EDITOR
AkSoundEngineController.Instance.EnableEditorLateUpdate();
#endif
}
}
var frameTime = IsOfflineRendering && FrameRate != 0.0f ? 1.0f / FrameRate : 0.0f;
UnityEngine.Time.captureDeltaTime = frameTime;
AkSoundEngine.SetOfflineRenderingFrameTime(frameTime);
AkSoundEngine.SetOfflineRendering(IsOfflineRendering);
if (!IsOfflineRendering)
return;
UnityEngine.ScreenCapture.CaptureScreenshot(GetUniqueScreenshotFileName(UnityEngine.Time.frameCount));
var sampleCount = AkSoundEngine.UpdateCaptureSampleCount(OutputDeviceId);
if (sampleCount <= 0)
return;
var buffer = new float[sampleCount];
var count = AkSoundEngine.GetCaptureSamples(OutputDeviceId, buffer, (uint)buffer.Length);
if (count <= 0)
return;
ProcessAudioSamples(buffer);
}
}
Using the Audio Input Source Plug-in in Unity
The audio input source plug-in can be used via C# scripting. See Audio Input Source Plug-in from the Wwise SDK documentation.
The following is a basic script that sends a test tone to the audio input source plug-in:
public class MyAudioInputBehaviour : UnityEngine.MonoBehaviour
{
public uint SampleRate = 48000;
public uint NumberOfChannels = 1;
public uint SampleIndex = 0;
public uint Frequency = 880;
private bool IsPlaying = true;
bool AudioSamplesDelegate(uint playingID, uint channelIndex, float[] samples)
{
for (uint i = 0; i < samples.Length; ++i)
samples[i] = UnityEngine.Mathf.Sin(Frequency * 2 * UnityEngine.Mathf.PI * (i + SampleIndex) / SampleRate);
if (channelIndex == NumberOfChannels - 1)
SampleIndex = (uint)(SampleIndex + samples.Length) % SampleRate;
return IsPlaying;
}
void AudioFormatDelegate(uint playingID, AkAudioFormat audioFormat)
{
audioFormat.channelConfig.uNumChannels = NumberOfChannels;
audioFormat.uSampleRate = SampleRate;
}
private void Start()
{
AkAudioInputManager.PostAudioInputEvent(AudioInputEvent, gameObject, AudioSamplesDelegate, AudioFormatDelegate);
}
public void StopSound()
{
IsPlaying = false;
}
private void OnDestroy()
{
AudioInputEvent.Stop(gameObject);
}
}
Apply Custom Positioning in Unity
By default, the AkGameObj
component is attached to a specific Unity gameObject
and uses its transform (with an optional offset) for full positioning. This is usually adequate for many games, such as first-person shooters. However, games with custom camera angles, such as many third-person games, may find it difficult to accommodate the two aspects of positioning (distance attenuation and spatialization) by simply attaching the audio listener to one game object, such as the main camera in Unity. Other games may want players to experience other custom positioning.
To this end, the AkGameObj
component class provides overridable positioning to Unity users. Through the three virtual methods GetPosition()
, GetForward()
, and GetUpward()
, users can derive a subclass from AkGameObj
and use that subclass component to customize any number of Unity gameObjects'
positioning.
Here is a simple example of how to use a custom component to override the default AkAudioListener
behavior. With a third-person project integrated with Wwise, remove the existing AkAudioListener
and its associated AkGameObj
. Then attach the following script to the MainCamera object, attach AkAudioListener
, and finally specify the target Unity gameObject
(such as the player avatar) that the audio listener's position will follow. After this, the distance attenuation of all the emitters will rely on the selected target Unity gameObject's
position as the listener position (an on-screen distance listener), while the orientation of all the emitters is still based on the main camera orientation as the listener orientation (an off-screen orientation listener).
#if ! (UNITY_DASHBOARD_WIDGET || UNITY_WEBPLAYER || UNITY_WII || UNITY_WIIU || UNITY_NACL || UNITY_FLASH || UNITY_BLACKBERRY) // Disable under unsupported platforms.
using UnityEngine;
using System;
using System.Collections.Generic;
[AddComponentMenu ("Wwise/AkGameObj3rdPersonCam")]
[ExecuteInEditMode]
public class AkGameObj3rdPersonCam :
AkGameObj
{
public Transform target;
{
return target.GetComponent<
AkGameObj> ().GetPosition ();
}
}
#endif // #if ! (UNITY_DASHBOARD_WIDGET || UNITY_WEBPLAYER || UNITY_WII || UNITY_WIIU || UNITY_NACL || UNITY_FLASH || UNITY_BLACKBERRY) // Disable under unsupported platforms.