using Robust.Shared.Serialization; using System; using System.Diagnostics.Contracts; using Robust.Shared.Serialization.Manager; using Robust.Shared.Serialization.Manager.Attributes; namespace Robust.Shared.Audio { /// /// Contains common audio parameters for audio playback on the client. /// [Serializable, NetSerializable] [DataDefinition] public struct AudioParams : IPopulateDefaultValues { /// /// Base volume to play the audio at, in dB. /// [DataField("volume")] public float Volume { get; set; } /// /// Scale for the audio pitch. /// [DataField("pitchscale")] public float PitchScale { get; set; } /// /// Audio bus to play on. /// [DataField("busname")] public string BusName { get; set; } /// /// Only applies to positional audio. /// The maximum distance from which the audio is hearable. /// [DataField("maxdistance")] public float MaxDistance { get; set; } /// /// Only applies to positional audio. /// Positional audio is dampened over distance with this as exponent. /// [DataField("attenuation")] public float Attenuation { get; set; } /// /// Only applies to global (non-positional) audio. /// Target channels if the audio configuration has more than 2 speakers. /// [DataField("mixtarget")] public AudioMixTarget MixTarget { get; set; } [DataField("loop")] public bool Loop { get; set; } [DataField("playoffset")] public float PlayOffsetSeconds { get; set; } // For the max distance value: it's 2000 in Godot, but I assume that's PIXELS due to the 2D positioning, // so that's divided by 32 (EyeManager.PIXELSPERMETER). /// /// The "default" audio configuration. /// public static readonly AudioParams Default = new(0, 1, "Master", 62.5f, 1, AudioMixTarget.Stereo, false, 0f); public AudioParams(float volume, float pitchScale, string busName, float maxDistance, float attenuation, AudioMixTarget mixTarget, bool loop, float playOffsetSeconds) : this() { Volume = volume; PitchScale = pitchScale; BusName = busName; MaxDistance = maxDistance; Attenuation = attenuation; MixTarget = mixTarget; Loop = loop; PlayOffsetSeconds = playOffsetSeconds; } /// /// Returns a copy of this instance with a new volume set, for easy chaining. /// /// The new volume. [Pure] public AudioParams WithVolume(float volume) { var me = this; me.Volume = volume; return me; } /// /// Returns a copy of this instance with a new pitch scale set, for easy chaining. /// /// The new pitch scale. [Pure] public AudioParams WithPitchScale(float pitch) { var me = this; me.PitchScale = pitch; return me; } /// /// Returns a copy of this instance with a new bus name set, for easy chaining. /// /// The new bus name. [Pure] public AudioParams WithBusName(string bus) { var me = this; me.BusName = bus; return me; } /// /// Returns a copy of this instance with a new attenuation set, for easy chaining. /// /// The new attenuation. [Pure] public AudioParams WithAttenuation(float attenuation) { var me = this; me.Attenuation = attenuation; return me; } /// /// Returns a copy of this instance with a new max distance set, for easy chaining. /// /// The new max distance. [Pure] public AudioParams WithMaxDistance(float dist) { var me = this; me.MaxDistance = dist; return me; } /// /// Returns a copy of this instance with a new mix target set, for easy chaining. /// /// The new mix target. [Pure] public AudioParams WithMixTarget(AudioMixTarget mixTarget) { var me = this; me.MixTarget = mixTarget; return me; } /// /// Returns a copy of this instance with a loop set, for easy chaining. /// /// The new loop. [Pure] public AudioParams WithLoop(bool loop) { var me = this; me.Loop = loop; return me; } [Pure] public AudioParams WithPlayOffset(float offset) { var me = this; me.PlayOffsetSeconds = offset; return me; } public void PopulateDefaultValues() { PitchScale = 1f; BusName = "Master"; MaxDistance = 62.5f; Attenuation = 1f; MixTarget = AudioMixTarget.Stereo; } } /// /// Controls target channels for non-positional audio if the audio configuration has more than 2 speakers. /// public enum AudioMixTarget : byte { // These match the values in the Godot enum, // but this is shared so we can't reference it. /// /// The audio will only be played on the first channel. /// Stereo = 0, /// /// The audio will be played on all surround channels. /// Surround = 1, /// /// The audio will be played on the second channel, which is usually the center. /// Center = 2, } }