optimize StreamingSound allocation and update

pull/20/head
cosmonaut 2022-08-02 11:06:45 -07:00
parent b4a0c7de88
commit dc7e68fecc
1 changed files with 41 additions and 53 deletions

View File

@ -1,23 +1,22 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MoonWorks.Audio
{
/// <summary>
/// For streaming long playback.
/// Can be extended to support custom decoders.
/// Must be extended with a decoder routine called by FillBuffer.
/// See StreamingSoundOgg for an example.
/// </summary>
public abstract class StreamingSound : SoundInstance
{
private readonly List<IntPtr> queuedBuffers = new List<IntPtr>();
private const int MINIMUM_BUFFER_CHECK = 3;
private int PendingBufferCount => queuedBuffers.Count;
private const int BUFFER_COUNT = 3;
private readonly IntPtr[] buffers;
private int nextBufferIndex = 0;
private uint queuedBufferCount = 0;
public abstract int BUFFER_SIZE { get; }
public StreamingSound(
public unsafe StreamingSound(
AudioDevice device,
ushort formatTag,
ushort bitsPerSample,
@ -27,6 +26,12 @@ namespace MoonWorks.Audio
) : base(device, formatTag, bitsPerSample, blockAlign, channels, samplesPerSecond)
{
device.AddDynamicSoundInstance(this);
buffers = new IntPtr[BUFFER_COUNT];
for (int i = 0; i < BUFFER_COUNT; i += 1)
{
buffers[i] = (IntPtr) NativeMemory.Alloc((nuint) BUFFER_SIZE);
}
}
public override void Play()
@ -78,25 +83,14 @@ namespace MoonWorks.Audio
FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED
);
while (PendingBufferCount > state.BuffersQueued)
{
lock (queuedBuffers)
{
NativeMemory.Free((void*) queuedBuffers[0]);
queuedBuffers.RemoveAt(0);
}
}
queuedBufferCount = state.BuffersQueued;
QueueBuffers();
}
protected void QueueBuffers()
{
for (
int i = MINIMUM_BUFFER_CHECK - PendingBufferCount;
i > 0;
i -= 1
)
for (int i = 0; i < BUFFER_COUNT - queuedBufferCount; i += 1)
{
AddBuffer();
}
@ -104,51 +98,40 @@ namespace MoonWorks.Audio
protected unsafe void ClearBuffers()
{
lock (queuedBuffers)
{
foreach (IntPtr buf in queuedBuffers)
{
NativeMemory.Free((void*) buf);
}
queuedBuffers.Clear();
}
nextBufferIndex = 0;
queuedBufferCount = 0;
}
protected unsafe void AddBuffer()
{
void* buffer = NativeMemory.Alloc((nuint) BUFFER_SIZE);
var buffer = buffers[nextBufferIndex];
nextBufferIndex = (nextBufferIndex + 1) % BUFFER_COUNT;
FillBuffer(
buffer,
(void*) buffer,
BUFFER_SIZE,
out int filledLengthInBytes,
out bool reachedEnd
);
lock (queuedBuffers)
FAudio.FAudioBuffer buf = new FAudio.FAudioBuffer
{
queuedBuffers.Add((IntPtr) buffer);
if (State != SoundState.Stopped)
{
FAudio.FAudioBuffer buf = new FAudio.FAudioBuffer
{
AudioBytes = (uint) filledLengthInBytes,
pAudioData = (IntPtr) buffer,
PlayLength = (
(uint) (filledLengthInBytes /
Format.nChannels /
(uint) (Format.wBitsPerSample / 8))
)
};
AudioBytes = (uint) filledLengthInBytes,
pAudioData = (IntPtr) buffer,
PlayLength = (
(uint) (filledLengthInBytes /
Format.nChannels /
(uint) (Format.wBitsPerSample / 8))
)
};
FAudio.FAudioSourceVoice_SubmitSourceBuffer(
Handle,
ref buf,
IntPtr.Zero
);
}
}
FAudio.FAudioSourceVoice_SubmitSourceBuffer(
Handle,
ref buf,
IntPtr.Zero
);
queuedBufferCount += 1;
/* We have reached the end of the file, what do we do? */
if (reachedEnd)
@ -169,9 +152,14 @@ namespace MoonWorks.Audio
out bool reachedEnd
);
protected override void Destroy()
protected unsafe override void Destroy()
{
StopImmediate();
for (int i = 0; i < BUFFER_COUNT; i += 1)
{
NativeMemory.Free((void*) buffers[i]);
}
}
}
}