Unstable 1.1.14.0
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user