Skip to content
Shmellyorc edited this page Aug 27, 2026 · 1 revision

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

Sound assets are loaded through the AssetManager.

var explosion = AssetManager.Instance.Load<Sound>("explosion.wav");
var music = AssetManager.Instance.Load<Sound>("background.ogg");

Supported Formats

.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 Priority

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.

Sound Instances

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();

Playback Control

instance.Play();
instance.Pause();
instance.Stop();

Sound Status

switch (instance.Status)
{
    case SoundStatus.Playing: break;
    case SoundStatus.Paused: break;
    case SoundStatus.Stopped: break;
}

Properties

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

Events

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

Sound Categories

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

Sound Helper

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

Extensions

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

Sound Instance Pool

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.

Audio Settings

Configure the audio system through GameSettings:

GameSettings.Instance.SetAudioLimit(128);  // Maximum concurrent voices

The default is 128. Minimum is 32.


Back to Home

Clone this wiki locally