using System; namespace MoonWorks.Audio { // NOTE: all sounds played with a SoundSequence must have the same audio format! public class SoundSequence : SourceVoice { public int NeedSoundThreshold = 0; public delegate void OnSoundNeededFunc(); public OnSoundNeededFunc OnSoundNeeded; public SoundSequence(AudioDevice device, ushort formatTag, ushort bitsPerSample, ushort blockAlign, ushort channels, uint samplesPerSecond) : base(device, formatTag, bitsPerSample, blockAlign, channels, samplesPerSecond) { device.AddSoundSequenceReference(this); OnUpdate += Update; } public SoundSequence(AudioDevice device, StaticSound templateSound) : base(device, templateSound.FormatTag, templateSound.BitsPerSample, templateSound.BlockAlign, templateSound.Channels, templateSound.SamplesPerSecond) { device.AddSoundSequenceReference(this); OnUpdate += Update; } private void Update() { lock (StateLock) { if (IsDisposed) { return; } if (State != SoundState.Playing) { return; } if (NeedSoundThreshold > 0) { FAudio.FAudioSourceVoice_GetState( Handle, out var state, FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED ); var queuedBufferCount = state.BuffersQueued; for (int i = 0; i < NeedSoundThreshold - queuedBufferCount; i += 1) { if (OnSoundNeeded != null) { OnSoundNeeded(); } } } } } public void EnqueueSound(StaticSound sound) { #if DEBUG if ( sound.FormatTag != Format.wFormatTag || sound.BitsPerSample != Format.wBitsPerSample || sound.Channels != Format.nChannels || sound.SamplesPerSecond != Format.nSamplesPerSec ) { Logger.LogWarn("Playlist audio format mismatch!"); } #endif lock (StateLock) { FAudio.FAudioSourceVoice_SubmitSourceBuffer( Handle, ref sound.Handle, IntPtr.Zero ); } } } }