(a00338777) v0.9.2.1
This commit is contained in:
@@ -12,6 +12,9 @@ namespace Barotrauma.Sounds
|
||||
//key = sample rate, value = filter
|
||||
private static Dictionary<int, BiQuad> muffleFilters = new Dictionary<int, BiQuad>();
|
||||
|
||||
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) : base(owner, filename, stream, true)
|
||||
{
|
||||
if (!ToolBox.IsProperFilenameCase(filename))
|
||||
@@ -32,6 +35,18 @@ namespace Barotrauma.Sounds
|
||||
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);
|
||||
|
||||
@@ -61,6 +76,15 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
|
||||
public override float GetAmplitudeAtPlaybackPos(int playbackPos)
|
||||
{
|
||||
if (playbackAmplitude == null || playbackAmplitude.Count == 0) { return 0.0f; }
|
||||
int index = playbackPos / AMPLITUDE_SAMPLE_COUNT;
|
||||
if (index < 0) { return 0.0f; }
|
||||
if (index >= playbackAmplitude.Count) { index = playbackAmplitude.Count - 1; }
|
||||
return playbackAmplitude[index];
|
||||
}
|
||||
|
||||
public override int FillStreamBuffer(int samplePos, short[] buffer)
|
||||
{
|
||||
if (!Stream) throw new Exception("Called FillStreamBuffer on a non-streamed sound!");
|
||||
|
||||
@@ -179,6 +179,8 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public abstract int FillStreamBuffer(int samplePos, short[] buffer);
|
||||
|
||||
public abstract float GetAmplitudeAtPlaybackPos(int playbackPos);
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
if (disposed) { return; }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using OpenAL;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Barotrauma.Sounds
|
||||
{
|
||||
@@ -79,7 +80,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public class SoundChannel : IDisposable
|
||||
{
|
||||
private const int STREAM_BUFFER_SIZE = 65536;
|
||||
private const int STREAM_BUFFER_SIZE = 8820;
|
||||
private short[] streamShortBuffer;
|
||||
|
||||
private Vector3? position;
|
||||
@@ -282,6 +283,35 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
|
||||
private float streamAmplitude;
|
||||
public float CurrentAmplitude
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsPlaying) { return 0.0f; }
|
||||
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
if (!IsStream)
|
||||
{
|
||||
int playbackPos; Al.GetSourcei(alSource, Al.SampleOffset, out playbackPos);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to get source's playback position: " + Al.GetErrorString(alError));
|
||||
}
|
||||
return Sound.GetAmplitudeAtPlaybackPos(playbackPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
float retVal = -1.0f;
|
||||
Monitor.Enter(mutex);
|
||||
retVal = streamAmplitude;
|
||||
Monitor.Exit(mutex);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string category;
|
||||
public string Category
|
||||
{
|
||||
@@ -311,10 +341,12 @@ namespace Barotrauma.Sounds
|
||||
private set;
|
||||
}
|
||||
private int streamSeekPos;
|
||||
private bool startedPlaying;
|
||||
private int buffersToRequeue;
|
||||
private bool reachedEndSample;
|
||||
private int queueStartIndex;
|
||||
private readonly uint[] streamBuffers;
|
||||
private readonly List<uint> emptyBuffers;
|
||||
private uint[] unqueuedBuffers;
|
||||
private float[] streamBufferAmplitudes;
|
||||
|
||||
private object mutex;
|
||||
|
||||
@@ -346,12 +378,17 @@ namespace Barotrauma.Sounds
|
||||
FilledByNetwork = sound is VoipSound;
|
||||
decayTimer = 0;
|
||||
streamSeekPos = 0; reachedEndSample = false;
|
||||
startedPlaying = true;
|
||||
|
||||
mutex = new object();
|
||||
buffersToRequeue = 4;
|
||||
muffled = muffle;
|
||||
|
||||
lock (mutex)
|
||||
if (IsStream)
|
||||
{
|
||||
mutex = new object();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (mutex != null) { Monitor.Enter(mutex); }
|
||||
if (sound.Owner.CountPlayingInstances(sound) < sound.MaxSimultaneousInstances)
|
||||
{
|
||||
ALSourceIndex = sound.Owner.AssignFreeSourceToChannel(this);
|
||||
@@ -390,7 +427,8 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
else
|
||||
{
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)sound.ALBuffer);
|
||||
uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffle ? sound.ALMuffledBuffer : sound.ALBuffer;
|
||||
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
|
||||
int alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
@@ -407,7 +445,8 @@ namespace Barotrauma.Sounds
|
||||
streamShortBuffer = new short[STREAM_BUFFER_SIZE];
|
||||
|
||||
streamBuffers = new uint[4];
|
||||
emptyBuffers = new List<uint>();
|
||||
unqueuedBuffers = new uint[4];
|
||||
streamBufferAmplitudes = new float[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Al.GenBuffer(out streamBuffers[i]);
|
||||
@@ -423,18 +462,27 @@ namespace Barotrauma.Sounds
|
||||
throw new Exception("Generated streamBuffer[" + i.ToString() + "] is invalid!");
|
||||
}
|
||||
}
|
||||
|
||||
Sound.Owner.InitStreamThread();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.Position = position;
|
||||
this.Gain = gain;
|
||||
this.Looping = false;
|
||||
this.Near = near;
|
||||
this.Far = far;
|
||||
this.Category = category;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (mutex != null) { Monitor.Exit(mutex); }
|
||||
}
|
||||
|
||||
Sound.Owner.Update();
|
||||
}
|
||||
|
||||
public bool FadingOutAndDisposing;
|
||||
@@ -445,8 +493,9 @@ namespace Barotrauma.Sounds
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (mutex)
|
||||
try
|
||||
{
|
||||
if (mutex != null) { Monitor.Enter(mutex); }
|
||||
if (ALSourceIndex >= 0)
|
||||
{
|
||||
Al.SourceStop(Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
|
||||
@@ -467,19 +516,17 @@ namespace Barotrauma.Sounds
|
||||
throw new Exception("Failed to stop streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
int buffersToUnqueue = 0;
|
||||
uint[] unqueuedBuffers = null;
|
||||
|
||||
buffersToUnqueue = 0;
|
||||
Al.GetSourcei(alSource, Al.BuffersProcessed, out buffersToUnqueue);
|
||||
int buffersToRequeue = 0;
|
||||
|
||||
buffersToRequeue = 0;
|
||||
Al.GetSourcei(alSource, Al.BuffersProcessed, out buffersToRequeue);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to determine processed buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
unqueuedBuffers = new uint[buffersToUnqueue];
|
||||
Al.SourceUnqueueBuffers(alSource, buffersToUnqueue, unqueuedBuffers);
|
||||
|
||||
Al.SourceUnqueueBuffers(alSource, buffersToRequeue, unqueuedBuffers);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
@@ -518,14 +565,19 @@ namespace Barotrauma.Sounds
|
||||
ALSourceIndex = -1;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (mutex != null) { Monitor.Exit(mutex); }
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateStream()
|
||||
{
|
||||
if (!IsStream) throw new Exception("Called UpdateStream on a non-streamed sound channel!");
|
||||
|
||||
lock (mutex)
|
||||
try
|
||||
{
|
||||
Monitor.Enter(mutex);
|
||||
if (!reachedEndSample)
|
||||
{
|
||||
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
|
||||
@@ -538,48 +590,38 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
throw new Exception("Failed to determine playing state from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
int buffersToUnqueue = 0;
|
||||
uint[] unqueuedBuffers = null;
|
||||
if (!startedPlaying)
|
||||
{
|
||||
buffersToUnqueue = 0;
|
||||
Al.GetSourcei(alSource, Al.BuffersProcessed, out buffersToUnqueue);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to determine processed buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
unqueuedBuffers = new uint[buffersToUnqueue+emptyBuffers.Count];
|
||||
Al.SourceUnqueueBuffers(alSource, buffersToUnqueue, unqueuedBuffers);
|
||||
for (int i = 0; i < emptyBuffers.Count; i++)
|
||||
{
|
||||
unqueuedBuffers[buffersToUnqueue + i] = emptyBuffers[i];
|
||||
}
|
||||
buffersToUnqueue += emptyBuffers.Count;
|
||||
emptyBuffers.Clear();
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to unqueue buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
else
|
||||
int unqueuedBufferCount;
|
||||
Al.GetSourcei(alSource, Al.BuffersProcessed, out unqueuedBufferCount);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
startedPlaying = false;
|
||||
buffersToUnqueue = 4;
|
||||
unqueuedBuffers = new uint[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
unqueuedBuffers[i] = streamBuffers[i];
|
||||
}
|
||||
throw new Exception("Failed to determine processed buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
Al.SourceUnqueueBuffers(alSource, unqueuedBufferCount, unqueuedBuffers);
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to unqueue buffers from streamed source: " + Al.GetErrorString(alError));
|
||||
}
|
||||
|
||||
for (int i = 0; i < buffersToUnqueue; i++)
|
||||
buffersToRequeue += unqueuedBufferCount;
|
||||
|
||||
int iterCount = buffersToRequeue;
|
||||
for (int k = 0; k < iterCount; k++)
|
||||
{
|
||||
int index = queueStartIndex;
|
||||
short[] buffer = streamShortBuffer;
|
||||
int readSamples = Sound.FillStreamBuffer(streamSeekPos, buffer);
|
||||
float readAmplitude = 0.0f;
|
||||
|
||||
for (int i=0;i<Math.Min(readSamples, buffer.Length);i++)
|
||||
{
|
||||
float sampleF = ((float)buffer[i]) / ((float)short.MaxValue);
|
||||
readAmplitude = Math.Max(readAmplitude, Math.Abs(sampleF));
|
||||
}
|
||||
|
||||
if (FilledByNetwork)
|
||||
{
|
||||
if (Sound is VoipSound voipSound)
|
||||
@@ -589,6 +631,7 @@ namespace Barotrauma.Sounds
|
||||
|
||||
if (readSamples <= 0)
|
||||
{
|
||||
streamAmplitude *= 0.5f;
|
||||
decayTimer++;
|
||||
if (decayTimer > 120) //TODO: replace magic number
|
||||
{
|
||||
@@ -618,38 +661,54 @@ namespace Barotrauma.Sounds
|
||||
|
||||
if (readSamples > 0)
|
||||
{
|
||||
Al.BufferData<short>(unqueuedBuffers[i], Sound.ALFormat, buffer, readSamples, Sound.SampleRate);
|
||||
streamBufferAmplitudes[index] = readAmplitude;
|
||||
|
||||
Al.BufferData<short>(streamBuffers[index], Sound.ALFormat, buffer, readSamples, Sound.SampleRate);
|
||||
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to assign data to stream buffer: " +
|
||||
Al.GetErrorString(alError) + ": " + unqueuedBuffers[i].ToString() + "/" + unqueuedBuffers.Length + ", readSamples: " + readSamples);
|
||||
Al.GetErrorString(alError) + ": " + streamBuffers[index].ToString() + "/" + streamBuffers.Length + ", readSamples: " + readSamples);
|
||||
}
|
||||
|
||||
Al.SourceQueueBuffer(alSource, unqueuedBuffers[i]);
|
||||
Al.SourceQueueBuffer(alSource, streamBuffers[index]);
|
||||
queueStartIndex = (queueStartIndex + 1) % 4;
|
||||
|
||||
alError = Al.GetError();
|
||||
if (alError != Al.NoError)
|
||||
{
|
||||
throw new Exception("Failed to queue buffer[" + i.ToString() + "] to stream: " + Al.GetErrorString(alError));
|
||||
throw new Exception("Failed to queue streamBuffer[" + index.ToString() + "] to stream: " + Al.GetErrorString(alError));
|
||||
}
|
||||
}
|
||||
else if (readSamples < 0)
|
||||
{
|
||||
reachedEndSample = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
emptyBuffers.Add((uint)unqueuedBuffers[i]);
|
||||
if (readSamples < 0)
|
||||
{
|
||||
reachedEndSample = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
buffersToRequeue--;
|
||||
}
|
||||
|
||||
|
||||
streamAmplitude = streamBufferAmplitudes[queueStartIndex];
|
||||
|
||||
Al.GetSourcei(alSource, Al.SourceState, out state);
|
||||
if (state != Al.Playing)
|
||||
{
|
||||
Al.SourcePlay(alSource);
|
||||
}
|
||||
}
|
||||
|
||||
if (reachedEndSample)
|
||||
{
|
||||
streamAmplitude = 0.0f;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,47 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public float PlaybackAmplitude
|
||||
{
|
||||
get
|
||||
{
|
||||
float aggregateAmplitude = 0.0f;
|
||||
//NOTE: this is obviously not entirely accurate;
|
||||
//It assumes a linear falloff model, and assumes that audio
|
||||
//is simply added together to produce the final result.
|
||||
//Adjustments may be needed under certain scenarios.
|
||||
for (int i=0;i<2;i++)
|
||||
{
|
||||
foreach (SoundChannel soundChannel in playingChannels[i].Where(ch => ch != null))
|
||||
{
|
||||
float amplitude = soundChannel.CurrentAmplitude;
|
||||
amplitude *= soundChannel.Gain;
|
||||
float dist = Vector3.Distance(ListenerPosition, soundChannel.Position ?? ListenerPosition);
|
||||
if (dist > soundChannel.Near)
|
||||
{
|
||||
amplitude *= 1.0f - Math.Min(1.0f, (dist - soundChannel.Near) / (soundChannel.Far - soundChannel.Near));
|
||||
}
|
||||
aggregateAmplitude += amplitude;
|
||||
}
|
||||
}
|
||||
return aggregateAmplitude;
|
||||
}
|
||||
}
|
||||
|
||||
public float CompressionDynamicRangeGain { get; private set; }
|
||||
|
||||
private float voipAttenuatedGain;
|
||||
private double lastAttenuationTime;
|
||||
public float VoipAttenuatedGain
|
||||
{
|
||||
get { return voipAttenuatedGain; }
|
||||
set
|
||||
{
|
||||
lastAttenuationTime = Timing.TotalTime;
|
||||
voipAttenuatedGain = value;
|
||||
}
|
||||
}
|
||||
|
||||
public int LoadedSoundCount
|
||||
{
|
||||
@@ -110,7 +151,43 @@ namespace Barotrauma.Sounds
|
||||
get { return loadedSounds.Select(s => s.Filename).Distinct().Count(); }
|
||||
}
|
||||
|
||||
private Dictionary<string, Pair<float, bool>> categoryModifiers;
|
||||
private class CategoryModifier
|
||||
{
|
||||
public float[] GainMultipliers;
|
||||
public bool Muffle;
|
||||
|
||||
public CategoryModifier(int gainMultiplierIndex, float gain, bool muffle)
|
||||
{
|
||||
Muffle = muffle;
|
||||
GainMultipliers = new float[gainMultiplierIndex+1];
|
||||
for (int i=0;i<GainMultipliers.Length;i++)
|
||||
{
|
||||
if (i==gainMultiplierIndex)
|
||||
{
|
||||
GainMultipliers[i] = gain;
|
||||
}
|
||||
else
|
||||
{
|
||||
GainMultipliers[i] = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetGainMultiplier(int index, float gain)
|
||||
{
|
||||
if (GainMultipliers.Length < index+1)
|
||||
{
|
||||
int oldLength = GainMultipliers.Length;
|
||||
Array.Resize(ref GainMultipliers, index + 1);
|
||||
for (int i=oldLength;i<GainMultipliers.Length;i++)
|
||||
{
|
||||
GainMultipliers[i] = 1.0f;
|
||||
}
|
||||
}
|
||||
GainMultipliers[index] = gain;
|
||||
}
|
||||
}
|
||||
private Dictionary<string, CategoryModifier> categoryModifiers;
|
||||
|
||||
public SoundManager()
|
||||
{
|
||||
@@ -190,6 +267,8 @@ namespace Barotrauma.Sounds
|
||||
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 Sound LoadSound(string filename, bool stream = false)
|
||||
@@ -257,11 +336,12 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (Disabled) { return -1; }
|
||||
|
||||
lock (playingChannels)
|
||||
//remove a channel that has stopped
|
||||
//or hasn't even been assigned
|
||||
int poolIndex = (int)newChannel.Sound.SourcePoolIndex;
|
||||
|
||||
lock (playingChannels[poolIndex])
|
||||
{
|
||||
//remove a channel that has stopped
|
||||
//or hasn't even been assigned
|
||||
int poolIndex = (int)newChannel.Sound.SourcePoolIndex;
|
||||
for (int i = 0; i < playingChannels[poolIndex].Length; i++)
|
||||
{
|
||||
if (playingChannels[poolIndex][i] == null || !playingChannels[poolIndex][i].IsPlaying)
|
||||
@@ -271,10 +351,10 @@ namespace Barotrauma.Sounds
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
//we couldn't get a free source to assign to this channel!
|
||||
return -1;
|
||||
}
|
||||
|
||||
//we couldn't get a free source to assign to this channel!
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
@@ -291,7 +371,7 @@ namespace Barotrauma.Sounds
|
||||
public bool IsPlaying(Sound sound)
|
||||
{
|
||||
if (Disabled) { return false; }
|
||||
lock (playingChannels)
|
||||
lock (playingChannels[(int)sound.SourcePoolIndex])
|
||||
{
|
||||
for (int i = 0; i < playingChannels[(int)sound.SourcePoolIndex].Length; i++)
|
||||
{
|
||||
@@ -309,7 +389,7 @@ namespace Barotrauma.Sounds
|
||||
{
|
||||
if (Disabled) { return 0; }
|
||||
int count = 0;
|
||||
lock (playingChannels)
|
||||
lock (playingChannels[(int)sound.SourcePoolIndex])
|
||||
{
|
||||
for (int i = 0; i < playingChannels[(int)sound.SourcePoolIndex].Length; i++)
|
||||
{
|
||||
@@ -326,7 +406,7 @@ namespace Barotrauma.Sounds
|
||||
public SoundChannel GetChannelFromSound(Sound sound)
|
||||
{
|
||||
if (Disabled) { return null; }
|
||||
lock (playingChannels)
|
||||
lock (playingChannels[(int)sound.SourcePoolIndex])
|
||||
{
|
||||
for (int i = 0; i < playingChannels[(int)sound.SourcePoolIndex].Length; i++)
|
||||
{
|
||||
@@ -343,7 +423,7 @@ namespace Barotrauma.Sounds
|
||||
public void KillChannels(Sound sound)
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
lock (playingChannels)
|
||||
lock (playingChannels[(int)sound.SourcePoolIndex])
|
||||
{
|
||||
for (int i = 0; i < playingChannels[(int)sound.SourcePoolIndex].Length; i++)
|
||||
{
|
||||
@@ -371,22 +451,23 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCategoryGainMultiplier(string category, float gain)
|
||||
public void SetCategoryGainMultiplier(string category, float gain, int index=0)
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
category = category.ToLower();
|
||||
if (categoryModifiers == null) categoryModifiers = new Dictionary<string, Pair<float, bool>>();
|
||||
if (categoryModifiers == null) categoryModifiers = new Dictionary<string, CategoryModifier>();
|
||||
if (!categoryModifiers.ContainsKey(category))
|
||||
{
|
||||
categoryModifiers.Add(category, new Pair<float, bool>(gain, false));
|
||||
categoryModifiers.Add(category, new CategoryModifier(index, gain, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryModifiers[category].First = gain;
|
||||
categoryModifiers[category].SetGainMultiplier(index, gain);
|
||||
}
|
||||
lock (playingChannels)
|
||||
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
lock (playingChannels[i])
|
||||
{
|
||||
for (int j = 0; j < playingChannels[i].Length; j++)
|
||||
{
|
||||
@@ -399,12 +480,24 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
|
||||
public float GetCategoryGainMultiplier(string category)
|
||||
public float GetCategoryGainMultiplier(string category, int index=-1)
|
||||
{
|
||||
if (Disabled) { return 0.0f; }
|
||||
category = category.ToLower();
|
||||
if (categoryModifiers == null || !categoryModifiers.ContainsKey(category)) return 1.0f;
|
||||
return categoryModifiers[category].First;
|
||||
if (index < 0)
|
||||
{
|
||||
float accumulatedMultipliers = 1.0f;
|
||||
for (int i=0;i<categoryModifiers[category].GainMultipliers.Length;i++)
|
||||
{
|
||||
accumulatedMultipliers *= categoryModifiers[category].GainMultipliers[i];
|
||||
}
|
||||
return accumulatedMultipliers;
|
||||
}
|
||||
else
|
||||
{
|
||||
return categoryModifiers[category].GainMultipliers[index];
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCategoryMuffle(string category,bool muffle)
|
||||
@@ -413,23 +506,26 @@ namespace Barotrauma.Sounds
|
||||
|
||||
category = category.ToLower();
|
||||
|
||||
if (categoryModifiers == null) categoryModifiers = new Dictionary<string, Pair<float, bool>>();
|
||||
if (categoryModifiers == null) categoryModifiers = new Dictionary<string, CategoryModifier>();
|
||||
if (!categoryModifiers.ContainsKey(category))
|
||||
{
|
||||
categoryModifiers.Add(category, new Pair<float, bool>(1.0f, muffle));
|
||||
categoryModifiers.Add(category, new CategoryModifier(0, 1.0f, muffle));
|
||||
}
|
||||
else
|
||||
{
|
||||
categoryModifiers[category].Second = muffle;
|
||||
categoryModifiers[category].Muffle = muffle;
|
||||
}
|
||||
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
{
|
||||
for (int j = 0; j < playingChannels[i].Length; j++)
|
||||
lock (playingChannels[i])
|
||||
{
|
||||
if (playingChannels[i][j] != null && playingChannels[i][j].IsPlaying)
|
||||
for (int j = 0; j < playingChannels[i].Length; j++)
|
||||
{
|
||||
if (playingChannels[i][j].Category.ToLower() == category) playingChannels[i][j].Muffled = muffle;
|
||||
if (playingChannels[i][j] != null && playingChannels[i][j].IsPlaying)
|
||||
{
|
||||
if (playingChannels[i][j].Category.ToLower() == category) playingChannels[i][j].Muffled = muffle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -441,7 +537,45 @@ namespace Barotrauma.Sounds
|
||||
|
||||
category = category.ToLower();
|
||||
if (categoryModifiers == null || !categoryModifiers.ContainsKey(category)) return false;
|
||||
return categoryModifiers[category].Second;
|
||||
return categoryModifiers[category].Muffle;
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (GameMain.Client != null && GameMain.Config.VoipAttenuationEnabled)
|
||||
{
|
||||
if (Timing.TotalTime > lastAttenuationTime+0.2)
|
||||
{
|
||||
voipAttenuatedGain = voipAttenuatedGain * 0.9f + 0.1f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
voipAttenuatedGain = 1.0f;
|
||||
}
|
||||
SetCategoryGainMultiplier("default", VoipAttenuatedGain, 1);
|
||||
SetCategoryGainMultiplier("ui", VoipAttenuatedGain, 1);
|
||||
SetCategoryGainMultiplier("waterambience", VoipAttenuatedGain, 1);
|
||||
SetCategoryGainMultiplier("music", VoipAttenuatedGain, 1);
|
||||
|
||||
if (GameMain.Config.DynamicRangeCompressionEnabled)
|
||||
{
|
||||
float targetGain = (Math.Min(1.0f, 1.0f / PlaybackAmplitude) - 1.0f) * 0.5f + 1.0f;
|
||||
if (targetGain < CompressionDynamicRangeGain)
|
||||
{
|
||||
//if the target gain is lower than the current gain, lower the current gain immediately to prevent clipping
|
||||
CompressionDynamicRangeGain = targetGain;
|
||||
}
|
||||
else
|
||||
{
|
||||
//otherwise, let it rise back smoothly
|
||||
CompressionDynamicRangeGain = (targetGain) * 0.05f + CompressionDynamicRangeGain * 0.95f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CompressionDynamicRangeGain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public void InitStreamThread()
|
||||
@@ -464,9 +598,10 @@ namespace Barotrauma.Sounds
|
||||
while (areStreamsPlaying)
|
||||
{
|
||||
areStreamsPlaying = false;
|
||||
lock (playingChannels)
|
||||
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
lock (playingChannels[i])
|
||||
{
|
||||
for (int j = 0; j < playingChannels[i].Length; j++)
|
||||
{
|
||||
@@ -497,14 +632,14 @@ namespace Barotrauma.Sounds
|
||||
Thread.Sleep(10); //TODO: use a separate thread for network audio?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Disabled) { return; }
|
||||
|
||||
lock (playingChannels)
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
{
|
||||
for (int i = 0; i < playingChannels.Length; i++)
|
||||
lock (playingChannels[i])
|
||||
{
|
||||
for (int j = 0; j < playingChannels[i].Length; j++)
|
||||
{
|
||||
@@ -512,6 +647,7 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
streamingThread?.Join();
|
||||
for (int i = loadedSounds.Count - 1; i >= 0; i--)
|
||||
{
|
||||
|
||||
@@ -393,19 +393,19 @@ namespace Barotrauma
|
||||
if (Math.Abs(diff.X) < FireSoundRange && Math.Abs(diff.Y) < FireSoundRange)
|
||||
{
|
||||
Vector2 diffLeft = (fs.WorldPosition + new Vector2(fs.Size.X, fs.Size.Y / 2)) - listenerPos;
|
||||
if (diff.X < fs.Size.X / 2.0f) diff.X = 0.0f;
|
||||
if (Math.Abs(diff.X) < fs.Size.X / 2.0f) { diffLeft.X = 0.0f; }
|
||||
if (diffLeft.X <= 0)
|
||||
{
|
||||
float distFallOffLeft = diffLeft.Length() / FireSoundRange;
|
||||
if (distFallOffLeft < 0.99f)
|
||||
{
|
||||
fireVolumeLeft[0] += (1.0f - distFallOffLeft) * (fs.Size.X / FireSoundLargeLimit);
|
||||
fireVolumeLeft[0] += (1.0f - distFallOffLeft);
|
||||
if (fs.Size.X > FireSoundLargeLimit) fireVolumeLeft[1] += (1.0f - distFallOffLeft) * ((fs.Size.X - FireSoundLargeLimit) / FireSoundLargeLimit);
|
||||
}
|
||||
}
|
||||
|
||||
Vector2 diffRight = (fs.WorldPosition + new Vector2(0.0f, fs.Size.Y / 2)) - listenerPos;
|
||||
if (diff.X < fs.Size.X / 2.0f) diff.X = 0.0f;
|
||||
if (Math.Abs(diff.X) < fs.Size.X / 2.0f) { diffRight.X = 0.0f; }
|
||||
if (diffRight.X >= 0)
|
||||
{
|
||||
float distFallOffRight = diffRight.Length() / FireSoundRange;
|
||||
|
||||
@@ -32,6 +32,11 @@ namespace Barotrauma.Sounds
|
||||
video = vid;
|
||||
}
|
||||
|
||||
public override float GetAmplitudeAtPlaybackPos(int playbackPos)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool IsPlaying()
|
||||
{
|
||||
bool retVal = false;
|
||||
@@ -65,8 +70,15 @@ namespace Barotrauma.Sounds
|
||||
SoundChannel chn = null;
|
||||
lock (mutex)
|
||||
{
|
||||
if (soundChannel != null) soundChannel.Dispose();
|
||||
chn = new SoundChannel(this, gain, null, 1.0f, 3.0f, "video", false);
|
||||
if (soundChannel != null)
|
||||
{
|
||||
soundChannel.Dispose();
|
||||
soundChannel = null;
|
||||
}
|
||||
}
|
||||
chn = new SoundChannel(this, gain, null, 1.0f, 3.0f, "video", false);
|
||||
lock (mutex)
|
||||
{
|
||||
soundChannel = chn;
|
||||
}
|
||||
return chn;
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
|
||||
private VoipQueue queue;
|
||||
public int bufferID = 0;
|
||||
private int bufferID = 0;
|
||||
|
||||
private SoundChannel soundChannel;
|
||||
|
||||
@@ -54,6 +54,11 @@ namespace Barotrauma.Sounds
|
||||
}
|
||||
}
|
||||
|
||||
public float CurrentAmplitude
|
||||
{
|
||||
get { return soundChannel?.CurrentAmplitude ?? 0.0f; }
|
||||
}
|
||||
|
||||
public VoipSound(SoundManager owner, VoipQueue q) : base(owner, "voip", true, true)
|
||||
{
|
||||
VoipConfig.SetupEncoding();
|
||||
@@ -70,6 +75,11 @@ namespace Barotrauma.Sounds
|
||||
soundChannel = chn;
|
||||
}
|
||||
|
||||
public override float GetAmplitudeAtPlaybackPos(int playbackPos)
|
||||
{
|
||||
throw new NotImplementedException(); //TODO: implement?
|
||||
}
|
||||
|
||||
public void SetPosition(Vector3? pos)
|
||||
{
|
||||
soundChannel.Position = pos;
|
||||
|
||||
Reference in New Issue
Block a user