Unstable 1.1.14.0

This commit is contained in:
Markus Isberg
2023-10-02 16:43:54 +03:00
parent 94f5a93a0c
commit cf8f0de659
606 changed files with 21906 additions and 11456 deletions
@@ -2,21 +2,89 @@
using OpenAL;
using NVorbis;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace Barotrauma.Sounds
{
class OggSound : Sound
sealed class OggSound : Sound
{
private VorbisReader reader;
private VorbisReader streamReader;
//key = sample rate, value = filter
private static readonly Dictionary<int, BiQuad> muffleFilters = new Dictionary<int, BiQuad>();
private static List<float> playbackAmplitude;
private 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) { }
private short[] sampleBuffer = Array.Empty<short>();
private short[] muffleBuffer = Array.Empty<short>();
public OggSound(SoundManager owner, string filename, bool stream, XElement xElement) : base(owner, filename,
stream, true, xElement)
{
var reader = new VorbisReader(Filename);
ALFormat = reader.Channels == 1 ? Al.FormatMono16 : Al.FormatStereo16;
SampleRate = reader.SampleRate;
if (stream)
{
streamReader = reader;
return;
}
TaskPool.Add(
$"LoadSamples {filename}",
LoadSamples(reader),
t =>
{
reader.Dispose();
if (!t.TryGetResult(out TaskResult result))
{
return;
}
sampleBuffer = result.SampleBuffer;
muffleBuffer = result.MuffleBuffer;
playbackAmplitude = result.PlaybackAmplitude;
Owner.KillChannels(this); // prevents INVALID_OPERATION error
buffers?.Dispose(); buffers = null;
});
}
private readonly record struct TaskResult(
short[] SampleBuffer,
short[] MuffleBuffer,
List<float> PlaybackAmplitude);
private static async Task<TaskResult> LoadSamples(VorbisReader reader)
{
reader.DecodedPosition = 0;
int bufferSize = (int)reader.TotalSamples * reader.Channels;
float[] floatBuffer = new float[bufferSize];
var sampleBuffer = new short[bufferSize];
var muffledBuffer = new short[bufferSize];
int readSamples = await Task.Run(() => reader.ReadSamples(floatBuffer, 0, bufferSize));
var 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, sampleBuffer, readSamples);
MuffleBuffer(floatBuffer, reader.SampleRate);
CastBuffer(floatBuffer, muffledBuffer, readSamples);
return new TaskResult(sampleBuffer, muffledBuffer, playbackAmplitude);
}
public override float GetAmplitudeAtPlaybackPos(int playbackPos)
{
@@ -27,101 +95,65 @@ namespace Barotrauma.Sounds
return playbackAmplitude[index];
}
private float[] streamFloatBuffer = null;
public override int FillStreamBuffer(int samplePos, short[] buffer)
{
if (!Stream) { throw new Exception("Called FillStreamBuffer on a non-streamed sound!"); }
if (reader == null) { throw new Exception("Called FillStreamBuffer when the reader is null!"); }
if (streamReader == null) { throw new Exception("Called FillStreamBuffer when the reader is null!"); }
if (samplePos >= reader.TotalSamples * reader.Channels * 2) return 0;
if (samplePos >= streamReader.TotalSamples * streamReader.Channels * 2) return 0;
samplePos /= reader.Channels * 2;
reader.DecodedPosition = samplePos;
samplePos /= streamReader.Channels * 2;
streamReader.DecodedPosition = samplePos;
float[] floatBuffer = new float[buffer.Length];
int readSamples = reader.ReadSamples(floatBuffer, 0, buffer.Length / 2);
if (streamFloatBuffer is null || streamFloatBuffer.Length < buffer.Length)
{
streamFloatBuffer = new float[buffer.Length];
}
int readSamples = streamReader.ReadSamples(streamFloatBuffer, 0, buffer.Length);
//MuffleBuffer(floatBuffer, reader.Channels);
CastBuffer(floatBuffer, buffer, readSamples);
CastBuffer(streamFloatBuffer, buffer, readSamples);
return readSamples;
}
static void MuffleBuffer(float[] buffer, int sampleRate, int channelCount)
static void MuffleBuffer(float[] buffer, int sampleRate)
{
if (!muffleFilters.TryGetValue(sampleRate, out BiQuad filter))
{
filter = new LowpassFilter(sampleRate, 1600);
muffleFilters.Add(sampleRate, filter);
}
var filter = new LowpassFilter(sampleRate, 1600);
filter.Process(buffer);
}
public override void InitializeALBuffers()
public override void InitializeAlBuffers()
{
base.InitializeALBuffers();
reader ??= new VorbisReader(Filename);
ALFormat = reader.Channels == 1 ? Al.FormatMono16 : Al.FormatStereo16;
SampleRate = reader.SampleRate;
if (Buffers != null && SoundBuffers.BuffersGenerated < SoundBuffers.MaxBuffers)
if (buffers != null && SoundBuffers.BuffersGenerated < SoundBuffers.MaxBuffers)
{
Buffers.RequestAlBuffers(); FillBuffers();
FillAlBuffers();
}
}
public override void FillBuffers()
public override void FillAlBuffers()
{
if (!Stream)
if (Stream) { return; }
if (sampleBuffer.Length == 0 || muffleBuffer.Length == 0) { return; }
buffers ??= new SoundBuffers(this);
if (!buffers.RequestAlBuffers()) { return; }
Al.BufferData(buffers.AlBuffer, ALFormat, sampleBuffer,
sampleBuffer.Length * sizeof(short), SampleRate);
int alError = Al.GetError();
if (alError != Al.NoError)
{
reader ??= new VorbisReader(Filename);
throw new Exception("Failed to set regular buffer data for non-streamed audio! " + Al.GetErrorString(alError));
}
reader.DecodedPosition = 0;
Al.BufferData(buffers.AlMuffledBuffer, ALFormat, muffleBuffer,
muffleBuffer.Length * sizeof(short), SampleRate);
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(Buffers.AlBuffer, ALFormat, shortBuffer,
readSamples * sizeof(short), SampleRate);
int alError = Al.GetError();
if (alError != Al.NoError)
{
throw new Exception("Failed to set regular buffer data for non-streamed audio! " + Al.GetErrorString(alError));
}
MuffleBuffer(floatBuffer, SampleRate, reader.Channels);
CastBuffer(floatBuffer, shortBuffer, readSamples);
Al.BufferData(Buffers.AlMuffledBuffer, ALFormat, shortBuffer,
readSamples * sizeof(short), SampleRate);
alError = Al.GetError();
if (alError != Al.NoError)
{
throw new Exception("Failed to set muffled buffer data for non-streamed audio! " + Al.GetErrorString(alError));
}
reader.Dispose(); reader = null;
alError = Al.GetError();
if (alError != Al.NoError)
{
throw new Exception("Failed to set muffled buffer data for non-streamed audio! " + Al.GetErrorString(alError));
}
}
@@ -129,7 +161,7 @@ namespace Barotrauma.Sounds
{
if (Stream)
{
reader?.Dispose();
streamReader?.Dispose();
}
base.Dispose();
@@ -33,7 +33,7 @@ namespace Barotrauma.Sounds
}
}
private SoundBuffers buffers;
protected SoundBuffers buffers;
public SoundBuffers Buffers
{
get { return !Stream ? buffers : null; }
@@ -72,8 +72,6 @@ namespace Barotrauma.Sounds
BaseGain = 1.0f;
BaseNear = 100.0f;
BaseFar = 200.0f;
InitializeALBuffers();
}
public override string ToString()
@@ -141,21 +139,11 @@ namespace Barotrauma.Sounds
public abstract float GetAmplitudeAtPlaybackPos(int playbackPos);
public virtual void InitializeALBuffers()
{
if (!Stream)
{
buffers = new SoundBuffers(this);
}
else
{
buffers = null;
}
}
public virtual void InitializeAlBuffers() { }
public virtual void FillBuffers() { }
public virtual void FillAlBuffers() { }
public virtual void DeleteALBuffers()
public virtual void DeleteAlBuffers()
{
Owner.KillChannels(this);
buffers?.Dispose();
@@ -165,7 +153,7 @@ namespace Barotrauma.Sounds
{
if (disposed) { return; }
DeleteALBuffers();
DeleteAlBuffers();
Owner.RemoveSound(this);
disposed = true;
@@ -7,7 +7,7 @@ using System.Text;
namespace Barotrauma.Sounds
{
class SoundBuffers : IDisposable
sealed class SoundBuffers : IDisposable
{
private static readonly HashSet<uint> bufferPool = new HashSet<uint>();
#if OSX
@@ -312,54 +312,52 @@ namespace Barotrauma.Sounds
if (!IsPlaying) { return; }
if (!IsStream)
if (IsStream) { return; }
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
Al.GetSourcei(alSource, Al.SampleOffset, out int playbackPos);
int alError = Al.GetError();
if (alError != Al.NoError)
{
uint alSource = Sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex);
Al.GetSourcei(alSource, Al.SampleOffset, out int playbackPos);
int alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to get source's playback position: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
DebugConsole.ThrowError("Failed to get source's playback position: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
Al.SourceStop(alSource);
Al.SourceStop(alSource);
alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to stop source: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to stop source: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
if (Sound.Buffers.RequestAlBuffers())
{
Sound.FillBuffers();
}
Al.Sourcei(alSource, Al.Buffer, muffled ? (int)Sound.Buffers.AlMuffledBuffer : (int)Sound.Buffers.AlBuffer);
Sound.FillAlBuffers();
if (Sound.Buffers is not { AlBuffer: not 0, AlMuffledBuffer: not 0 }) { return; }
alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to bind buffer to source: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
Al.Sourcei(alSource, Al.Buffer, muffled ? (int)Sound.Buffers.AlMuffledBuffer : (int)Sound.Buffers.AlBuffer);
Al.SourcePlay(alSource);
alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to replay source: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to bind buffer to source: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
Al.Sourcei(alSource, Al.SampleOffset, playbackPos);
alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to reset playback position: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
Al.SourcePlay(alSource);
alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to replay source: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
Al.Sourcei(alSource, Al.SampleOffset, playbackPos);
alError = Al.GetError();
if (alError != Al.NoError)
{
DebugConsole.ThrowError("Failed to reset playback position: " + debugName + ", " + Al.GetErrorString(alError), appendStackTrace: true);
return;
}
}
}
@@ -509,10 +507,8 @@ namespace Barotrauma.Sounds
throw new Exception("Failed to reset source buffer: " + debugName + ", " + Al.GetErrorString(alError));
}
if (Sound.Buffers.RequestAlBuffers())
{
Sound.FillBuffers();
}
Sound.FillAlBuffers();
if (Sound.Buffers is not { AlBuffer: not 0, AlMuffledBuffer: not 0 }) { return; }
uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffled ? Sound.Buffers.AlMuffledBuffer : Sound.Buffers.AlBuffer;
Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
@@ -64,14 +64,15 @@ namespace Barotrauma.Sounds
/// The b2 value.
/// </summary>
protected double B2;
/// <summary>
/// The q value.
/// </summary>
private double _q;
protected readonly double _q;
/// <summary>
/// The gain value in dB.
/// </summary>
private double _gainDB;
protected readonly double _gainDB;
/// <summary>
/// The z1 value.
/// </summary>
@@ -81,77 +82,15 @@ namespace Barotrauma.Sounds
/// </summary>
protected double Z2;
private double _frequency;
/// <summary>
/// Gets or sets the frequency.
/// </summary>
/// <exception cref="System.ArgumentOutOfRangeException">value;The samplerate has to be bigger than 2 * frequency.</exception>
public double Frequency
{
get { return _frequency; }
set
{
if (SampleRate < value * 2)
{
throw new ArgumentOutOfRangeException("value", "The samplerate has to be bigger than 2 * frequency.");
}
_frequency = value;
CalculateBiQuadCoefficients();
}
}
protected readonly double _frequency;
/// <summary>
/// Gets the sample rate.
/// </summary>
public int SampleRate { get; private set; }
protected readonly int _sampleRate;
/// <summary>
/// The q value.
/// </summary>
public double Q
{
get { return _q; }
set
{
if (value <= 0)
{
throw new ArgumentOutOfRangeException("value");
}
_q = value;
CalculateBiQuadCoefficients();
}
}
/// <summary>
/// Gets or sets the gain value in dB.
/// </summary>
public double GainDB
{
get { return _gainDB; }
set
{
_gainDB = value;
CalculateBiQuadCoefficients();
}
}
/// <summary>
/// Initializes a new instance of the <see cref="BiQuad"/> class.
/// </summary>
/// <param name="sampleRate">The sample rate.</param>
/// <param name="frequency">The frequency.</param>
/// <exception cref="System.ArgumentOutOfRangeException">
/// sampleRate
/// or
/// frequency
/// or
/// q
/// </exception>
protected BiQuad(int sampleRate, double frequency)
: this(sampleRate, frequency, 1.0 / Math.Sqrt(2))
{
}
protected static readonly double DefaultQ = 1.0 / Math.Sqrt(2);
protected const double DefaultGainDb = 6.0;
/// <summary>
/// Initializes a new instance of the <see cref="BiQuad"/> class.
@@ -166,18 +105,29 @@ namespace Barotrauma.Sounds
/// or
/// q
/// </exception>
protected BiQuad(int sampleRate, double frequency, double q)
protected BiQuad(int sampleRate, double frequency, double q, double gainDb)
{
if (sampleRate <= 0)
{
throw new ArgumentOutOfRangeException("sampleRate");
}
if (frequency <= 0)
{
throw new ArgumentOutOfRangeException("frequency");
}
if (q <= 0)
{
throw new ArgumentOutOfRangeException("q");
SampleRate = sampleRate;
Frequency = frequency;
Q = q;
GainDB = 6;
}
if (sampleRate < frequency * 2)
{
throw new ArgumentOutOfRangeException("sampleRate", "The sample rate has to be greater than or equal to 2 * frequency.");
}
_sampleRate = sampleRate;
_frequency = frequency;
_q = q;
_gainDB = gainDb;
CalculateBiQuadCoefficients();
}
/// <summary>
@@ -215,7 +165,7 @@ namespace Barotrauma.Sounds
/// <summary>
/// Used to apply a lowpass-filter to a signal.
/// </summary>
public class LowpassFilter : BiQuad
public sealed class LowpassFilter : BiQuad
{
/// <summary>
/// Initializes a new instance of the <see cref="LowpassFilter"/> class.
@@ -223,7 +173,7 @@ namespace Barotrauma.Sounds
/// <param name="sampleRate">The sample rate.</param>
/// <param name="frequency">The filter's corner frequency.</param>
public LowpassFilter(int sampleRate, double frequency)
: base(sampleRate, frequency)
: base(sampleRate, frequency, DefaultQ, DefaultGainDb)
{
}
@@ -232,20 +182,20 @@ namespace Barotrauma.Sounds
/// </summary>
protected override void CalculateBiQuadCoefficients()
{
double k = Math.Tan(Math.PI * Frequency / SampleRate);
var norm = 1 / (1 + k / Q + k * k);
double k = Math.Tan(Math.PI * _frequency / _sampleRate);
var norm = 1 / (1 + k / _q + k * k);
A0 = k * k * norm;
A1 = 2 * A0;
A2 = A0;
B1 = 2 * (k * k - 1) * norm;
B2 = (1 - k / Q + k * k) * norm;
B2 = (1 - k / _q + k * k) * norm;
}
}
/// <summary>
/// Used to apply a highpass-filter to a signal.
/// </summary>
public class HighpassFilter : BiQuad
public sealed class HighpassFilter : BiQuad
{
/// <summary>
/// Initializes a new instance of the <see cref="HighpassFilter"/> class.
@@ -253,7 +203,7 @@ namespace Barotrauma.Sounds
/// <param name="sampleRate">The sample rate.</param>
/// <param name="frequency">The filter's corner frequency.</param>
public HighpassFilter(int sampleRate, double frequency)
: base(sampleRate, frequency)
: base(sampleRate, frequency, DefaultQ, DefaultGainDb)
{
}
@@ -262,20 +212,20 @@ namespace Barotrauma.Sounds
/// </summary>
protected override void CalculateBiQuadCoefficients()
{
double k = Math.Tan(Math.PI * Frequency / SampleRate);
var norm = 1 / (1 + k / Q + k * k);
double k = Math.Tan(Math.PI * _frequency / _sampleRate);
var norm = 1 / (1 + k / _q + k * k);
A0 = 1 * norm;
A1 = -2 * A0;
A2 = A0;
B1 = 2 * (k * k - 1) * norm;
B2 = (1 - k / Q + k * k) * norm;
B2 = (1 - k / _q + k * k) * norm;
}
}
/// <summary>
/// Used to apply a bandpass-filter to a signal.
/// </summary>
public class BandpassFilter : BiQuad
public sealed class BandpassFilter : BiQuad
{
/// <summary>
/// Initializes a new instance of the <see cref="BandpassFilter"/> class.
@@ -283,7 +233,7 @@ namespace Barotrauma.Sounds
/// <param name="sampleRate">The sample rate.</param>
/// <param name="frequency">The filter's corner frequency.</param>
public BandpassFilter(int sampleRate, double frequency)
: base(sampleRate, frequency)
: base(sampleRate, frequency, DefaultQ, DefaultGainDb)
{
}
@@ -292,20 +242,20 @@ namespace Barotrauma.Sounds
/// </summary>
protected override void CalculateBiQuadCoefficients()
{
double k = Math.Tan(Math.PI * Frequency / SampleRate);
double norm = 1 / (1 + k / Q + k * k);
A0 = k / Q * norm;
double k = Math.Tan(Math.PI * _frequency / _sampleRate);
double norm = 1 / (1 + k / _q + k * k);
A0 = k / _q * norm;
A1 = 0;
A2 = -A0;
B1 = 2 * (k * k - 1) * norm;
B2 = (1 - k / Q + k * k) * norm;
B2 = (1 - k / _q + k * k) * norm;
}
}
/// <summary>
/// Used to apply a notch-filter to a signal.
/// </summary>
public class NotchFilter : BiQuad
public sealed class NotchFilter : BiQuad
{
/// <summary>
/// Initializes a new instance of the <see cref="NotchFilter"/> class.
@@ -313,7 +263,7 @@ namespace Barotrauma.Sounds
/// <param name="sampleRate">The sample rate.</param>
/// <param name="frequency">The filter's corner frequency.</param>
public NotchFilter(int sampleRate, double frequency)
: base(sampleRate, frequency)
: base(sampleRate, frequency, DefaultQ, DefaultGainDb)
{
}
@@ -322,20 +272,20 @@ namespace Barotrauma.Sounds
/// </summary>
protected override void CalculateBiQuadCoefficients()
{
double k = Math.Tan(Math.PI * Frequency / SampleRate);
double norm = 1 / (1 + k / Q + k * k);
double k = Math.Tan(Math.PI * _frequency / _sampleRate);
double norm = 1 / (1 + k / _q + k * k);
A0 = (1 + k * k) * norm;
A1 = 2 * (k * k - 1) * norm;
A2 = A0;
B1 = A1;
B2 = (1 - k / Q + k * k) * norm;
B2 = (1 - k / _q + k * k) * norm;
}
}
/// <summary>
/// Used to apply a lowshelf-filter to a signal.
/// </summary>
public class LowShelfFilter : BiQuad
public sealed class LowShelfFilter : BiQuad
{
/// <summary>
/// Initializes a new instance of the <see cref="LowShelfFilter"/> class.
@@ -344,10 +294,8 @@ namespace Barotrauma.Sounds
/// <param name="frequency">The filter's corner frequency.</param>
/// <param name="gainDB">Gain value in dB.</param>
public LowShelfFilter(int sampleRate, double frequency, double gainDB)
: base(sampleRate, frequency)
{
GainDB = gainDB;
}
: base(sampleRate, frequency, DefaultQ, gainDB)
{ }
/// <summary>
/// Calculates all coefficients.
@@ -355,10 +303,10 @@ namespace Barotrauma.Sounds
protected override void CalculateBiQuadCoefficients()
{
const double sqrt2 = 1.4142135623730951;
double k = Math.Tan(Math.PI * Frequency / SampleRate);
double v = Math.Pow(10, Math.Abs(GainDB) / 20.0);
double k = Math.Tan(Math.PI * _frequency / _sampleRate);
double v = Math.Pow(10, Math.Abs(_gainDB) / 20.0);
double norm;
if (GainDB >= 0)
if (_gainDB >= 0)
{ // boost
norm = 1 / (1 + sqrt2 * k + k * k);
A0 = (1 + Math.Sqrt(2 * v) * k + v * k * k) * norm;
@@ -382,7 +330,7 @@ namespace Barotrauma.Sounds
/// <summary>
/// Used to apply a highshelf-filter to a signal.
/// </summary>
public class HighShelfFilter : BiQuad
public sealed class HighShelfFilter : BiQuad
{
/// <summary>
/// Initializes a new instance of the <see cref="HighShelfFilter"/> class.
@@ -391,10 +339,8 @@ namespace Barotrauma.Sounds
/// <param name="frequency">The filter's corner frequency.</param>
/// <param name="gainDB">Gain value in dB.</param>
public HighShelfFilter(int sampleRate, double frequency, double gainDB)
: base(sampleRate, frequency)
{
GainDB = gainDB;
}
: base(sampleRate, frequency, DefaultQ, gainDB)
{ }
/// <summary>
/// Calculates all coefficients.
@@ -402,10 +348,10 @@ namespace Barotrauma.Sounds
protected override void CalculateBiQuadCoefficients()
{
const double sqrt2 = 1.4142135623730951;
double k = Math.Tan(Math.PI * Frequency / SampleRate);
double v = Math.Pow(10, Math.Abs(GainDB) / 20.0);
double k = Math.Tan(Math.PI * _frequency / _sampleRate);
double v = Math.Pow(10, Math.Abs(_gainDB) / 20.0);
double norm;
if (GainDB >= 0)
if (_gainDB >= 0)
{ // boost
norm = 1 / (1 + sqrt2 * k + k * k);
A0 = (v + Math.Sqrt(2 * v) * k + k * k) * norm;
@@ -429,22 +375,8 @@ namespace Barotrauma.Sounds
/// <summary>
/// Used to apply an peak-filter to a signal.
/// </summary>
public class PeakFilter : BiQuad
public sealed class PeakFilter : BiQuad
{
/// <summary>
/// Gets or sets the bandwidth.
/// </summary>
public double BandWidth
{
get { return Q; }
set
{
if (value <= 0)
throw new ArgumentOutOfRangeException("value");
Q = value;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="PeakFilter"/> class.
/// </summary>
@@ -453,10 +385,8 @@ namespace Barotrauma.Sounds
/// <param name="bandWidth">The bandWidth.</param>
/// <param name="peakGainDB">The gain value in dB.</param>
public PeakFilter(int sampleRate, double frequency, double bandWidth, double peakGainDB)
: base(sampleRate, frequency, bandWidth)
{
GainDB = peakGainDB;
}
: base(sampleRate, frequency, bandWidth, peakGainDB)
{ }
/// <summary>
/// Calculates all coefficients.
@@ -464,11 +394,11 @@ namespace Barotrauma.Sounds
protected override void CalculateBiQuadCoefficients()
{
double norm;
double v = Math.Pow(10, Math.Abs(GainDB) / 20.0);
double k = Math.Tan(Math.PI * Frequency / SampleRate);
double q = Q;
double v = Math.Pow(10, Math.Abs(_gainDB) / 20.0);
double k = Math.Tan(Math.PI * _frequency / _sampleRate);
double q = _q;
if (GainDB >= 0) //boost
if (_gainDB >= 0) //boost
{
norm = 1 / (1 + 1 / q * k + k * k);
A0 = (1 + v / q * k + k * k) * norm;
@@ -812,7 +812,7 @@ namespace Barotrauma.Sounds
{
for (int i = loadedSounds.Count - 1; i >= 0; i--)
{
loadedSounds[i].InitializeALBuffers();
loadedSounds[i].InitializeAlBuffers();
}
}
@@ -834,7 +834,7 @@ namespace Barotrauma.Sounds
{
if (keepSounds)
{
loadedSounds[i].DeleteALBuffers();
loadedSounds[i].DeleteAlBuffers();
}
else
{
@@ -156,6 +156,12 @@ namespace Barotrauma
insideSubFactor = 1.0f;
}
if (Character.Controlled != null && Character.Controlled.PressureTimer > 0.0f && !Character.Controlled.IsDead)
{
//make the sound lerp to the "outside" sound when under pressure
insideSubFactor -= Character.Controlled.PressureTimer / 100.0f;
}
movementSoundVolume = Math.Max(movementSoundVolume, movementFactor);
if (!MathUtils.IsValid(movementSoundVolume))
{
@@ -183,7 +189,7 @@ namespace Barotrauma
if (chn is null || !chn.IsPlaying)
{
if (volume < 0.01f) { return; }
if (!(chn is null)) { waterAmbienceChannels.Remove(chn); }
if (chn is not null) { waterAmbienceChannels.Remove(chn); }
chn = sound.Play(volume, "waterambience");
chn.Looping = true;
waterAmbienceChannels.Add(chn);
@@ -195,6 +201,15 @@ namespace Barotrauma
{
chn.FadeOutAndDispose();
}
if (Character.Controlled != null && Character.Controlled.PressureTimer > 0.0f && !Character.Controlled.IsDead)
{
//make the sound decrease in pitch when under pressure
chn.FrequencyMultiplier = MathHelper.Clamp(Character.Controlled.PressureTimer / 200.0f, 0.75f, 1.0f);
}
else
{
chn.FrequencyMultiplier = Math.Min(chn.frequencyMultiplier + deltaTime, 1.0f);
}
}
}
@@ -652,6 +667,7 @@ namespace Barotrauma
}
}
LogCurrentMusic();
updateMusicTimer = UpdateMusicInterval;
}
@@ -715,6 +731,26 @@ namespace Barotrauma
}
}
private static double lastMusicLogTime;
const double MusicLogInterval = 60.0;
private static void LogCurrentMusic()
{
if (Screen.Selected != GameMain.GameScreen) { return; }
if (Timing.TotalTime < lastMusicLogTime + MusicLogInterval) { return; }
for (int i = 0; i < musicChannel.Length; i++)
{
if (musicChannel[i] != null &&
musicChannel[i].IsPlaying &&
musicChannel[i].Sound?.Filename != null)
{
GameAnalyticsManager.AddDesignEvent(
"BackgroundMusic:" +
Path.GetFileNameWithoutExtension(musicChannel[i].Sound.Filename.Replace(":", string.Empty).Replace(" ", string.Empty)));
}
}
lastMusicLogTime = Timing.TotalTime;
}
private static void DisposeMusicChannel(int index)
{
var clip = musicClips.FirstOrDefault(m => m.Sound == musicChannel[index]?.Sound);