using SFML.Audio; using System; using System.IO; namespace Otter { /// /// Class used to play a sound from a file or an IO Stream. Sounds are cached if loaded from a file. /// public class Sound { #region Static Fields static float globalVolume = 1; #endregion #region Static Properties /// /// The global volume of all sounds. /// public static float GlobalVolume { get { return globalVolume; } set { globalVolume = Util.Clamp(value, 0, 1); } } /// /// Where the Listener is in 3D space. /// public static Vector3 ListenerPosition { set { Listener.Position = (SFML.System.Vector3f)value; } get { return (Vector3)Listener.Position; } } /// /// The Listener's X position. /// public static float ListenerX { set { Listener.Position = new SFML.System.Vector3f(value, Listener.Position.Y, Listener.Position.Z); } get { return Listener.Position.X; } } /// /// The Listener's Y position. /// public static float ListenerY { set { Listener.Position = new SFML.System.Vector3f(Listener.Position.X, value, Listener.Position.Z); } get { return Listener.Position.Y; } } /// /// The Listener's Z position. /// public static float ListenerZ { set { Listener.Position = new SFML.System.Vector3f(Listener.Position.X, Listener.Position.Y, value); } get { return Listener.Position.Z; } } /// /// What direction the Listener is pointing. Should be a unit vector. /// public static Vector3 ListenerDirection { set { Listener.Direction = (SFML.System.Vector3f)value; } get { return (Vector3)Listener.Direction; } } #endregion #region Private Fields SFML.Audio.Sound sound; SoundBuffer buffer; #endregion #region Public Fields /// /// The local volume of this sound. /// public float Volume = 1f; #endregion #region Public Properties /// /// Adjust the pitch of the sound. Default value is 1. /// public float Pitch { set { sound.Pitch = value; } get { return sound.Pitch; } } /// /// The playback offset of the sound in milliseconds. /// public int Offset { set { sound.PlayingOffset = SFML.System.Time.FromMilliseconds(value); } get { return (int)sound.PlayingOffset.AsMilliseconds(); } } /// /// Determines if the sound should loop or not. /// public bool Loop { set { sound.Loop = value; } get { return sound.Loop; } } /// /// The duration of the sound in milliseconds. /// public int Duration { get { return (int)sound.SoundBuffer.Duration.AsMilliseconds(); } } /// /// Whether or not the sound plays relative to the Listener position. /// Only mono sounds are able to be spatial. /// public bool RelativeToListener { set { sound.RelativeToListener = value; } get { return sound.RelativeToListener; } } /// /// Where the sound is in 3D space. /// public Vector3 Position { set { sound.Position = (SFML.System.Vector3f)value; } get { return (Vector3)sound.Position; } } /// /// The sound's X position. /// public float X { set { sound.Position = new SFML.System.Vector3f(value, sound.Position.Y, sound.Position.Z); } get { return sound.Position.X; } } /// /// The sound's Y position. /// public float Y { set { sound.Position = new SFML.System.Vector3f(sound.Position.X, value, sound.Position.Z); } get { return sound.Position.Y; } } /// /// The sound's Z position. /// public float Z { set { sound.Position = new SFML.System.Vector3f(sound.Position.X, sound.Position.Y, value); } get { return sound.Position.Z; } } /// /// The sound's attenuation factor. /// Determines how the sound fades over distance. /// public float Attenuation { set { sound.Attenuation = value; } get { return sound.Attenuation; } } /// /// The minimum distance to hear the sound at max volume. /// Past this distance the sound is faded according to it's attenuation. /// 0 is an invalid value. /// public float MinimumDistance { set { sound.MinDistance = value; } get { return sound.MinDistance; } } /// /// Check if the Sound is currently playing. /// public bool IsPlaying { get { return sound.Status == SoundStatus.Playing; } } #endregion #region Constructors /// /// Load a new sound from a filepath. If this file has been used before it will be loaded from the cache. /// /// The path to the sound file. /// Determines if the sound should loop. public Sound(string source, bool loop = false) { buffer = Sounds.Load(source); sound = new SFML.Audio.Sound(buffer); Loop = loop; sound.RelativeToListener = false; } /// /// Load a new sound from an IO Stream. /// /// The memory stream of the sound data. /// Determines if the sound should loop. public Sound(Stream stream, bool loop = false) { buffer = new SoundBuffer(stream); sound = new SFML.Audio.Sound(buffer); Loop = loop; } /// /// Load a new sound from copying another sound. /// /// The sound to copy from. public Sound(Sound sound) { buffer = sound.buffer; this.sound = new SFML.Audio.Sound(buffer); Loop = sound.Loop; sound.RelativeToListener = sound.RelativeToListener; X = sound.X; Y = sound.Y; Z = sound.Z; Volume = sound.Volume; Pitch = sound.Pitch; Attenuation = sound.Attenuation; MinimumDistance = sound.MinimumDistance; Offset = sound.Offset; } #endregion #region Public Methods /// /// Play the sound. /// public void Play() { sound.Volume = Util.Clamp(GlobalVolume * Volume, 0f, 1f) * 100f; sound.Play(); } /// /// Stop the sound. /// public void Stop() { sound.Stop(); } /// /// Pause the sound. /// public void Pause() { sound.Pause(); } /// /// Centers the sound at the given position. /// /// /// /// public void CenterSound(float x, float y, float z) { Position = new Vector3(x, y, z); } /// /// Centers the sound at the given position. /// /// /// public void CenterSound(float x, float y) { CenterSound(x, y, Z); } /// /// Centers the sound at the given position. /// /// public void CenterSound(Vector3 position) { CenterSound(position.X, position.Y, position.Z); } /// /// Centers the sound at the given position. /// /// public void CenterSound(Vector2 position) { CenterSound(position.X, position.Y, Z); } #endregion #region Static Methods /// /// Centers the Listener at the given position. /// /// /// /// public static void CenterListener(float x, float y, float z) { ListenerPosition = new Vector3(x, y, z); } /// /// Centers the Listener at the given position. /// /// /// public static void CenterListener(float x, float y) { CenterListener(x, y, ListenerZ); } /// /// Centers the Listener at the given position. /// /// public static void CenterListener(Vector3 position) { CenterListener(position.X, position.Y, position.Z); } /// /// Centers the Listener at the given position. /// /// public static void CenterListener(Vector2 position) { CenterListener(position.X, position.Y, ListenerZ); } /// /// Points the Listener in the given direction. /// /// /// /// public static void PointListener(float x, float y, float z) { ListenerDirection = new Vector3(x, y, z); } /// /// Points the Listener in the given direction. /// /// /// public static void PointListener(float x, float y) { PointListener(x, y, ListenerDirection.Z); } /// /// Points the Listener in the given direction. /// /// public static void PointListener(Vector3 direction) { PointListener(direction.X, direction.Y, direction.Z); } /// /// Points the Listener in the given direction. /// /// public static void PointListener(Vector2 direction) { PointListener(direction.X, direction.Y, ListenerDirection.Z); } #endregion } }