I'm currently working on some audio processing code in Unity, and recently encountered a rather strange issue which I hope to resolve soon enough.
Basically, using OnAudioFilterRead callback function on an AudioSource when the playOnAwake flag is checked results in an unexpected behavior, i.e., the default Unity AudioSource stream seems to get played for a couple of buffers - bypassing OnAudioFilterRead function - until the script is initialized properly (assumably until Awake/OnEnable functions are done).
To emphasize the issue, here is a simple illustrative script that silences the audio source:
// This script is attached to a GameObject with an AudioSource.
// AudioSource has a clip attached to it, and playOnAwake flag is set to true.
[RequireComponent(typeof(AudioSource))]
public class MuteSource : MonoBehaviour {
void Awake () {
/*
* Some time-consuming code block.
*/
}
void OnAudioFilterRead (float[] data, int channels) {
for (int i = 0; i < data.Length; ++i) {
data[i] = 0.0f;
}
}
}
As mentioned, this script above only starts giving the silent output after the code block in Awake finishes (it plays the clip as if no script was attached until that).
I have played around with this to get a better idea of the underlying issue and even got stranger results. Firstly, adding Stop beforehand to Awake does not seem to affect anything:
void Awake () {
// The clip still plays as normal after this call.
AudioSource audioSource = GetComponent<AudioSource>();
audioSource.Stop();
/*
* Some time-consuming code block.
*/
}
Another thing I tried was to enforce muting the output by attaching a similar script on AudioListener, but still no luck:
// This script is attached to a GameObject with AudioListener.
[RequireComponent(typeof(AudioListener))]
public class MuteListener : MonoBehaviour {
void Awake () {
}
void OnAudioFilterRead (float[] data, int channels) {
for (int i = 0; i < data.Length; ++i) {
data[i] = 0.0f;
}
}
}
When combined, if both MuteSource and MuteListener is present in the scene, even MuteListener does not seem to be enough to enforce silencing the output, i.e., the problem remains as it is. In fact, I have tried different variations such as removing OnAudioFilterRead from AudioSource completely and adding Stop to Awake of MuteSource as described below which did not change the behavior. Likewise, moving the time-consuming code block on Awake function to OnEnable didn't help either.
The only workaround I could find was to change ScriptExecutionOrder to call MuteListener before MuteSource, which seems to work fine. Similarly, removing the time-consuming code block completely resolves the issue as expected.
All in all, I really appreciate if you have any suggestions/feedback on this. Thanks very much in advance!
In case anyone else encountered the issue, seems like the problem is resolved automatically in Unity 5.2.0B5 (or possibly some earlier version above 5.1.0). Strangely enough, I couldn't find anything specific regarding the fix in any of their release notes.