-
Notifications
You must be signed in to change notification settings - Fork 1
Audio
Void's audio system provides sound playback with pooling, priority-based voice allocation, category-based volume control, and a full event system.
Sound assets are loaded through the AssetManager.
var explosion = AssetManager.Instance.Load<Sound>("explosion.wav");
var music = AssetManager.Instance.Load<Sound>("background.ogg");
.wav, .ogg, .mp3, .flac, .aiff, .au, .raw, .paf, .svx, .nist, .voc, .ircam,
.w64, .mat4, .mat5, .pvf, .htk, .sds, .avr, .sd2, .caf, .wve, .mpc2k, .rf64
Sound assets have a priority level that determines how they compete for voices.
var explosion = AssetManager.Instance.Load<Sound>("explosion.wav");
// Default priority is Normal
You can set priority when creating instances. Priority levels are: Low, Normal, High, Critical. Critical sounds are never stolen.
Create a sound instance from an asset to play it.
var instance = explosion.CreateInstance(SoundCategory.SFX);
instance.Volume = 0.8f;
instance.Pan = -0.5f;
instance.Pitch = 1.2f;
instance.Looping = true;
instance.Play();
instance.Play();
instance.Pause();
instance.Stop();
switch (instance.Status)
{
case SoundStatus.Playing: break;
case SoundStatus.Paused: break;
case SoundStatus.Stopped: break;
}
float volume = instance.Volume; // 0 to 1
float pan = instance.Pan; // -1 (left) to 1 (right)
float pitch = instance.Pitch; // 0.1 to 10
float playTime = instance.PlayTime; // Current playback time in seconds
float duration = instance.Duration; // Total duration in seconds
float progress = instance.Progress; // 0 to 1
instance.SoundCompleted += (s, e) =>
{
Console.WriteLine($"Sound finished! Looped {e.LoopCount} times");
instance.Dispose();
};
instance.SoundLooped += (s, e) =>
{
Console.WriteLine($"Loop iteration {e.LoopCount}");
};
instance.SoundStopped += (s, e) =>
{
Console.WriteLine($"Sound stopped. Was playing: {e.WasPlaying}");
};
instance.SoundError += (s, e) =>
{
Console.WriteLine($"Error: {e.ErrorMessage}");
};
Categories group sounds for volume control. You can define your own enum.
public enum SoundCategory { SFX, Music, UI, Ambient }
Create instances with a category:
var instance = explosion.CreateInstance(SoundCategory.SFX);
var musicInstance = music.CreateInstance(SoundCategory.Music);
The SoundHelper provides convenient shortcuts for common operations.
Master Volume
SoundHelper.MasterVolume = 0.8f;
Category Volumes
SoundHelper.SetCategoryVolume(SoundCategory.SFX, 0.9f);
SoundHelper.SetCategoryVolume(SoundCategory.Music, 0.5f);
float sfxVolume = SoundHelper.GetCategoryVolume(SoundCategory.SFX);
Play One-Shot
SoundHelper.PlayPooled(explosion, 0.8f, 0f, 1f, SoundCategory.SFX);
Play with Pitch Variation
SoundHelper.PlayPooledWithVariation(explosion, 0.15f, 0.8f, 0f, SoundCategory.SFX);
Batch Operations
SoundHelper.StopAll();
SoundHelper.PauseAll();
SoundHelper.ResumeAll();
Sound Groups Register a group of sounds for random selection:
SoundHelper.RegisterSoundGroup("footsteps", footstep1, footstep2, footstep3);
Play a random sound from the group:
SoundHelper.PlayFromGroup("footsteps", 0.7f, 0f, 1f, SoundCategory.SFX, true);
The SoundExtensions class provides fluent and convenience methods.
Fluent Configuration
sound.CreateInstance()
.WithVolume(0.8f)
.WithPan(-0.5f)
.WithPitch(1.2f)
.WithLooping(true)
.PlayWith(0.8f, -0.5f, 1.2f);
Stop and Dispose
instance.StopAndDispose();
Play and Forget
sound.PlayAndForget(0.8f, 0f, 1f, SoundCategory.SFX);
Play Random from Collection
var sounds = new[] { sound1, sound2, sound3 };
sounds.PlayRandom(0.7f);
sounds.PlayRandomWithVariation(0.15f, 0.7f);
sounds.PlayRandomAndForget(0.7f);
sounds.PlayAll(0.7f);
The pool manages all sound instances and handles voice allocation automatically.
Voice Allocation Strategy
When all instances are active:
- Recycles any stopped instances first
- Steals the lowest priority playing instance if the new sound has higher priority
- Steals the oldest playing instance as a fallback
Pool Status
int active = SoundHelper.ActiveSoundCount;
int available = SoundHelper.AvailableSoundCount;
int total = SoundHelper.TotalSoundCount;
bool exhausted = SoundHelper.IsPoolExhausted;
The pool runs a background update loop that handles completion detection and automatic recycling. You don't need to manually manage instances.
Configure the audio system through GameSettings:
GameSettings.Instance.SetAudioLimit(128); // Maximum concurrent voices
The default is 128. Minimum is 32.