You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
12 KiB
C#

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