diff --git a/src/Audio/AudioDevice.cs b/src/Audio/AudioDevice.cs index d4acd2ef..7ba24e3d 100644 --- a/src/Audio/AudioDevice.cs +++ b/src/Audio/AudioDevice.cs @@ -4,7 +4,7 @@ using System.Runtime.InteropServices; namespace MoonWorks.Audio { - public class AudioDevice + public class AudioDevice : IDisposable { public IntPtr Handle { get; } public byte[] Handle3D { get; } @@ -17,9 +17,10 @@ namespace MoonWorks.Audio public float SpeedOfSound = 343.5f; internal FAudio.FAudioVoiceSends ReverbSends; - private readonly List> streamingSounds = new List>(); + private bool IsDisposed; + public unsafe AudioDevice() { FAudio.FAudioCreate(out var handle, 0, 0); @@ -214,5 +215,42 @@ namespace MoonWorks.Audio { streamingSounds.Add(new WeakReference(instance)); } + + protected virtual void Dispose(bool disposing) + { + if (!IsDisposed) + { + if (disposing) + { + // TODO: dispose managed state (managed objects) + foreach (var weakReference in streamingSounds) + { + if (weakReference.TryGetTarget(out var streamingSound)) + { + streamingSound.Dispose(); + } + } + streamingSounds.Clear(); + } + + FAudio.FAudio_Release(Handle); + + IsDisposed = true; + } + } + + // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources + ~AudioDevice() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: false); + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } } } diff --git a/src/Audio/SoundInstance.cs b/src/Audio/SoundInstance.cs index 0f007793..7514f1a2 100644 --- a/src/Audio/SoundInstance.cs +++ b/src/Audio/SoundInstance.cs @@ -228,6 +228,10 @@ namespace MoonWorks.Audio State = SoundState.Stopped; } + public abstract void Play(); + public abstract void Pause(); + public abstract void Stop(bool immediate); + private void InitDSPSettings(uint srcChannels) { dspSettings = new FAudio.F3DAUDIO_DSP_SETTINGS(); @@ -314,6 +318,7 @@ namespace MoonWorks.Audio if (disposing) { // dispose managed state (managed objects) + Stop(true); } FAudio.FAudioVoice_DestroyVoice(Handle); diff --git a/src/Audio/StaticSoundInstance.cs b/src/Audio/StaticSoundInstance.cs index c5142044..646adc59 100644 --- a/src/Audio/StaticSoundInstance.cs +++ b/src/Audio/StaticSoundInstance.cs @@ -40,7 +40,7 @@ namespace MoonWorks.Audio Parent = parent; } - public void Play() + public override void Play() { if (State == SoundState.Playing) { @@ -70,7 +70,7 @@ namespace MoonWorks.Audio State = SoundState.Playing; } - public void Pause() + public override void Pause() { if (State == SoundState.Paused) { @@ -79,7 +79,7 @@ namespace MoonWorks.Audio } } - public void Stop(bool immediate = true) + public override void Stop(bool immediate = true) { if (immediate) { diff --git a/src/Audio/StreamingSound.cs b/src/Audio/StreamingSound.cs index df2c7659..3909cad3 100644 --- a/src/Audio/StreamingSound.cs +++ b/src/Audio/StreamingSound.cs @@ -5,7 +5,7 @@ using System.Runtime.InteropServices; namespace MoonWorks.Audio { /// - /// For streaming long playback. + /// For streaming long playback. /// Can be extended to support custom decoders. /// public abstract class StreamingSound : SoundInstance @@ -26,7 +26,7 @@ namespace MoonWorks.Audio bool loop ) : base(device, channels, samplesPerSecond, is3D, loop) { } - public void Play() + public override void Play() { if (State == SoundState.Playing) { @@ -38,7 +38,7 @@ namespace MoonWorks.Audio FAudio.FAudioSourceVoice_Start(Handle, 0, 0); } - public void Pause() + public override void Pause() { if (State == SoundState.Playing) { @@ -47,7 +47,7 @@ namespace MoonWorks.Audio } } - public void Stop(bool immediate = true) + public override void Stop(bool immediate = true) { if (immediate) { @@ -110,8 +110,8 @@ namespace MoonWorks.Audio protected void AddBuffer() { AddBuffer( - out var buffer, - out var bufferOffset, + out var buffer, + out var bufferOffset, out var bufferLength, out var reachedEnd ); diff --git a/src/Graphics/GraphicsDevice.cs b/src/Graphics/GraphicsDevice.cs index 1975ccb0..d0bfabfb 100644 --- a/src/Graphics/GraphicsDevice.cs +++ b/src/Graphics/GraphicsDevice.cs @@ -12,7 +12,7 @@ namespace MoonWorks.Graphics private readonly Queue commandBufferPool; - private readonly List resources = new List(); + private readonly List> resources = new List>(); public GraphicsDevice( IntPtr deviceWindowHandle, @@ -80,7 +80,7 @@ namespace MoonWorks.Graphics Refresh.Refresh_Wait(Handle); } - internal void AddResourceReference(WeakReference resourceReference) + internal void AddResourceReference(WeakReference resourceReference) { lock (resources) { @@ -88,7 +88,7 @@ namespace MoonWorks.Graphics } } - internal void RemoveResourceReference(WeakReference resourceReference) + internal void RemoveResourceReference(WeakReference resourceReference) { lock (resources) { @@ -106,10 +106,9 @@ namespace MoonWorks.Graphics { foreach (var resource in resources) { - var target = resource.Target; - if (target != null) + if (resource.TryGetTarget(out var target)) { - (target as IDisposable).Dispose(); + target.Dispose(); } } resources.Clear(); diff --git a/src/Graphics/GraphicsResource.cs b/src/Graphics/GraphicsResource.cs index 0dfcba88..d35183c8 100644 --- a/src/Graphics/GraphicsResource.cs +++ b/src/Graphics/GraphicsResource.cs @@ -10,13 +10,13 @@ namespace MoonWorks.Graphics public bool IsDisposed { get; private set; } protected abstract Action QueueDestroyFunction { get; } - private WeakReference selfReference; + private WeakReference selfReference; public GraphicsResource(GraphicsDevice device) { Device = device; - selfReference = new WeakReference(this); + selfReference = new WeakReference(this); Device.AddResourceReference(selfReference); }