add SoundQueue
parent
dbbd6540ab
commit
1d86d0c210
|
@ -30,6 +30,7 @@ namespace MoonWorks.Audio
|
|||
private readonly HashSet<WeakReference> resources = new HashSet<WeakReference>();
|
||||
private readonly List<StreamingSound> autoUpdateStreamingSoundReferences = new List<StreamingSound>();
|
||||
private readonly List<StaticSoundInstance> autoFreeStaticSoundInstanceReferences = new List<StaticSoundInstance>();
|
||||
private readonly List<WeakReference<SoundQueue>> soundQueueReferences = new List<WeakReference<SoundQueue>>();
|
||||
|
||||
private AudioTweenManager AudioTweenManager;
|
||||
|
||||
|
@ -184,6 +185,18 @@ namespace MoonWorks.Audio
|
|||
}
|
||||
}
|
||||
|
||||
for (var i = soundQueueReferences.Count - 1; i >= 0; i -= 1)
|
||||
{
|
||||
if (soundQueueReferences[i].TryGetTarget(out var soundQueue))
|
||||
{
|
||||
soundQueue.Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
soundQueueReferences.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
AudioTweenManager.Update(elapsedSeconds);
|
||||
}
|
||||
|
||||
|
@ -256,6 +269,11 @@ namespace MoonWorks.Audio
|
|||
autoFreeStaticSoundInstanceReferences.Add(instance);
|
||||
}
|
||||
|
||||
internal void AddSoundQueueReference(SoundQueue queue)
|
||||
{
|
||||
soundQueueReferences.Add(new WeakReference<SoundQueue>(queue));
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!IsDisposed)
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
using System;
|
||||
|
||||
namespace MoonWorks.Audio
|
||||
{
|
||||
// NOTE: all sounds played with a playlist must have the same audio format!
|
||||
public class SoundQueue : SoundInstance
|
||||
{
|
||||
public int NeedBufferThreshold = 0;
|
||||
private uint queuedBufferCount = 0;
|
||||
|
||||
public delegate void OnBufferNeededFunc();
|
||||
public OnBufferNeededFunc OnBufferNeeded;
|
||||
|
||||
private object StateLock = new object();
|
||||
|
||||
public SoundQueue(AudioDevice device, ushort formatTag, ushort bitsPerSample, ushort blockAlign, ushort channels, uint samplesPerSecond) : base(device, formatTag, bitsPerSample, blockAlign, channels, samplesPerSecond)
|
||||
{
|
||||
device.AddSoundQueueReference(this);
|
||||
}
|
||||
|
||||
public SoundQueue(AudioDevice device, StaticSound templateSound) : base(device, templateSound.FormatTag, templateSound.BitsPerSample, templateSound.BlockAlign, templateSound.Channels, templateSound.SamplesPerSecond)
|
||||
{
|
||||
device.AddSoundQueueReference(this);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
lock (StateLock)
|
||||
{
|
||||
if (IsDisposed) { return; }
|
||||
if (State != SoundState.Playing) { return; }
|
||||
|
||||
if (NeedBufferThreshold > 0)
|
||||
{
|
||||
FAudio.FAudioSourceVoice_GetState(
|
||||
Voice,
|
||||
out var state,
|
||||
FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED
|
||||
);
|
||||
|
||||
var queuedBufferCount = state.BuffersQueued;
|
||||
for (int i = 0; i < NeedBufferThreshold - queuedBufferCount; i += 1)
|
||||
{
|
||||
if (OnBufferNeeded != null)
|
||||
{
|
||||
OnBufferNeeded();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void EnqueueSound(StaticSound sound)
|
||||
{
|
||||
#if DEBUG
|
||||
if (
|
||||
sound.FormatTag != Format.wFormatTag ||
|
||||
sound.BitsPerSample != Format.wBitsPerSample ||
|
||||
sound.Channels != Format.nChannels ||
|
||||
sound.SamplesPerSecond != Format.nSamplesPerSec
|
||||
)
|
||||
{
|
||||
Logger.LogWarn("Playlist audio format mismatch!");
|
||||
}
|
||||
#endif
|
||||
|
||||
lock (StateLock)
|
||||
{
|
||||
FAudio.FAudioSourceVoice_SubmitSourceBuffer(
|
||||
Voice,
|
||||
ref sound.Handle,
|
||||
IntPtr.Zero
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Pause()
|
||||
{
|
||||
lock (StateLock)
|
||||
{
|
||||
if (State == SoundState.Playing)
|
||||
{
|
||||
FAudio.FAudioSourceVoice_Stop(Voice, 0, 0);
|
||||
State = SoundState.Paused;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Play()
|
||||
{
|
||||
PlayUsingOperationSet(0);
|
||||
}
|
||||
|
||||
public override void QueueSyncPlay()
|
||||
{
|
||||
PlayUsingOperationSet(1);
|
||||
}
|
||||
|
||||
private void PlayUsingOperationSet(uint operationSet)
|
||||
{
|
||||
lock (StateLock)
|
||||
{
|
||||
if (State == SoundState.Playing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FAudio.FAudioSourceVoice_Start(Voice, 0, operationSet);
|
||||
State = SoundState.Playing;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
lock (StateLock)
|
||||
{
|
||||
FAudio.FAudioSourceVoice_ExitLoop(Voice, 0);
|
||||
State = SoundState.Stopped;
|
||||
}
|
||||
}
|
||||
|
||||
public override void StopImmediate()
|
||||
{
|
||||
lock (StateLock)
|
||||
{
|
||||
FAudio.FAudioSourceVoice_Stop(Voice, 0, 0);
|
||||
FAudio.FAudioSourceVoice_FlushSourceBuffers(Voice);
|
||||
State = SoundState.Stopped;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue