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;
}
}
}