(965c31410a) Unstable v0.10.4.0
This commit is contained in:
@@ -16,67 +16,7 @@ namespace Barotrauma.Sounds
|
||||
private static List<float> playbackAmplitude;
|
||||
private const int AMPLITUDE_SAMPLE_COUNT = 4410; //100ms in a 44100hz file
|
||||
|
||||
public OggSound(SoundManager owner, string filename, bool stream, XElement xElement) : base(owner, filename, stream, true, xElement)
|
||||
{
|
||||
filename = filename.CleanUpPath();
|
||||
if (!ToolBox.IsProperFilenameCase(filename))
|
||||
{
|
||||
DebugConsole.ThrowError("Sound file \"" + filename + "\" has incorrect case!");
|
||||
}
|
||||
|
||||
reader = new VorbisReader(filename);
|
||||
|
||||
ALFormat = reader.Channels == 1 ? Al.FormatMono16 : Al.FormatStereo16;
|
||||
SampleRate = reader.SampleRate;
|
||||
|
||||
if (!stream)
|
||||
{
|
||||
int bufferSize = (int)reader.TotalSamples * reader.Channels;
|
||||
|
||||
float[] floatBuffer = new float[bufferSize];
|
||||
short[] shortBuffer = new short[bufferSize];
|
||||
|
||||
int readSamples = reader.ReadSamples(floatBuffer, 0, bufferSize);
|
||||
|
||||
playbackAmplitude = new List<float>();
|
||||
for (int i=0;i<bufferSize;i+=reader.Channels*AMPLITUDE_SAMPLE_COUNT)
|
||||
{
|
||||
float maxAmplitude = 0.0f;
|
||||
for (int j=i;j<i+reader.Channels*AMPLITUDE_SAMPLE_COUNT;j++)
|
||||
{
|
||||
if (j >= bufferSize) { break; }
|
||||
maxAmplitude = Math.Max(maxAmplitude, Math.Abs(floatBuffer[j]));
|
||||
}
|
||||
playbackAmplitude.Add(maxAmplitude);
|
||||
}
|
||||
|
||||
CastBuffer(floatBuffer, shortBuffer, readSamples);
|
||||
|
||||
Al.BufferData(ALBuffer, ALFormat, shortBuffer,
|
||||
readSamples * sizeof(short), SampleRate);
|
||||
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set buffer data for non-streamed audio! "+Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
MuffleBuffer(floatBuffer, SampleRate, reader.Channels);
|
||||
|
||||
CastBuffer(floatBuffer, shortBuffer, readSamples);
|
||||
|
||||
Al.BufferData(ALMuffledBuffer, ALFormat, shortBuffer,
|
||||
readSamples * sizeof(short), SampleRate);
|
||||
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set buffer data for non-streamed audio! " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
public OggSound(SoundManager owner, string filename, bool stream, XElement xElement) : base(owner, filename, stream, true, xElement) { }
|
||||
|
||||
public override float GetAmplitudeAtPlaybackPos(int playbackPos)
|
||||
{
|
||||
@@ -114,6 +54,64 @@ namespace Barotrauma.Sounds
|
||||
filter.Process(buffer);
|
||||
}
|
||||
|
||||
public override void InitializeALBuffers()
|
||||
{
|
||||
base.InitializeALBuffers();
|
||||
|
||||
reader ??= new VorbisReader(Filename);
|
||||
|
||||
ALFormat = reader.Channels == 1 ? Al.FormatMono16 : Al.FormatStereo16;
|
||||
SampleRate = reader.SampleRate;
|
||||
|
||||
if (!Stream)
|
||||
{
|
||||
int bufferSize = (int)reader.TotalSamples * reader.Channels;
|
||||
|
||||
float[] floatBuffer = new float[bufferSize];
|
||||
short[] shortBuffer = new short[bufferSize];
|
||||
|
||||
int readSamples = reader.ReadSamples(floatBuffer, 0, bufferSize);
|
||||
|
||||
playbackAmplitude = new List<float>();
|
||||
for (int i = 0; i < bufferSize; i += reader.Channels * AMPLITUDE_SAMPLE_COUNT)
|
||||
{
|
||||
float maxAmplitude = 0.0f;
|
||||
for (int j = i; j < i + reader.Channels * AMPLITUDE_SAMPLE_COUNT; j++)
|
||||
{
|
||||
if (j >= bufferSize) { break; }
|
||||
maxAmplitude = Math.Max(maxAmplitude, Math.Abs(floatBuffer[j]));
|
||||
}
|
||||
playbackAmplitude.Add(maxAmplitude);
|
||||
}
|
||||
|
||||
CastBuffer(floatBuffer, shortBuffer, readSamples);
|
||||
|
||||
Al.BufferData(ALBuffer, ALFormat, shortBuffer,
|
||||
readSamples * sizeof(short), SampleRate);
|
||||
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set buffer data for non-streamed audio! " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
MuffleBuffer(floatBuffer, SampleRate, reader.Channels);
|
||||
|
||||
CastBuffer(floatBuffer, shortBuffer, readSamples);
|
||||
|
||||
Al.BufferData(ALMuffledBuffer, ALFormat, shortBuffer,
|
||||
readSamples * sizeof(short), SampleRate);
|
||||
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to set buffer data for non-streamed audio! " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
reader.Dispose(); reader = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (Stream)
|
||||
|
||||
@@ -43,11 +43,42 @@ namespace OpenAL
|
||||
#elif LINUX
|
||||
public const string OpenAlDll = "libopenal.so.1";
|
||||
#elif WINDOWS
|
||||
#if X86
|
||||
public const string OpenAlDll = "soft_oal_x86.dll";
|
||||
#elif X64
|
||||
public const string OpenAlDll = "soft_oal_x64.dll";
|
||||
#endif
|
||||
|
||||
public delegate void ErrorReasonCallback(string str);
|
||||
|
||||
#if WINDOWS
|
||||
[DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcSetErrorReasonCallback")]
|
||||
private static extern void SetErrorReasonCallback(IntPtr callback);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
private delegate void ErrorReasonCallbackInternal(IntPtr cstr);
|
||||
|
||||
private static ErrorReasonCallbackInternal CurrentErrorReasonCallback;
|
||||
private static IntPtr CurrentErrorReasonCallbackPtr;
|
||||
|
||||
public static void SetErrorReasonCallback(ErrorReasonCallback callback)
|
||||
{
|
||||
CurrentErrorReasonCallback = (IntPtr cstr) =>
|
||||
{
|
||||
int strLen = 0;
|
||||
while (Marshal.ReadByte(cstr, strLen) != '\0') { strLen++; }
|
||||
byte[] bytes = new byte[strLen];
|
||||
Marshal.Copy(cstr, bytes, 0, strLen);
|
||||
string csStr = Encoding.UTF8.GetString(bytes);
|
||||
|
||||
callback?.Invoke(csStr);
|
||||
};
|
||||
|
||||
CurrentErrorReasonCallbackPtr = Marshal.GetFunctionPointerForDelegate(CurrentErrorReasonCallback);
|
||||
SetErrorReasonCallback(CurrentErrorReasonCallbackPtr);
|
||||
}
|
||||
#else
|
||||
public static void SetErrorReasonCallback(ErrorReasonCallback callback)
|
||||
{
|
||||
//FIXME: not implemented on macOS and Linux
|
||||
}
|
||||
#endif
|
||||
|
||||
#region Enum
|
||||
@@ -77,10 +108,11 @@ namespace OpenAL
|
||||
public const int CaptureDeviceSpecifier = 0x310;
|
||||
public const int CaptureDefaultDeviceSpecifier = 0x311;
|
||||
public const int EnumCaptureSamples = 0x312;
|
||||
public const int EnumConnected = 0x313;
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Context Management Functions
|
||||
#region Context Management Functions
|
||||
|
||||
[DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCreateContext")]
|
||||
private static extern IntPtr _CreateContext(IntPtr device, IntPtr attrlist);
|
||||
@@ -112,7 +144,22 @@ namespace OpenAL
|
||||
public static extern IntPtr GetContextsDevice(IntPtr context);
|
||||
|
||||
[DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcOpenDevice")]
|
||||
public static extern IntPtr OpenDevice(string deviceName);
|
||||
private static extern IntPtr OpenDevice(IntPtr deviceName);
|
||||
|
||||
public static IntPtr OpenDevice(string deviceName)
|
||||
{
|
||||
if (deviceName == null)
|
||||
{
|
||||
return OpenDevice(IntPtr.Zero);
|
||||
}
|
||||
|
||||
byte[] devicenameBytes = Encoding.UTF8.GetBytes(deviceName + "\0");
|
||||
GCHandle devicenameHandle = GCHandle.Alloc(devicenameBytes, GCHandleType.Pinned);
|
||||
IntPtr retVal = OpenDevice(devicenameHandle.AddrOfPinnedObject());
|
||||
devicenameHandle.Free();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
[DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCloseDevice")]
|
||||
public static extern bool CloseDevice(IntPtr device);
|
||||
@@ -150,9 +197,9 @@ namespace OpenAL
|
||||
[DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetEnumValue")]
|
||||
public static extern int GetEnumValue(IntPtr device, string enumname);
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Query Functions
|
||||
#region Query Functions
|
||||
|
||||
[DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcGetString")]
|
||||
private static extern IntPtr _GetString(IntPtr device, int param);
|
||||
@@ -171,6 +218,7 @@ namespace OpenAL
|
||||
{
|
||||
List<string> retVal = new List<string>();
|
||||
IntPtr strPtr = _GetString(device, param);
|
||||
if (strPtr == IntPtr.Zero) { return retVal; }
|
||||
int strStart = 0;
|
||||
int strEnd = 0;
|
||||
byte currChar = Marshal.ReadByte(strPtr, strEnd);
|
||||
@@ -208,9 +256,9 @@ namespace OpenAL
|
||||
data = dataArr[0];
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Capture Functions
|
||||
#region Capture Functions
|
||||
|
||||
[DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCaptureOpenDevice")]
|
||||
private static extern IntPtr CaptureOpenDevice(IntPtr devicename, uint frequency, int format, int buffersize);
|
||||
@@ -236,6 +284,6 @@ namespace OpenAL
|
||||
[DllImport(OpenAlDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "alcCaptureSamples")]
|
||||
public static extern void CaptureSamples(IntPtr device, IntPtr buffer, int samples);
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,37 +98,8 @@ namespace Barotrauma.Sounds
|
||||
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;
|
||||
}
|
||||
InitializeALBuffers();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@@ -191,10 +162,42 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public abstract float GetAmplitudeAtPlaybackPos(int playbackPos);
|
||||
|
||||
public virtual void Dispose()
|
||||
public virtual void InitializeALBuffers()
|
||||
{
|
||||
if (disposed) { return; }
|
||||
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 virtual void DeleteALBuffers()
|
||||
{
|
||||
Owner.KillChannels(this);
|
||||
if (alBuffer != 0)
|
||||
{
|
||||
@@ -202,7 +205,7 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
throw new Exception("Buffer to delete is invalid!");
|
||||
}
|
||||
|
||||
|
||||
Al.DeleteBuffer(alBuffer); alBuffer = 0;
|
||||
|
||||
int alError = Al.GetError();
|
||||
@@ -226,6 +229,13 @@ namespace Barotrauma.Sounds
|
||||
throw new Exception("Failed to delete OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (disposed) { return; }
|
||||
|
||||
DeleteALBuffers();
|
||||
|
||||
Owner.RemoveSound(this);
|
||||
disposed = true;
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (ALSources == null) { return; }
|
||||
for (int i = 0; i < ALSources.Length; i++)
|
||||
{
|
||||
Al.DeleteSource(ALSources[i]);
|
||||
|
||||
@@ -19,8 +19,8 @@ namespace Barotrauma.Sounds
|
||||
private set;
|
||||
}
|
||||
|
||||
private readonly IntPtr alcDevice;
|
||||
private readonly IntPtr alcContext;
|
||||
private IntPtr alcDevice;
|
||||
private IntPtr alcContext;
|
||||
|
||||
public enum SourcePoolIndex
|
||||
{
|
||||
@@ -33,6 +33,10 @@ namespace Barotrauma.Sounds
|
||||
private readonly SoundChannel[][] playingChannels = new SoundChannel[2][];
|
||||
private readonly object threadDeathMutex = new object();
|
||||
|
||||
public bool CanDetectDisconnect { get; private set; }
|
||||
|
||||
public bool Disconnected { get; private set; }
|
||||
|
||||
private Thread streamingThread;
|
||||
|
||||
private Vector3 listenerPosition;
|
||||
@@ -197,18 +201,55 @@ namespace Barotrauma.Sounds
|
||||
streamingThread = null;
|
||||
categoryModifiers = null;
|
||||
|
||||
int alcError = Alc.NoError;
|
||||
sourcePools = new SoundSourcePool[2];
|
||||
playingChannels[(int)SourcePoolIndex.Default] = new SoundChannel[SOURCE_COUNT];
|
||||
playingChannels[(int)SourcePoolIndex.Voice] = new SoundChannel[16];
|
||||
|
||||
string deviceName = GameMain.Config.AudioOutputDevice;
|
||||
|
||||
if (string.IsNullOrEmpty(deviceName))
|
||||
{
|
||||
deviceName = Alc.GetString((IntPtr)null, Alc.DefaultDeviceSpecifier);
|
||||
}
|
||||
|
||||
#if (!OSX)
|
||||
var audioDeviceNames = Alc.GetStringList((IntPtr)null, Alc.AllDevicesSpecifier);
|
||||
if (audioDeviceNames.Any() && !audioDeviceNames.Any(n => n.Equals(deviceName, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
deviceName = audioDeviceNames[0];
|
||||
}
|
||||
#endif
|
||||
GameMain.Config.AudioOutputDevice = deviceName;
|
||||
|
||||
InitializeAlcDevice(deviceName);
|
||||
|
||||
ListenerPosition = Vector3.Zero;
|
||||
ListenerTargetVector = new Vector3(0.0f, 0.0f, 1.0f);
|
||||
ListenerUpVector = new Vector3(0.0f, -1.0f, 0.0f);
|
||||
|
||||
CompressionDynamicRangeGain = 1.0f;
|
||||
}
|
||||
|
||||
public bool InitializeAlcDevice(string deviceName)
|
||||
{
|
||||
ReleaseResources(true);
|
||||
|
||||
string deviceName = Alc.GetString(IntPtr.Zero, Alc.DefaultDeviceSpecifier);
|
||||
DebugConsole.NewMessage($"Attempting to open ALC device \"{deviceName}\"");
|
||||
|
||||
alcDevice = IntPtr.Zero;
|
||||
int alcError = Al.NoError;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
alcDevice = Alc.OpenDevice(deviceName);
|
||||
if (alcDevice == IntPtr.Zero)
|
||||
{
|
||||
DebugConsole.NewMessage($"ALC device initialization attempt #{i + 1} failed: device is null");
|
||||
alcError = Alc.GetError(IntPtr.Zero);
|
||||
DebugConsole.NewMessage($"ALC device initialization attempt #{i + 1} failed: device is null (error code {Alc.GetErrorString(alcError)})");
|
||||
if (!string.IsNullOrEmpty(deviceName))
|
||||
{
|
||||
deviceName = null;
|
||||
DebugConsole.NewMessage($"Switching to default device...");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -223,29 +264,44 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
alcDevice = IntPtr.Zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alcDevice == IntPtr.Zero)
|
||||
{
|
||||
DebugConsole.ThrowError("ALC device creation failed too many times!");
|
||||
Disabled = true;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
CanDetectDisconnect = Alc.IsExtensionPresent(alcDevice, "ALC_EXT_disconnect");
|
||||
alcError = Alc.GetError(alcDevice);
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
DebugConsole.ThrowError("Error determining if disconnect can be detected: " + alcError.ToString() + ". Disabling audio playback...");
|
||||
Disabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Disconnected = false;
|
||||
|
||||
int[] alcContextAttrs = new int[] { };
|
||||
alcContext = Alc.CreateContext(alcDevice, alcContextAttrs);
|
||||
if (alcContext == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to create an ALC context! (error code: " + Alc.GetError(alcDevice).ToString() + "). Disabling audio playback...");
|
||||
Disabled = true;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Alc.MakeContextCurrent(alcContext))
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to assign the current ALC context! (error code: " + Alc.GetError(alcDevice).ToString() + "). Disabling audio playback...");
|
||||
Disabled = true;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
alcError = Alc.GetError(alcDevice);
|
||||
@@ -253,31 +309,27 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
DebugConsole.ThrowError("Error after assigning ALC context: " + Alc.GetErrorString(alcError) + ". Disabling audio playback...");
|
||||
Disabled = true;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
sourcePools = new SoundSourcePool[2];
|
||||
sourcePools[(int)SourcePoolIndex.Default] = new SoundSourcePool(SOURCE_COUNT);
|
||||
playingChannels[(int)SourcePoolIndex.Default] = new SoundChannel[SOURCE_COUNT];
|
||||
|
||||
sourcePools[(int)SourcePoolIndex.Voice] = new SoundSourcePool(16);
|
||||
playingChannels[(int)SourcePoolIndex.Voice] = new SoundChannel[16];
|
||||
|
||||
Al.DistanceModel(Al.LinearDistanceClamped);
|
||||
|
||||
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
DebugConsole.ThrowError("Error setting distance model: " + Al.GetErrorString(alError) + ". Disabling audio playback...");
|
||||
Disabled = true;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
ListenerPosition = Vector3.Zero;
|
||||
ListenerTargetVector = new Vector3(0.0f, 0.0f, 1.0f);
|
||||
ListenerUpVector = new Vector3(0.0f, -1.0f, 0.0f);
|
||||
sourcePools[(int)SourcePoolIndex.Default] = new SoundSourcePool(SOURCE_COUNT);
|
||||
sourcePools[(int)SourcePoolIndex.Voice] = new SoundSourcePool(16);
|
||||
|
||||
CompressionDynamicRangeGain = 1.0f;
|
||||
ReloadSounds();
|
||||
|
||||
Disabled = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Sound LoadSound(string filename, bool stream = false)
|
||||
@@ -551,7 +603,25 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
if (Disconnected || Disabled) { return; }
|
||||
|
||||
if (CanDetectDisconnect)
|
||||
{
|
||||
Alc.GetInteger(alcDevice, Alc.EnumConnected, out int isConnected);
|
||||
int alcError = Alc.GetError(alcDevice);
|
||||
if (alcError != Alc.NoError)
|
||||
{
|
||||
throw new Exception("Failed to determine if device is connected: " + alcError.ToString());
|
||||
}
|
||||
|
||||
if (isConnected == 0)
|
||||
{
|
||||
DebugConsole.ThrowError("Playback device has been disconnected. You can select another available device in the settings.");
|
||||
GameMain.Config.AudioOutputDevice = "<disconnected>";
|
||||
Disconnected = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.Client != null && GameMain.Config.VoipAttenuationEnabled)
|
||||
{
|
||||
@@ -681,10 +751,16 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
private void ReloadSounds()
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
for (int i = loadedSounds.Count - 1; i >= 0; i--)
|
||||
{
|
||||
loadedSounds[i].InitializeALBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReleaseResources(bool keepSounds)
|
||||
{
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
{
|
||||
lock (playingChannels[i])
|
||||
@@ -699,10 +775,24 @@ namespace Barotrauma.Sounds
|
||||
streamingThread?.Join();
|
||||
for (int i = loadedSounds.Count - 1; i >= 0; i--)
|
||||
{
|
||||
loadedSounds[i].Dispose();
|
||||
if (keepSounds)
|
||||
{
|
||||
loadedSounds[i].DeleteALBuffers();
|
||||
}
|
||||
else
|
||||
{
|
||||
loadedSounds[i].Dispose();
|
||||
}
|
||||
}
|
||||
sourcePools[(int)SourcePoolIndex.Default]?.Dispose();
|
||||
sourcePools[(int)SourcePoolIndex.Voice]?.Dispose();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
|
||||
ReleaseResources(false);
|
||||
|
||||
if (!Alc.MakeContextCurrent(IntPtr.Zero))
|
||||
{
|
||||
|
||||
@@ -809,7 +809,8 @@ namespace Barotrauma
|
||||
Screen.Selected == GameMain.ParticleEditorScreen ||
|
||||
Screen.Selected == GameMain.SpriteEditorScreen ||
|
||||
Screen.Selected == GameMain.SubEditorScreen ||
|
||||
(Screen.Selected == GameMain.GameScreen && GameMain.GameSession?.GameMode is SubTestMode))
|
||||
Screen.Selected == GameMain.EventEditorScreen ||
|
||||
(Screen.Selected == GameMain.GameScreen && GameMain.GameSession?.GameMode is TestGameMode))
|
||||
{
|
||||
return "editor";
|
||||
}
|
||||
@@ -882,7 +883,7 @@ namespace Barotrauma
|
||||
|
||||
if (GameMain.GameSession != null)
|
||||
{
|
||||
if (Submarine.Loaded != null && Level.Loaded != null && Submarine.MainSub.AtEndPosition)
|
||||
if (Submarine.Loaded != null && Level.Loaded != null && Submarine.MainSub != null && Submarine.MainSub.AtEndPosition)
|
||||
{
|
||||
return "levelend";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user