Files
alien-attack/AlientAttack.MonoGame/Audio/VariantSoundPool.cs

48 lines
1.5 KiB
C#

using Microsoft.Xna.Framework.Audio;
using System;
namespace AlienAttack.MonoGame.Audio;
public sealed class VariantSoundPool
{
private readonly SoundPool[] _variantPools;
private readonly Random _rng;
private int _lastIndex = -1;
public VariantSoundPool(SoundEffect[] variants, int voicesPerVariant, Random rng)
{
if (variants == null || variants.Length == 0)
throw new ArgumentException("At least one variant is required.", nameof(variants));
ArgumentOutOfRangeException.ThrowIfLessThan(voicesPerVariant, 1);
_rng = rng ?? throw new ArgumentNullException(nameof(rng));
_variantPools = new SoundPool[variants.Length];
for (int i = 0; i < variants.Length; i++)
_variantPools[i] = new SoundPool(variants[i], voicesPerVariant);
}
public void Play(float volume = 1f, float pitch = 0f, float pan = 0f, bool avoidImmediateRepeat = true)
{
int idx = PickVariantIndex(avoidImmediateRepeat);
_variantPools[idx].Play(volume, pitch, pan);
}
private int PickVariantIndex(bool avoidImmediateRepeat)
{
if (_variantPools.Length == 1)
return 0;
int idx = _rng.Next(_variantPools.Length);
if (!avoidImmediateRepeat) { _lastIndex = idx; return idx; }
// Avoid playing the exact same sample twice in a row (nice polish)
if (idx == _lastIndex)
idx = (idx + 1 + _rng.Next(_variantPools.Length - 1)) % _variantPools.Length;
_lastIndex = idx;
return idx;
}
}