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,
}
}