diff --git a/src/Audio/StreamingSound.cs b/src/Audio/StreamingSound.cs
index 1bb06d3..eac63fd 100644
--- a/src/Audio/StreamingSound.cs
+++ b/src/Audio/StreamingSound.cs
@@ -1,23 +1,22 @@
using System;
-using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace MoonWorks.Audio
{
///
/// 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.
///
public abstract class StreamingSound : SoundInstance
{
- private readonly List queuedBuffers = new List();
- 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]);
+ }
}
}
}