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