MoonWorks/src/Audio/SoundQueue.cs

131 lines
2.8 KiB
C#
Raw Normal View History

2023-07-28 20:02:50 +00:00
using System;
namespace MoonWorks.Audio
{
2023-07-28 20:21:50 +00:00
// NOTE: all sounds played with a SoundSequence must have the same audio format!
public class SoundSequence : SoundInstance
2023-07-28 20:02:50 +00:00
{
2023-07-28 20:10:01 +00:00
public int NeedSoundThreshold = 0;
public delegate void OnSoundNeededFunc();
public OnSoundNeededFunc OnSoundNeeded;
2023-07-28 20:02:50 +00:00
private object StateLock = new object();
2023-07-28 20:21:50 +00:00
public SoundSequence(AudioDevice device, ushort formatTag, ushort bitsPerSample, ushort blockAlign, ushort channels, uint samplesPerSecond) : base(device, formatTag, bitsPerSample, blockAlign, channels, samplesPerSecond)
2023-07-28 20:02:50 +00:00
{
2023-07-28 20:21:50 +00:00
device.AddSoundSequenceReference(this);
2023-07-28 20:02:50 +00:00
}
2023-07-28 20:21:50 +00:00
public SoundSequence(AudioDevice device, StaticSound templateSound) : base(device, templateSound.FormatTag, templateSound.BitsPerSample, templateSound.BlockAlign, templateSound.Channels, templateSound.SamplesPerSecond)
2023-07-28 20:02:50 +00:00
{
2023-07-28 20:21:50 +00:00
device.AddSoundSequenceReference(this);
2023-07-28 20:02:50 +00:00
}
public void Update()
{
lock (StateLock)
{
if (IsDisposed) { return; }
if (State != SoundState.Playing) { return; }
2023-07-28 20:10:01 +00:00
if (NeedSoundThreshold > 0)
2023-07-28 20:02:50 +00:00
{
FAudio.FAudioSourceVoice_GetState(
Voice,
out var state,
FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED
);
var queuedBufferCount = state.BuffersQueued;
2023-07-28 20:10:01 +00:00
for (int i = 0; i < NeedSoundThreshold - queuedBufferCount; i += 1)
2023-07-28 20:02:50 +00:00
{
2023-07-28 20:10:01 +00:00
if (OnSoundNeeded != null)
2023-07-28 20:02:50 +00:00
{
2023-07-28 20:10:01 +00:00
OnSoundNeeded();
2023-07-28 20:02:50 +00:00
}
}
}
}
}
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;
}
}
}
}