Class NativeAudio
The most important class, contains static methods that are used to command the native side.
Inheritance
System.ObjectNativeAudioNamespace: E7.Native
Assembly: E7.NativeAudio.dll
Syntax
public static class NativeAudio
Properties
Initialized
Returns true after calling Initialize() successfully, meaning that
we have a certain amount of native sources ready for use at native side.
It is able to turn back to false if you call Dispose()
to return native sources back to the OS.
Declaration
public static bool Initialized { get; }
Property Value
| Type | Description |
|---|---|
System.Boolean |
OnSupportedPlatform
-
If in Editor, it is instantly unsupported (
false) no matter what build platform selected. - If not in Editor, it is
trueonly on Android and iOS.
Declaration
public static bool OnSupportedPlatform { get; }
Property Value
| Type | Description |
|---|---|
System.Boolean |
Methods
Dispose()
[Android] Undo the Initialize(). It doesn't affect any loaded audio, just dispose all the native sources returning them to OS and make them available for other applications.
You still have to unload each audio. Disposing twice is safe, it does nothing.
[iOS] Disposing doesn't work.
[Editor] This is a no-op. It is safe to call and nothing will happen.
Declaration
public static void Dispose()
GetDeviceAudioInformation()
Ask the phone about its audio capabilities.
The returned struct has different properties depending on platform.
You should put preprocessor directive (#if UNITY_ANDROID and so on) over the returned object
if you are going to access any of its fields. Or else it would be an error if you switch your build platform.
[Editor] Does not work, returns default value of DeviceAudioInformation.
Declaration
public static DeviceAudioInformation GetDeviceAudioInformation()
Returns
| Type | Description |
|---|---|
DeviceAudioInformation |
GetNativeSource(Int32)
Get a native source in order to play an audio or control an audio currently played on it. You can keep and cache the returned native source reference and keep using it.
This method is for when you want a specific index of native source you would like to play on.
Declaration
public static NativeSource GetNativeSource(int nativeSourceIndex)
Parameters
| Type | Name | Description |
|---|---|---|
System.Int32 |
nativeSourceIndex |
Specify a zero-indexed native source that you want. If at Initialize() you requested 3, then valid numbers here are : 0, 1, and 2. If this index turns out to be an invalid index at native side, it has a fallback to round-robin native source selection. |
Returns
| Type | Description |
|---|---|
NativeSource |
Native source representation you can use it to play audio.
If |
Remarks
It checks with the native side if
a specified nativeSourceIndex is valid or not before returning a native source
interfacing object to you. If not, it has a fallback to round-robin native source selection.
Refer to Selecting native sources on how to strategize your native source index usage depending on your audio.
GetNativeSourceAuto()
Get a native source in order to play an audio or control an audio currently played on it. You can keep and cache the returned native source reference and keep using it.
Unlike GetNativeSource(Int32), this method is for when you just want to play an audio without much care about stopping a previously played audio on any available native source.
It selects a native source by round-robin algorithm, just select the next index from the previous play.
Declaration
public static NativeSource GetNativeSourceAuto()
Returns
| Type | Description |
|---|---|
NativeSource |
Native source representation you can use it to play audio resulting from round-robin selection. |
Remarks
Refer to Selecting native sources on how to strategize your native source index usage depending on your audio.
GetNativeSourceAuto(INativeSourceSelector)
Get a native source in order to play an audio or control an audio currently played on it. You can keep and cache the returned native source reference and keep using it.
Like GetNativeSource(Int32), this method is for when you want a specific index of native source to play. But unlike that, you can create your own "index returning object" that implements INativeSourceSelector. Making it more systematic for you.
Declaration
public static NativeSource GetNativeSourceAuto(INativeSourceSelector nativeSourceSelector)
Parameters
| Type | Name | Description |
|---|---|---|
INativeSourceSelector |
nativeSourceSelector |
Returns
| Type | Description |
|---|---|
NativeSource |
Native source representation you can use it to play audio, resulting from an index that
Native Audio got from calling NextNativeSourceIndex() on
|
Remarks
You can have internal state inside it if it is a class, you can emulate the default
round-robin native source selection, for example.
Refer to Selecting native sources on how to strategize your native source index usage depending on your audio.
GetNativeSourceCount()
Get number of usable native sources. Returns 0 if called before initialization.
[Android] It returns as many as you actually got from initialization. (e.g. if you requested 999 and actually get 15, then this returns 15)
[iOS] It is currently fixed to 15 as that is how OpenAL works. It gives you a set amount of sources.
Declaration
public static int GetNativeSourceCount()
Returns
| Type | Description |
|---|---|
System.Int32 |
Remarks
This is useful in a case like you want to completely stop all audio played with Native Audio before unloading audio to prevent crash where the play head now play unloaded memory.
Therefore you need to get all native sources and stop each one.
With this count you could do so in a for loop.
Initialize()
[iOS] Initializes OpenAL. 15 OpenAL native sources will be allocated all at once. It is not possible to initialize again on iOS. (Nothing will happen)
[Android] Initializes OpenSL ES. 1 OpenSL ES "Engine" and a number of native sources AudioPlayer object
(and in turn native AudioTrack) will be allocated all at once.
See Initialize(NativeAudio.InitializationOptions) overload how to customize your initialization.
Declaration
public static void Initialize()
Remarks
- More about this limit : https://developer.android.com/ndk/guides/audio/opensl/opensl-for-android
- And my own research here : https://gametorrahod.com/android-native-audio-primer-for-unity-developers/
Initialize(NativeAudio.InitializationOptions)
[iOS] Initializes OpenAL. 15 OpenAL native sources will be allocated all at once. It is not possible to initialize again on iOS. (Nothing will happen)
[Android] Initializes OpenSL ES. 1 OpenSL ES "Engine" and a number of native sources AudioPlayer object
(and in turn native AudioTrack) will be allocated all at once.
See Initialize(NativeAudio.InitializationOptions) overload how to customize your initialization.
Declaration
public static void Initialize(NativeAudio.InitializationOptions initializationOptions)
Parameters
| Type | Name | Description |
|---|---|---|
NativeAudio.InitializationOptions |
initializationOptions |
Customize your initialization. Start making it from defaultOptions |
Remarks
- More about this limit : https://developer.android.com/ndk/guides/audio/opensl/opensl-for-android
- And my own research here : https://gametorrahod.com/android-native-audio-primer-for-unity-developers/
Exceptions
| Type | Condition |
|---|---|
System.NotSupportedException |
Thrown when you initialize in Editor or something other than iOS or Android at runtime. |
Load(String)
(ADVANCED) Loads an audio from StreamingAssets folder's destination at runtime.
Most of the cases you should use the Load(AudioClip) overload instead.
It only supports .wav PCM 16-bit format, stereo or mono,
in any sampling rate since it will be resampled to fit the device.
Declaration
public static NativeAudioPointer Load(string streamingAssetsRelativePath)
Parameters
| Type | Name | Description |
|---|---|---|
System.String |
streamingAssetsRelativePath |
If the file is |
Returns
| Type | Description |
|---|---|
NativeAudioPointer |
An audio buffer pointer for use with Play(NativeAudioPointer). Get the source from GetNativeSource(Int32) |
Exceptions
| Type | Condition |
|---|---|
System.IO.FileLoadException |
Thrown when some unexpected exception at native side loading occurs. |
Load(String, NativeAudio.LoadOptions)
(ADVANCED) Loads an audio from StreamingAssets folder's destination at runtime.
Most of the cases you should use the Load(AudioClip) overload instead.
It only supports .wav PCM 16-bit format, stereo or mono,
in any sampling rate since it will be resampled to fit the device.
Declaration
public static NativeAudioPointer Load(string streamingAssetsRelativePath, NativeAudio.LoadOptions loadOptions)
Parameters
| Type | Name | Description |
|---|---|---|
System.String |
streamingAssetsRelativePath |
If the file is |
NativeAudio.LoadOptions |
loadOptions |
Customize your load. Start creating your option from defaultOptions. |
Returns
| Type | Description |
|---|---|
NativeAudioPointer |
An audio buffer pointer for use with Play(NativeAudioPointer). Get the source from GetNativeSource(Int32) |
Exceptions
| Type | Condition |
|---|---|
System.IO.FileLoadException |
Thrown when some unexpected exception at native side loading occurs. |
Load(AudioClip)
Loads by copying Unity-imported UnityEngine.AudioClip's raw audio memory to native side. You are free to unload the UnityEngine.AudioClip's audio data without affecting what's loaded at the native side after this.
[Editor] This method is a stub and returns null.
Declaration
public static NativeAudioPointer Load(AudioClip audioClip)
Parameters
| Type | Name | Description |
|---|---|---|
UnityEngine.AudioClip |
audioClip |
Hard requirements :
|
Returns
| Type | Description |
|---|---|
NativeAudioPointer |
An audio buffer pointer for use with Play(NativeAudioPointer). Get the source from GetNativeSource(Int32) |
Remarks
If you did not Initialize() yet, it will initialize with no NativeAudio.InitializationOptions. You cannot load audio while uninitialized.
Hard requirements :
- Load type MUST be Decompress On Load so Native Audio could read raw PCM byte array from your compressed audio.
- If you use Load In Background, you must call UnityEngine.AudioClip.LoadAudioData beforehand and ensure that UnityEngine.AudioClip.loadState is UnityEngine.AudioDataLoadState.Loaded before calling Load(AudioClip). Otherwise it would throw an exception. If you are not using UnityEngine.AudioClip.loadInBackground but also not using UnityEngine.AudioClip.preloadAudioData, Native Audio can load for you if not yet loaded.
It supports all compression format, force to mono, overriding to any sample rate, and quality slider.
[iOS] Loads an audio into OpenAL's output audio buffer. (Max 256) This buffer will be paired to one of 15 OpenAL source when you play it.
[Android] Loads an audio into a short* array at unmanaged native side.
This array will be pushed into one of available SLAndroidSimpleBufferQueue when you play it.
The resampling of audio will occur at this moment to match your player's device native rate.
The SLES audio player must be created to match the device rate to enable the special "fast path" audio. What's left is to make our audio compatible with that fast path player, which the resampler will take care of.
You can change the sampling quality of SRC (libsamplerate) library on a
per-audio basis with the Load(AudioClip, NativeAudio.LoadOptions) overload.
Exceptions
| Type | Condition |
|---|---|
System.Exception |
Thrown when some unexpected exception at native side loading occurs. |
System.NotSupportedException |
Thrown when you have prohibited settings on your UnityEngine.AudioClip. |
System.InvalidOperationException |
Thrown when you didn't manually load your UnityEngine.AudioClip when it is not set to load in background. |
Load(AudioClip, NativeAudio.LoadOptions)
Loads by copying Unity-imported UnityEngine.AudioClip's raw audio memory to native side. You are free to unload the UnityEngine.AudioClip's audio data without affecting what's loaded at the native side after this.
[Editor] This method is a stub and returns null.
Declaration
public static NativeAudioPointer Load(AudioClip audioClip, NativeAudio.LoadOptions loadOptions)
Parameters
| Type | Name | Description |
|---|---|---|
UnityEngine.AudioClip |
audioClip |
Hard requirements :
|
NativeAudio.LoadOptions |
loadOptions |
Customize your load. Start creating your option from defaultOptions. |
Returns
| Type | Description |
|---|---|
NativeAudioPointer |
An audio buffer pointer for use with Play(NativeAudioPointer). Get the source from GetNativeSource(Int32) |
Remarks
If you did not Initialize() yet, it will initialize with no NativeAudio.InitializationOptions. You cannot load audio while uninitialized.
Hard requirements :
- Load type MUST be Decompress On Load so Native Audio could read raw PCM byte array from your compressed audio.
- If you use Load In Background, you must call UnityEngine.AudioClip.LoadAudioData beforehand and ensure that UnityEngine.AudioClip.loadState is UnityEngine.AudioDataLoadState.Loaded before calling Load(AudioClip). Otherwise it would throw an exception. If you are not using UnityEngine.AudioClip.loadInBackground but also not using UnityEngine.AudioClip.preloadAudioData, Native Audio can load for you if not yet loaded.
- Must not be UnityEngine.AudioClip.ambisonic.
It supports all compression format, force to mono, overriding to any sample rate, and quality slider.
[iOS] Loads an audio into OpenAL's output audio buffer. (Max 256) This buffer will be paired to one of 15 OpenAL source when you play it.
[Android] Loads an audio into a short* array at unmanaged native side.
This array will be pushed into one of available SLAndroidSimpleBufferQueue when you play it.
The resampling of audio will occur at this moment to match your player's device native rate.
The SLES audio player must be created to match the device rate to enable the special "fast path" audio. What's left is to make our audio compatible with that fast path player, which the resampler will take care of.
You can change the sampling quality of SRC (libsamplerate) library on a
per-audio basis with the Load(AudioClip, NativeAudio.LoadOptions) overload.
Exceptions
| Type | Condition |
|---|---|
System.Exception |
Thrown when some unexpected exception at native side loading occurs. |
System.NotSupportedException |
Thrown when you have prohibited settings on your UnityEngine.AudioClip. |
System.InvalidOperationException |
Thrown when you didn't manually load your UnityEngine.AudioClip when it is not set to load in background. |
SilentAnalyze()
(EXPERIMENTAL) Native Audio will load a small silent wav and perform various stress test for about 1 second. Your player won't be able to hear anything, but recommended to do it when there's no other workload running because it will also measure FPS.
The test will be asynchronous because it has to wait for frame to play the next audio. Yield wait for the result with the returned NativeAudioAnalyzer. This is a component of a new game object created to run a test coroutine on your scene.
If your game is in a yieldable routine, use yield return new WaitUntil( () => analyzer.Analyzed );,
it will wait a frame until that is true.
If not, you can do a blocking wait with a while loop on analyzer.Analyzed == false.
You must have initialized Native Audio before doing the analysis or else Native Audio will initialize with default options. (Remember you cannot initialize twice to fix initialization options)
By the analysis result you can see if the frame rate drop while using Native Audio or not. I have fixed most of the frame rate drop problem I found. But if there are more obscure devices that drop frame rate, this method can check it at runtime and by the returned result you can stop using Native Audio and return to Unity UnityEngine.AudioSource.
Declaration
public static NativeAudioAnalyzer SilentAnalyze()
Returns
| Type | Description |
|---|---|
NativeAudioAnalyzer |