From ffc51cca185900e2341675c1457dd49e3d438746 Mon Sep 17 00:00:00 2001 From: cosmonaut Date: Wed, 20 Jan 2021 10:55:15 -0800 Subject: [PATCH] fix dynamic looping --- src/Audio/DynamicSound.cs | 4 +-- src/Audio/DynamicSoundInstance.cs | 52 +++++++++++++++++++++---------- src/Audio/SoundInstance.cs | 7 ++++- src/Audio/StaticSound.cs | 4 +-- src/Audio/StaticSoundInstance.cs | 9 ++---- 5 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/Audio/DynamicSound.cs b/src/Audio/DynamicSound.cs index 0485d03..2c0f3f6 100644 --- a/src/Audio/DynamicSound.cs +++ b/src/Audio/DynamicSound.cs @@ -44,9 +44,9 @@ namespace MoonWorks.Audio }; } - public DynamicSoundInstance CreateInstance() + public DynamicSoundInstance CreateInstance(bool loop = false) { - var instance = new DynamicSoundInstance(Device, this, false); + var instance = new DynamicSoundInstance(Device, this, false, loop); Device.AddDynamicSoundInstance(instance); return instance; } diff --git a/src/Audio/DynamicSoundInstance.cs b/src/Audio/DynamicSoundInstance.cs index 5ef7c7a..78a3fc8 100644 --- a/src/Audio/DynamicSoundInstance.cs +++ b/src/Audio/DynamicSoundInstance.cs @@ -19,8 +19,9 @@ namespace MoonWorks.Audio internal DynamicSoundInstance( AudioDevice device, DynamicSound parent, - bool is3D - ) : base(device, parent, is3D) + bool is3D, + bool loop + ) : base(device, parent, is3D, loop) { queuedBuffers = new List(); queuedSizes = new List(); @@ -32,17 +33,14 @@ namespace MoonWorks.Audio public void Play() { - Update(); - if (State == SoundState.Playing) { return; } - QueueBuffers(); - - FAudio.FAudioSourceVoice_Start(Handle, 0, 0); State = SoundState.Playing; + Update(); + FAudio.FAudioSourceVoice_Start(Handle, 0, 0); } public void Pause() @@ -54,12 +52,16 @@ namespace MoonWorks.Audio } } - public void Stop() + public void Stop(bool immediate = true) { - FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); - FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle); + if (immediate) + { + FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); + FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle); + ClearBuffers(); + } + State = SoundState.Stopped; - ClearBuffers(); } internal void Update() @@ -80,8 +82,9 @@ namespace MoonWorks.Audio { Marshal.FreeHGlobal(queuedBuffers[0]); queuedBuffers.RemoveAt(0); - queuedSizes.RemoveAt(0); } + + QueueBuffers(); } private void QueueBuffers() @@ -104,7 +107,7 @@ namespace MoonWorks.Audio Marshal.FreeHGlobal(buf); } queuedBuffers.Clear(); - queuedBuffers.Clear(); + queuedSizes.Clear(); } } @@ -112,6 +115,7 @@ namespace MoonWorks.Audio { var parent = (DynamicSound) Parent; + /* NOTE: this function returns samples per channel, not total samples */ var samples = FAudio.stb_vorbis_get_samples_float_interleaved( parent.FileHandle, parent.Info.channels, @@ -119,13 +123,14 @@ namespace MoonWorks.Audio buffer.Length ); - IntPtr next = Marshal.AllocHGlobal(buffer.Length * sizeof(float)); - Marshal.Copy(buffer, 0, next, buffer.Length); + var sampleCount = samples * parent.Info.channels; + var lengthInBytes = (uint) sampleCount * sizeof(float); + + IntPtr next = Marshal.AllocHGlobal((int) lengthInBytes); + Marshal.Copy(buffer, 0, next, sampleCount); lock (queuedBuffers) { - var lengthInBytes = (uint) buffer.Length * sizeof(float); - queuedBuffers.Add(next); if (State != SoundState.Stopped) { @@ -151,6 +156,19 @@ namespace MoonWorks.Audio queuedSizes.Add(lengthInBytes); } } + + /* We have reached the end of the file, what do we do? */ + if (sampleCount < buffer.Length) + { + if (Loop) + { + FAudio.stb_vorbis_seek_start(parent.FileHandle); + } + else + { + Stop(false); + } + } } } } diff --git a/src/Audio/SoundInstance.cs b/src/Audio/SoundInstance.cs index 1a232e1..441549d 100644 --- a/src/Audio/SoundInstance.cs +++ b/src/Audio/SoundInstance.cs @@ -8,6 +8,8 @@ namespace MoonWorks.Audio protected AudioDevice Device { get; } internal IntPtr Handle { get; } public Sound Parent { get; } + public bool Loop { get; } + protected FAudio.F3DAUDIO_DSP_SETTINGS dspSettings; protected bool is3D; @@ -171,7 +173,8 @@ namespace MoonWorks.Audio public SoundInstance( AudioDevice device, Sound parent, - bool is3D + bool is3D, + bool loop ) { Device = device; Parent = parent; @@ -203,6 +206,8 @@ namespace MoonWorks.Audio handle, ref Device.ReverbSends ); + + Loop = loop; } private void InitDSPSettings(uint srcChannels) diff --git a/src/Audio/StaticSound.cs b/src/Audio/StaticSound.cs index f9c3ac6..77802cd 100644 --- a/src/Audio/StaticSound.cs +++ b/src/Audio/StaticSound.cs @@ -78,9 +78,9 @@ namespace MoonWorks.Audio LoopLength = 0; } - public StaticSoundInstance CreateInstance() + public StaticSoundInstance CreateInstance(bool loop = false) { - return new StaticSoundInstance(Device, this, false, true); + return new StaticSoundInstance(Device, this, false, loop); } protected virtual void Dispose(bool disposing) diff --git a/src/Audio/StaticSoundInstance.cs b/src/Audio/StaticSoundInstance.cs index 2a5e669..10eb23a 100644 --- a/src/Audio/StaticSoundInstance.cs +++ b/src/Audio/StaticSoundInstance.cs @@ -4,8 +4,6 @@ namespace MoonWorks.Audio { public class StaticSoundInstance : SoundInstance { - public bool Loop { get; } - private SoundState _state = SoundState.Stopped; public override SoundState State { @@ -30,14 +28,13 @@ namespace MoonWorks.Audio } } - public StaticSoundInstance( + internal StaticSoundInstance( AudioDevice device, StaticSound parent, bool is3D, - bool loop = false - ) : base(device, parent, is3D) + bool loop + ) : base(device, parent, is3D, loop) { - Loop = loop; State = SoundState.Stopped; }