(61d00a474) v0.9.7.1
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
using System;
|
||||
using OpenAL;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.IO;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
public abstract class Sound : IDisposable
|
||||
{
|
||||
protected bool disposed;
|
||||
public bool Disposed
|
||||
{
|
||||
get { return disposed; }
|
||||
}
|
||||
|
||||
public SoundManager Owner
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public string Filename
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public XElement XElement
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public bool Stream
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public bool StreamsReliably
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public virtual SoundManager.SourcePoolIndex SourcePoolIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
return SoundManager.SourcePoolIndex.Default;
|
||||
}
|
||||
}
|
||||
|
||||
private uint alBuffer;
|
||||
public uint ALBuffer
|
||||
{
|
||||
get { return !Stream ? alBuffer : 0; }
|
||||
}
|
||||
|
||||
private uint alMuffledBuffer;
|
||||
public uint ALMuffledBuffer
|
||||
{
|
||||
get { return !Stream ? alMuffledBuffer : 0; }
|
||||
}
|
||||
|
||||
public int ALFormat
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
public int SampleRate
|
||||
{
|
||||
get;
|
||||
protected set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How many instances of the same sound clip can be playing at the same time
|
||||
/// </summary>
|
||||
public int MaxSimultaneousInstances = 5;
|
||||
|
||||
public float BaseGain;
|
||||
public float BaseNear;
|
||||
public float BaseFar;
|
||||
|
||||
public Sound(SoundManager owner, string filename, bool stream, bool streamsReliably, XElement xElement=null)
|
||||
{
|
||||
Owner = owner;
|
||||
Filename = Path.GetFullPath(filename.CleanUpPath()).CleanUpPath();
|
||||
Stream = stream;
|
||||
StreamsReliably = streamsReliably;
|
||||
XElement = xElement;
|
||||
|
||||
BaseGain = 1.0f;
|
||||
BaseNear = 100.0f;
|
||||
BaseFar = 200.0f;
|
||||
|
||||
if (!stream)
|
||||
{
|
||||
Al.GenBuffer(out alBuffer);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!Al.IsBuffer(alBuffer))
|
||||
{
|
||||
throw new Exception("Generated OpenAL buffer is invalid!");
|
||||
}
|
||||
|
||||
Al.GenBuffer(out alMuffledBuffer);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
if (!Al.IsBuffer(alMuffledBuffer))
|
||||
{
|
||||
throw new Exception("Generated OpenAL buffer is invalid!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alBuffer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return GetType().ToString() + " (" + Filename + ")";
|
||||
}
|
||||
|
||||
public virtual bool IsPlaying()
|
||||
{
|
||||
return Owner.IsPlaying(this);
|
||||
}
|
||||
|
||||
public virtual SoundChannel Play(float gain, float range, Vector2 position, bool muffle = false)
|
||||
{
|
||||
return new SoundChannel(this, gain, new Vector3(position.X, position.Y, 0.0f), range * 0.4f, range, "default", muffle);
|
||||
}
|
||||
|
||||
public virtual SoundChannel Play(Vector3? position, float gain, bool muffle = false)
|
||||
{
|
||||
return new SoundChannel(this, gain, position, BaseNear, BaseFar, "default", muffle);
|
||||
}
|
||||
|
||||
public virtual SoundChannel Play(float gain)
|
||||
{
|
||||
return Play(null, gain);
|
||||
}
|
||||
|
||||
public virtual SoundChannel Play()
|
||||
{
|
||||
return Play(BaseGain);
|
||||
}
|
||||
|
||||
public virtual SoundChannel Play(float? gain, string category)
|
||||
{
|
||||
if (Owner.CountPlayingInstances(this) >= MaxSimultaneousInstances) { return null; }
|
||||
return new SoundChannel(this, gain ?? BaseGain, null, BaseNear, BaseFar, category);
|
||||
}
|
||||
|
||||
static protected void CastBuffer(float[] inBuffer, short[] outBuffer, int length)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
outBuffer[i] = FloatToShort(inBuffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static protected short FloatToShort(float fVal)
|
||||
{
|
||||
int temp = (int)(32767 * fVal);
|
||||
if (temp > short.MaxValue) temp = short.MaxValue;
|
||||
else if (temp < short.MinValue) temp = short.MinValue;
|
||||
return (short)temp;
|
||||
}
|
||||
static protected float ShortToFloat(short shortVal)
|
||||
{
|
||||
return shortVal / 32767f;
|
||||
}
|
||||
|
||||
public abstract int FillStreamBuffer(int samplePos, short[] buffer);
|
||||
|
||||
public abstract float GetAmplitudeAtPlaybackPos(int playbackPos);
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (disposed) { return; }
|
||||
|
||||
Owner.KillChannels(this);
|
||||
if (alBuffer != 0)
|
||||
{
|
||||
if (!Al.IsBuffer(alBuffer))
|
||||
{
|
||||
throw new Exception("Buffer to delete is invalid!");
|
||||
}
|
||||
|
||||
Al.DeleteBuffer(alBuffer); alBuffer = 0;
|
||||
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to delete OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
if (alMuffledBuffer != 0)
|
||||
{
|
||||
if (!Al.IsBuffer(alMuffledBuffer))
|
||||
{
|
||||
throw new Exception("Buffer to delete is invalid!");
|
||||
}
|
||||
|
||||
Al.DeleteBuffer(alMuffledBuffer); alMuffledBuffer = 0;
|
||||
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to delete OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
|
||||
Owner.RemoveSound(this);
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user