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);
}| Method | Verb | Scope | Subject | Notes |
|---|---|---|---|---|
SetMusicProgress | Set | Progress | Music | Sends float progress in AudioParamKeys.State.Progress. |
RestoreMusicProgress | Restore | Progress | Music | No value parameter. |
SetAudioVolume | Set | Volume | Given subject | Sends the value as CoreParamKeys.ObjectValue. |
PlayClip | Play | none | SFX | Sends clip key. |
PlayClipWithCallback | Play | none | SFX | Adds the callback in AudioParamKeys.Debug.ClipResponse when it is not null. |
PlayMusic | Play | none | Music | Sends clip key. |
StopClip | Stop | none | SFX | Sends clip key and State.Stop set to true. |
PauseMusic | Pause | none | Music | Sends clip key. |
StopMusic | Stop | none | Music | Sends clip key. |
SetVolume | Set | Volume | Preset | Sends 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);
}BuildHolderHashmaprebuilds the lookup. Duplicate clip keys are logged, and the first occurrence is kept.GetHashedClipbuilds the lookup if it has not been built, then returns the clip data, or null with a warning if the key is missing.RefreshAllHashmapscallsRefreshHashmapon every holder and then callsBuildHolderHashmap.GetClipDurationreturns 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:
SetAudioTweenertakes a tweener. A null value logs a warning and disables fading.ReplayAudiorestarts a source that is in the tracked state list.PlayAudioresolves the clip in the current language and plays it on a pooled sound effect source.PlayMusicresolves the clip without a language, and plays it on a pooled music source.PauseAudiofades the source out and then pauses it.ResumeMusicunpauses the source and fades it back to the clip's volume, or to 1 if the clip is not found.StopAudiokills any running fade, then fades out and deactivates the source.StopMusicreleases the tracked state for the clip.GetFirstPlayingAudioSourcereturns the first pooled source that is playing the clip.RestoreMusicProgressandSetMusicProgresscall the same members onLayeredMusicPlayer. Both do nothing when no player is set.StopLayeredMusiccallsStoponLayeredMusicPlayer.SetAudioContextstores the context.ApplyVolumePresetapplies a preset to the mixer. AVolumeSource.Savedvalue loads the preset fromGetVolumePreset. A channel of None applies all three channels.RequestMusicresumes a paused clip, does nothing if the clip is already playing, or plays it. WhenisLayeredis false, it releases all other tracked states first.GetAudioStatereturns the tracked state for the clip, or null.PauseMusicpauses the clip and marks its state as reserved.HandleCommandreceives anICommand. It currently routes every verb toHandleStandardAudioCommand.HandleStandardAudioCommandreads the verb, scope, and subject, and calls the matching method.ProcessEventroutes Domain.UI events to the UI handler.EnterLayeredAudioModesets layering on.EnterNonLayeredAudioModesets 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);
}Playcopies 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 invokesonResponsewith the clip.FadePausefades to 0 over 1 second, then pauses the source.FadeStopfades 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.
GetAudioSourcereturns the first inactive sound effect source, activated. It returns null if none is free.GetMusicSourcereturns a music source already playing the clip, if one exists. Otherwise it returns and activates the first inactive music source.FindPlayingSourcechecks 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;
}GetClipByIDreturns 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.GetClipsForLanguagereturns 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);
}DomainreturnsDomain.Audioand cannot be overridden.Initcallsbase.Init(), cachesAudioManager.Instance, and registersOnEventfor Domain.UI on the event bus.OnEventforwards the event toAudioManager.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);
}