48 lines
1.5 KiB
C#
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;
|
|
}
|
|
} |