Integrating ODIN Voice Chat with the FMOD Audio Solution in Unity
Introduction
Welcome to this guide on integrating the ODIN Voice Chat Plugin with the FMOD Audio Solution in Unity. The code used in this guide is available on the ODIN-FMOD Git repository.
What You'll Learn:
- How the
FMODMicrophoneReader
and FMODPlaybackComponent scripts work and how to use them in your project - Properly set up ODIN in Unity when using FMOD as an audio solution
- Deal with limitations and potential pitfalls
Note: This guide assumes that your project has disabled Unity's built-in audio.
Disclaimer: Be aware that the implementation shown here uses Programmer Sounds of the FMOD Engine. While this allows real-time audio data, a big disadvantage of this approach is an increased latency by ~500ms.
Getting Started
To follow this guide, you'll need to have some prerequisites:
- Basic knowledge of Unity
- The FMOD Plugin for Unity, which you can get here
- The ODIN Voice Chat Plugin, available here
To set up FMOD in your project, please follow FMOD's in-depth integration tutorial. You can find the tutorial here.
To set up the ODIN Voice Chat Plugin, please take a look at our Getting-Started guide, which you can find here:
Begin ODIN Getting Started GuideFMODMicrophoneReader
script is an essential part of the FMOD integration. It replaces the default ODINMicrophoneReader
component, taking over the microphone input responsibilities by using FMOD. This script is crucial for reading microphone data and sending it to the ODIN servers for voice chat.You can either follow the Usage setup to drop the FMODMicrophoneReader
Usage
- Add the
FMODMicrophoneReader
script to yourOdinManager
prefab. - Disable the original
MicrophoneReader
component.
If you're using ODIN Plugin versions older than 1.5.9, do not remove the MicrophoneReader
The script currently doesn't support automatic device switching or allow for programmatically changing devices. If you'd like to see extensions to this script, feel free to join our Discord server and let us know.
How it works
To read data from the microphone using FMOD, we'll need to perform the following steps:
- Setup and create a
FMOD.Sound
object, into which FMOD can store the microphone input data. - Start the microphone recording.
- Continually read the FMOD microphone data and push it to the ODIN servers.
1. Setup
The setup is performed in Unity's Start()
method.
Retrieve Microphone Info
You need to retrieve details about the microphone, such as the sampling rate and the number of channels. We'll use this info to configure the FMOD recording sound in the next step and the ODIN microphone streams later on.
Configure Recording Sound Info
After obtaining the input device details, the next action is to set up the CREATESOUNDEXINFO
object. This object
carries essential metadata that FMOD needs for audio capture.
We use SOUND_FORMAT.PCMFLOAT
because ODIN requires this format for microphone data. This avoids the need for audio
data conversions later on.
The _recordingSoundInfo.length
is set to capture one second of audio. To change the recording duration, you can adjust
the formula with a different multiplier.
Create Recording Sound
To hold the captured audio, FMOD requires us to create a FMOD Sound
object as shown below.
Here, we use the MODE.LOOP_NORMAL | MODE.OPENUSER
flags in combination with the previously configured
_recordingSoundInfo
to initialize the _recordingSound
object.
2. Recording
At this point, we're ready to start capturing audio. To do so, call the recordStart
method from FMOD's core system.
After initiating the recording, we also get the length of the recorded sound in PCM samples by calling getLength
. This
value will help us manage the recording buffer in later steps.
3. Continually push microphone data
In the Update()
method, we manage the ongoing capture of audio data from the FMOD microphone and its transmission to
the ODIN servers. This ensures that the audio stream remains both current and continuously active.
Initialization
The method starts by checking if there is an active OdinHandler
The next step is to find out how much audio has been recorded since the last check. This way, we know how much data to read from the buffer.
If the read buffer is too short to hold the new audio data, its size is updated.
Read Microphone Data
Microphone data is read from the FMOD sound object and copied into the read buffer using FMOD's @lock
and the System
Marshal.Copy
functions.
In this implementation, it's crucial to be aware of the unit differences between FMOD, ODIN, and the system's
Marshal.Copy
function. FMOD expects the read position and read length to be specified in bytes. In contrast, both ODIN
and Marshal.Copy
require the lengths to be represented as the number of samples being copied. Since we're recording in
the SOUND_FORMAT.PCMFLOAT
format, we can use sizeof(float)
to easily switch between FMOD's byte-sized units and
ODIN's sample-sized units.
Push Microphone Data
After reading, if there is any valid data, it is pushed to the ODIN servers and the current microphone read position is updated.
The _currentReadPosition
is reset back to zero when it reaches the length of the recording buffer to avoid going out
of bounds.
The ValidateMicrophoneStream
method ensures that an ODIN microphone stream is set up and configured correctly:
By understanding and implementing these steps, you should be able to continually read FMOD microphone data and push it to the ODIN servers, thereby keeping your audio stream up-to-date.