docs
Systems
Presentation
AudioSystem
Public API Reference

AudioCommandFactory

Static class for building and sending Audio-domain commands.

public static class AudioCommandFactory
{
    public static void SetMusicProgress(float n);
    public static void RestoreMusicProgress();
    public static void SetAudioVolume(AudioSubject audioSubject, float value);
    public static void PlayClip(string clipKey);
    public static void PlayClipWithCallback(string clipKey, Action<AudioClip> onClipReady);
    public static void PlayMusic(string clipKey);
    public static void StopClip(string clipKey);
    public static void PauseMusic(string clipKey);
    public static void StopMusic(string clipKey);
    public static void SetVolume(VolumeContext context = VolumeContext.None,
                                 VolumeSource source = VolumeSource.None,
                                 VolumeChannel channel = VolumeChannel.None,
                                 VolumeMix volumePreset = default);
}
MethodVerbScopeSubjectNotes
SetMusicProgressSetProgressMusicSends float progress in AudioParamKeys.State.Progress.
RestoreMusicProgressRestoreProgressMusicNo value parameter.
SetAudioVolumeSetVolumeGiven subjectSends the value as CoreParamKeys.ObjectValue.
PlayClipPlaynoneSFXSends clip key.
PlayClipWithCallbackPlaynoneSFXAdds the callback in AudioParamKeys.Debug.ClipResponse when it is not null.
PlayMusicPlaynoneMusicSends clip key.
StopClipStopnoneSFXSends clip key and State.Stop set to true.
PauseMusicPausenoneMusicSends clip key.
StopMusicStopnoneMusicSends clip key.
SetVolumeSetVolumePresetSends source, channel, preset, and context.

AudioCommandVerb

public enum AudioCommandVerb
{
    OnGenieDialogueShow = 1,
    Set = 0,
    Restore = 2,
    Play = 3,
    Stop = 4,
    Pause = 5,
}

AudioScope

public enum AudioScope
{
    Progress = 0,
    Volume = 1,
}

ContractConstantsAudio

Static class of string constants for audio contracts, routing keys, and parameter tokens.

public static class ContractConstantsAudio
{
    public const string Base;
    public const string Volume;
    public const string AudioSubject;
    public const string Context;
    public const string Source;
    public const string Channel;
    public const string PresetId;
    public const string State;
    public const string Layout;
    public const string Visual;
    public const string Command;
    public const string Clip;
    public const string Group;
    public const string AudioDebug;
    public const string Pitch;
    public const string Loop;
    public const string Delay;
    public const string Progress;
    public const string Action;
    public const string Name;
    public const string Payload;
    public const string StateValue;
    public const string Category;
    public const string ClipId;
    public const string ClipKey;
    public const string Stop;
    public const string DebugContext;
    public const string DebugEnable;
    public const string ClipResponse;
    public const string DurationBatchResponse;
    public const string AudioScopeKey;
}

Base values: Base is core.audio.. Volume is core.audio.volume.. State, Layout, Visual, Command, Clip, Group, and AudioDebug are the base strings with the prefix core.audio. and a domain segment and trailing dot.

AudioParamKeys

Static container of typed ParamKey<T> fields for audio commands.

public static class AudioParamKeys
{
    public static readonly ParamKey<AudioSubject> AudioSubject;
 
    public static class Command
    {
        public static readonly ParamKey<AudioScope> AudioScope;
    }
 
    public static class Clip
    {
        public static readonly ParamKey<string> ClipKey;
    }
 
    public static class Group
    {
        public static readonly ParamKey<string> GroupName;
    }
 
    public static class State
    {
        public static readonly ParamKey<float> Delay;
        public static readonly ParamKey<float> Progress;
        public static readonly ParamKey<bool> Stop;
    }
 
    public static class Debug
    {
        public static readonly ParamKey<Action<AudioClip>> ClipResponse;
        public static readonly ParamKey<Action<Dictionary<string, float>>> DurationBatchResponse;
    }
 
    public static class Volume
    {
        public static readonly ParamKey<VolumeSource> Source;
        public static readonly ParamKey<VolumeContext> Context;
        public static readonly ParamKey<VolumeChannel> Channel;
        public static readonly ParamKey<VolumeMix> Preset;
    }
}

AudioClipLookup

Resolves AudioClipData by clip key. It does not play audio.

public class AudioClipLookup
{
    public AudioClipLookup(List<AudioClipHolder> audios,
                           List<AudioClipHolder> music,
                           List<LocalizedGroupAudioClipHolder> localized);
 
    public void BuildHolderHashmap();
    public AudioConstants.AudioClipData GetHashedClip(string clipKey, string languageKey = null);
    public void RefreshAllHashmaps();
    public bool ContainsClip(string clipKey);
    public AudioClipHolder GetHolderForClip(string clipKey);
    public AudioClip GetClipAudio(string clipKey, string languageKey);
    public float GetClipDuration(string clipKey, string languageKey);
}
  • BuildHolderHashmap rebuilds the lookup. Duplicate clip keys are logged, and the first occurrence is kept.
  • GetHashedClip builds the lookup if it has not been built, then returns the clip data, or null with a warning if the key is missing.
  • RefreshAllHashmaps calls RefreshHashmap on every holder and then calls BuildHolderHashmap.
  • GetClipDuration returns the clip length in seconds, or 0 if the clip is missing.

AudioConstants

public class AudioConstants
{
    public class AudioClipData
    {
        public string ClipKey;
        public AudioClip Clip;
        public float Volume;     // range 0 to 1
        public float Pitch;      // range -3 to 3
        public int Priority;     // range 0 to 256
        public bool Loop = false;
        public bool PlayOnAwake = false;
        public AudioMixerGroup Mixer;
    }
 
    public const string InvalidClip = "InvalidClip";
    public const int LayeredMusicDefaultValue = 0;
    public const string MasterVolumeParam = "MasterVolume";
    public const string MusicVolumeParam = "MusicVolume";
    public const string SfxVolumeParam = "SFXVolume";
    public const float MuteDb = -80f;
    public const string LayeredMusicProgress = "Progress";
}

AudioManager

Abstract MonoBehaviour that runs audio playback, music state, volume, and command handling. Project subclasses implement the abstract members listed below.

public abstract class AudioManager : MonoBehaviour
{
    public static AudioManager Instance;
    public AudioMixerManager AudioMixer;
    public List<AudioClipHolder> AudiosHolder, MusicHolder;
    public List<LocalizedGroupAudioClipHolder> LocalizedGroupAudiosHolder;
    public int PooledObjectsAudio = 10;
    public int PooledObjectsMusic = 5;
    public ILayeredMusicPlayer LayeredMusicPlayer;
 
    public void SetAudioTweener(IAudioTweener tweener);
    public void SetLayeredMusicPlayer(ILayeredMusicPlayer player);
    public void ReplayAudio(AudioSource source);
    public AudioSource PlayAudio(string clipKey, Action<AudioClip> onResponse = null);
    public AudioSource PlayMusic(string clipKey, Action<AudioClip> onResponse = null);
    public void PauseAudio(string clipKey, AudioSource audioToPause);
    public void ResumeMusic(string clipKey, AudioSource audioSource);
    public void StopAudio(AudioSource audioToStop);
    public void StopMusic(string clipKey);
    public AudioSource GetFirstPlayingAudioSource(string clipKey);
    public void RestoreMusicProgress();
    public void SetMusicProgress(float progress);
    public void StopLayeredMusic();
    public void SetAudioContext(VolumeContext context);
    public void ApplyVolumePreset(VolumeSource source, VolumeChannel channel, VolumeMix volumePreset);
    public void RequestMusic(string clipKey, bool isLayered, Action<AudioClip> onResponse);
    public AudioState GetAudioState(string clipKey);
    public void PauseMusic(string clipKey);
    public void HandleCommand(ICommand e);
    public void HandleStandardAudioCommand(ICommand e);
    public void ProcessEvent(Event e);
    public void EnterLayeredAudioMode();
    public void EnterNonLayeredAudioMode();
 
    protected abstract string GetCurrentLanguage();
    protected abstract VolumeMix GetVolumePreset();
    protected abstract void HandleButtonClicked(Event e);
    protected abstract void HandleApplyButtonClicked();
}

Behavior notes for the public methods:

  • SetAudioTweener takes a tweener. A null value logs a warning and disables fading.
  • ReplayAudio restarts a source that is in the tracked state list.
  • PlayAudio resolves the clip in the current language and plays it on a pooled sound effect source.
  • PlayMusic resolves the clip without a language, and plays it on a pooled music source.
  • PauseAudio fades the source out and then pauses it.
  • ResumeMusic unpauses the source and fades it back to the clip's volume, or to 1 if the clip is not found.
  • StopAudio kills any running fade, then fades out and deactivates the source.
  • StopMusic releases the tracked state for the clip.
  • GetFirstPlayingAudioSource returns the first pooled source that is playing the clip.
  • RestoreMusicProgress and SetMusicProgress call the same members on LayeredMusicPlayer. Both do nothing when no player is set.
  • StopLayeredMusic calls Stop on LayeredMusicPlayer.
  • SetAudioContext stores the context.
  • ApplyVolumePreset applies a preset to the mixer. A VolumeSource.Saved value loads the preset from GetVolumePreset. A channel of None applies all three channels.
  • RequestMusic resumes a paused clip, does nothing if the clip is already playing, or plays it. When isLayered is false, it releases all other tracked states first.
  • GetAudioState returns the tracked state for the clip, or null.
  • PauseMusic pauses the clip and marks its state as reserved.
  • HandleCommand receives an ICommand. It currently routes every verb to HandleStandardAudioCommand.
  • HandleStandardAudioCommand reads the verb, scope, and subject, and calls the matching method.
  • ProcessEvent routes Domain.UI events to the UI handler.
  • EnterLayeredAudioMode sets layering on. EnterNonLayeredAudioMode sets layering off, and stops layered music if a player is set.

AudioMixerManager

MonoBehaviour that sets and reads volume levels on the mixer, in decibels.

public class AudioMixerManager : MonoBehaviour
{
    public AudioMixer AudioMixer;
 
    public void SetMasterVolume(float volume);
    public void SetMusicVolume(float volume);
    public void SetSFXVolume(float volume);
    public float GetMasterVolume();
    public float GetMusicVolume();
    public float GetSFXVolume();
}

The methods use the parameter names in AudioConstants: MasterVolume, MusicVolume, and SFXVolume.

AudioPlaybackUtility

Static helper that applies clip data to a source and runs fades through an IAudioTweener.

public static class AudioPlaybackUtility
{
    public static void Play(MonoBehaviour runner,
                            AudioSource source,
                            AudioConstants.AudioClipData audioData,
                            IAudioTweener tweener,
                            Action<AudioClip> onResponse);
 
    public static void FadePause(AudioSource source, IAudioTweener tweener);
    public static void FadeStop(AudioSource source, IAudioTweener tweener);
}
  • Play copies the clip settings to the source, activates it, starts playback at volume 0, and fades to the clip volume over 0.3 seconds. For non-looping clips, it then starts a coroutine that waits until playback ends, deactivates the source, and invokes onResponse with the clip.
  • FadePause fades to 0 over 1 second, then pauses the source.
  • FadeStop fades to 0 over 1 second, then stops the source and deactivates it.

AudioSourcePool

Pool of pre-created AudioSource components on child GameObjects.

public class AudioSourcePool
{
    public AudioSourcePool(Transform parent, int pooledAudioCount, int pooledMusicCount);
 
    public IReadOnlyList<AudioSource> MusicSources { get; }
 
    public AudioSource GetAudioSource();
    public AudioSource GetMusicSource(AudioClip clip);
    public AudioSource FindPlayingSource(AudioClip clip);
}
  • The constructor creates the sources and deactivates them.
  • GetAudioSource returns the first inactive sound effect source, activated. It returns null if none is free.
  • GetMusicSource returns a music source already playing the clip, if one exists. Otherwise it returns and activates the first inactive music source.
  • FindPlayingSource checks music sources, then sound effect sources, for one playing the clip.

IAudioTweener

public interface IAudioTweener
{
    void FadeVolume(AudioSource source, float targetVolume, float duration, Action onComplete = null);
    void Kill(AudioSource source);
}

Defined in SaffronLibrary.Prime.Systems.Audio.Interfaces.

AudioClipHolder

ScriptableObject that stores a list of clips and a hashmap for lookup.

public class AudioClipHolder : ScriptableObject
{
    public List<AudioConstants.AudioClipData> Audios;
    protected bool _isHashmapBuilt;
 
    public virtual void BuildHashmap();
    protected void EnsureHashmapBuilt();
    public virtual AudioConstants.AudioClipData GetClipByID(string clipKey);
    public virtual AudioConstants.AudioClipData GetClipByID(string clipKey, string languageKey);
    public virtual bool ContainsClip(string clipKey);
    public virtual List<string> GetAllClipIDs();
    public virtual void RefreshHashmap();
}

The asset menu is Audio/Clips/AudioClipsHolder. The first occurrence of a duplicate clip key is kept, and later ones are logged.

GroupAudioClipHolder

public abstract class GroupAudioClipHolder : AudioClipHolder
{
    public abstract List<AudioConstants.AudioClipData> GetClips(string languageKey = null);
}

LocalizedGroupAudioClipHolder

ScriptableObject that stores clips per slide group and per language.

public class LocalizedGroupAudioClipHolder : AudioClipHolder
{
    public string GroupName;
    public List<LocalizedAudioSlideGroup> SlideGroups;
 
    public override void BuildHashmap();
    public override AudioConstants.AudioClipData GetClipByID(string clipKey, string languageKey);
    public override bool ContainsClip(string clipKey);
    public override List<string> GetAllClipIDs();
    public List<string> GetClipsForLanguage(string language);
    public override void RefreshHashmap();
}
 
[System.Serializable]
public class LocalizedAudioVariant
{
    public string Language;
    public List<AudioConstants.AudioClipData> Clips;
}
 
[System.Serializable]
public class LocalizedAudioSlideGroup
{
    public string SlideName;
    public List<LocalizedAudioVariant> LanguageVariants;
}
  • GetClipByID returns the clip for the requested language. If that language is missing, it returns the first available language for the key. It returns null if the key is missing.
  • GetClipsForLanguage returns the clip keys that have a variant in the language.

NonLocalizedGroupAudioClipHolder

public class NonLocalizedGroupAudioClipHolder : GroupAudioClipHolder
{
    public List<AudioClipSubGroup> SubGroups;
    public string GroupName;
 
    public override AudioConstants.AudioClipData GetClipByID(string clipKey);
    public override List<AudioConstants.AudioClipData> GetClips(string languageKey = null);
}
 
[System.Serializable]
public class AudioClipSubGroup
{
    public string SubGroupName;
    public List<AudioConstants.AudioClipData> Clips;
}

GetClipByID sets the inherited Audios list to the flattened result of GetClips before it looks up the key. This rewrites the Audios field each time it is called.

ILayeredMusicPlayer

Defined in SaffronLibrary.Prime.Systems.Audio.Interfaces.

public interface ILayeredMusicPlayer
{
    bool IsPlaying { get; }
    void Play();
    void Stop();
    void SetProgress(float value);
    void RestoreProgress();
}

ILayeredMusicDataStore

Defined in SaffronLibrary.Prime.Systems.Audio.Interfaces.

public interface ILayeredMusicDataStore
{
    void SaveProgress(float progress);
    float GetProgress();
}

AudioSubject

public enum AudioSubject
{
    Music = 0,
    SFX = 1,
    Preset = 2,
    Master = 3,
}

Audio enums

public enum PlaybackStatus
{
    None = 0,
    Playing = 1,
    Stopped = 2,
    Paused = 3
}
 
public enum AudioGroupType
{
    OpeningCinematic,
    ClosingCinematic,
    Invalid,
}
 
public enum VolumeChannel
{
    None = 0,
    SFX = 1,
    Music = 2,
    Master = 3
}
 
public enum VolumeSource
{
    None = 0,
    Saved = 1,
    Runtime = 2,
    Preset = 3
}
 
public enum VolumeContext
{
    None = 0,
    Gameplay = 1,
    UI = 2,
}

AudioFlowController

Abstract FlowController for the Audio domain. It also receives UI events.

public abstract class AudioFlowController : FlowController, IEventReceiver
{
    protected sealed override Domain Domain { get; }
    protected AudioManager audioManager;
 
    public override void Init();
    public virtual void OnEvent(Event e);
}
  • Domain returns Domain.Audio and cannot be overridden.
  • Init calls base.Init(), caches AudioManager.Instance, and registers OnEvent for Domain.UI on the event bus.
  • OnEvent forwards the event to AudioManager.ProcessEvent.

HandleCommand is declared abstract in FlowController. Project subclasses implement it.

AudioState

public class AudioState
{
    public int ClipId;
    public PlaybackStatus PlaybackStatus;
    public AudioSource LinkedSource;
    public string ClipKey;
    public bool IsReserved;
}

ClipId is ClipKey.GetHashCode(). IsReserved keeps the state when it is released, so the source can be resumed.

VolumeMix

public struct VolumeMix
{
    public float SFX;
    public float Music;
    public float Master;
 
    public VolumeMix(float sfx, float music, float master);
}