Why does AudioSource.PlayScheduled() play for an instant?

I am getting chirping/audio artifacts when using AudioSource.PlayScheduled().

I am using AudioSource.PlayScheduled() to sequence audio clips. I am using pretty much the exact setup as described in the documentation sample code. Two sources, alternate between the two, using AudioSettings.dspTime to PlayScheduled to start the next clip as the current one ends.

Sometimes, at the moment PlayScheduled() is called, the clip assigned to that audio source plays for an instant. It should not do that - it should remain silent until its scheduled time. The audiosource then goes idle as expected until the time in the future that was passed to it in PlayScheduled, then plays correctly. I verified it is actually the scheduled clip playing for an instant by using two very distinct clips, with unique audio at the start. You can hear it just long enough to identify it.

I have playOnAwake set to false on both audio sources.

It seems like everything works fine under light load. Only when there is stuff happening in the scene does it happen. Stats window is around 50 fps though, and profiler shows audio total cpu usage at 0.5-0.7%. That seems fine.

Does anybody know why PlayScheduled() is playing the clip for an instant when it is called?

I’ve encountered this too. It seems to be a bug. For the meantime, I fixed it by putting an audio filter to mute audio until the scheduled start time, e.g.:

	public class MyAudioPlayer : MonoBehaviour
	{
		public AudioSource m_audioSource;

		public void PlayScheduled(double dspStartTime)
		{
			m_startTime = dspStartTime;
			m_playbackUnmutePending = true; // weird bug, plays an artifact before scheduled time?
			m_audioSource.PlayScheduled(dspStartTime);
		}

		void OnAudioFilterRead(float[] data, int channels) 
		{
			if(!m_playbackUnmutePending) {
				return;
			}

			if(AudioSettings.dspTime >= m_startTime) {
				m_playbackUnmutePending = false;
				return;
			}

			for(int i = 0; i < data.Length; i++) {
				data *= 0f; // mute until start time cos PlaySchedule artifact.*
  •  	}*
    
  •  }*
    
  •  private bool m_playbackUnmutePending;*
    
  •  private double? m_startTime;*
    

}

I have another workaround for the bug which is launching LoadAudioData on awake and wait until song loads to continue using SongIsLoaded() consultor.

This way you can use a Load in background song like if it were Preloaded and you don’t get the bug. Note that for this workaround to work song must be marked as LoadInBackground

public void Awake()
{
	audiosource.audioClip.LoadAudioData ();
	StartCoroutine (WaitUntilSongIsLoaded ());
}

public bool SongIsLoaded()
{
	return audiosource.audioClip.loadState == AudioDataLoadState.Loaded;
}

private IEnumerator WaitUntilSongIsLoaded()
{
	while(audiosource.audioClip.loadState != AudioDataLoadState.Loaded)
	{
		yield return null;
	}
}

Then, you need to wait until all needed songs are loaded and when all SongIsLoaded return true then start the level. Also AudioDataLoadState.Fail handler should be added to the solution as well as unloading the song when not used.