Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaClient/Source/Sounds/Sound.cs
T
Alex Noir 2cb0ee73be Adds footstep sound variety, makes diving and clown suits have unique footstep sounds!
https://puu.sh/yQ8fs/61e12f15c6.webm
TODO: Get rid of the "damagesoundtype" system and replace it with simple "tag" checking to allow customizability from content pack side
Fix damagemodifier sounds never being played (I've never once heard LimbArmor play on anything but mantis)
2017-12-29 17:41:18 +03:00

272 lines
7.4 KiB
C#

using Barotrauma.Sounds;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
namespace Barotrauma
{
public class Sound
{
public static Vector3 CameraPos;
private static List<Sound> loadedSounds = new List<Sound>();
private static OggStream stream;
private OggSound oggSound;
private readonly string filePath;
private readonly bool destroyOnGameEnd;
private float baseVolume;
private float range;
private int alSourceId;
public bool IsPlaying
{
get
{
return SoundManager.IsPlaying(alSourceId);
}
}
private Sound(string file, bool destroyOnGameEnd)
{
filePath = file;
foreach (Sound loadedSound in loadedSounds)
{
if (loadedSound.filePath == file) oggSound = loadedSound.oggSound;
}
if (oggSound == null && !SoundManager.Disabled)
{
try
{
DebugConsole.Log("Loading sound " + file);
oggSound = OggSound.Load(file);
}
catch (Exception e)
{
DebugConsole.ThrowError("Failed to load sound "+file+"!", e);
}
ALHelper.Check();
}
baseVolume = 1.0f;
range = 1000.0f;
this.destroyOnGameEnd = destroyOnGameEnd;
loadedSounds.Add(this);
}
public string FilePath
{
get { return filePath; }
}
public int AlBufferId
{
get { return oggSound==null ? -1 : oggSound.AlBufferId; }
}
public static void Init()
{
SoundManager.Init();
}
public static Sound Load(string file, bool destroyOnGameEnd = true)
{
if (!File.Exists(file))
{
DebugConsole.ThrowError("File \"" + file + "\" not found!");
return null;
}
Sound dupe = Sound.loadedSounds.Find(s => s.filePath == file);
if (dupe != null)
return dupe;
return new Sound(file, destroyOnGameEnd);
}
public static Sound Load(XElement element, bool destroyOnGameEnd = true)
{
string filePath = element.GetAttributeString("file", "");
var newSound = new Sound(filePath, destroyOnGameEnd);
if (newSound != null)
{
newSound.baseVolume = element.GetAttributeFloat("volume", 1.0f);
newSound.range = element.GetAttributeFloat("range", 1000.0f);
Sound dupe = Sound.loadedSounds.Find(s => s.filePath == filePath && s.baseVolume == newSound.baseVolume && s.range == newSound.range);
if (dupe != null)
return dupe;
}
return newSound;
}
public int Play(float volume = 1.0f)
{
if (volume <= 0.0f) return -1;
alSourceId = SoundManager.Play(this, volume);
return alSourceId;
}
public int Play(Vector2 position)
{
return Play(baseVolume, range, position);
}
public int Play(float baseVolume, float range, Vector2 position)
{
Vector2 relativePos = GetRelativePosition(position);
float volume = GetVolume(relativePos, range, baseVolume);
if (volume <= 0.0f) return -1;
alSourceId = SoundManager.Play(this, relativePos, volume);
return alSourceId;
}
public void UpdatePosition(Vector2 position)
{
int sourceIndex = -1;
if (SoundManager.IsPlaying(this, out sourceIndex))
{
Vector2 relativePos = GetRelativePosition(position);
float volume = GetVolume(relativePos, range, baseVolume);
if (volume <= 0.0f)
{
SoundManager.Stop(this);
return;
}
SoundManager.UpdateSoundPosition(sourceIndex, relativePos, volume);
}
}
private float GetVolume(Vector2 relativePosition, float range, float baseVolume)
{
float volume = (range == 0.0f) ? 0.0f : MathHelper.Clamp(baseVolume * (range - (relativePosition.Length() * 100.0f)) / range, 0.0f, 1.0f);
return volume;
}
private Vector2 GetRelativePosition(Vector2 position)
{
return new Vector2(position.X - CameraPos.X, position.Y - CameraPos.Y) / 100.0f;
}
public int Loop(int sourceIndex, float volume)
{
if (volume <= 0.0f)
{
if (sourceIndex > 0)
{
SoundManager.Stop(sourceIndex);
sourceIndex = -1;
}
return sourceIndex;
}
int newIndex = SoundManager.Loop(this, sourceIndex, volume);
return newIndex;
}
public int Loop(int sourceIndex, float baseVolume, Vector2 position, float range)
{
Vector2 relativePos = GetRelativePosition(position);
float volume = GetVolume(relativePos, range, baseVolume);
if (volume <= 0.0f)
{
if (sourceIndex > 0)
{
SoundManager.Stop(sourceIndex);
sourceIndex = -1;
}
return sourceIndex;
}
alSourceId = SoundManager.Loop(this, sourceIndex, relativePos, volume);
return alSourceId;
}
public static void OnGameEnd()
{
List<Sound> removableSounds = loadedSounds.FindAll(s => s.destroyOnGameEnd);
foreach (Sound sound in removableSounds)
{
sound.Remove();
}
}
public void Remove()
{
//sound already removed?
if (!loadedSounds.Contains(this)) return;
loadedSounds.Remove(this);
if (alSourceId > 0 &&
(SoundManager.IsPlaying(alSourceId) || SoundManager.IsPaused(alSourceId)))
{
SoundManager.Stop(alSourceId);
ALHelper.Check();
}
foreach (Sound s in loadedSounds)
{
if (s.oggSound == oggSound) return;
}
SoundManager.ClearAlSource(AlBufferId);
ALHelper.Check();
if (oggSound != null)
{
oggSound.Dispose();
oggSound = null;
}
}
public static void StartStream(string file, float volume = 1.0f)
{
if (SoundManager.Disabled) return;
stream = SoundManager.StartStream(file, volume);
}
public static void StreamVolume(float volume = 1.0f)
{
if (SoundManager.Disabled) return;
stream.Volume = volume;
}
public static void StopStream()
{
if (stream != null) SoundManager.StopStream();
}
public static void Dispose()
{
SoundManager.Dispose();
}
}
}