using System; namespace Susurrus.XAudio2 { /// /// Source voices that share one format, handed out and taken back. /// public class SourceVoicePool { private readonly SourceVoice[] all; private readonly SourceVoice[] idle; private int idleCount; public int ChannelCount { get; } public SampleFormat Format { get; } /// /// Gets how many voices the pool holds, in use or not. /// public int Capacity => all.Length; public SourceVoicePool(int channelCount, SampleFormat format, SourceVoice[] voices) { if (voices == null) { throw new ArgumentNullException(nameof(voices)); } ChannelCount = channelCount; Format = format; all = (SourceVoice[])voices.Clone(); idle = (SourceVoice[])voices.Clone(); idleCount = idle.Length; } /// /// Takes an idle voice out of the pool. Returns null when every voice is in use. /// public SourceVoice Take() { if (idleCount == 0) { return null; } return idle[--idleCount]; } /// /// Puts a voice taken from this pool back. Returning one that isn't in use, or that came from elsewhere, /// throws. /// public void Return(SourceVoice voice) { bool isOurs = Array.IndexOf(all, voice) >= 0; bool isIdle = Array.IndexOf(idle, voice, 0, idleCount) >= 0; if (!isOurs || isIdle) { throw new ArgumentException("That voice isn't one this pool has handed out.", nameof(voice)); } idle[idleCount++] = voice; } /// /// Destroys every voice, including those in use. /// public void Destroy() { for (int i = 0; i < all.Length; ++i) { all[i].Destroy(); } idleCount = 0; } } }