forked from MoonsideGames/MoonWorks
initial 3D audio implementation
parent
7cc14ea819
commit
5eb5027bf1
|
@ -17,6 +17,8 @@ namespace MoonWorks.Audio
|
||||||
public float SpeedOfSound = 343.5f;
|
public float SpeedOfSound = 343.5f;
|
||||||
|
|
||||||
internal FAudio.FAudioVoiceSends ReverbSends;
|
internal FAudio.FAudioVoiceSends ReverbSends;
|
||||||
|
|
||||||
|
private readonly List<WeakReference<AudioResource>> resources = new List<WeakReference<AudioResource>>();
|
||||||
private readonly List<WeakReference<StreamingSound>> streamingSounds = new List<WeakReference<StreamingSound>>();
|
private readonly List<WeakReference<StreamingSound>> streamingSounds = new List<WeakReference<StreamingSound>>();
|
||||||
|
|
||||||
private bool IsDisposed;
|
private bool IsDisposed;
|
||||||
|
@ -216,6 +218,22 @@ namespace MoonWorks.Audio
|
||||||
streamingSounds.Add(new WeakReference<StreamingSound>(instance));
|
streamingSounds.Add(new WeakReference<StreamingSound>(instance));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void AddResourceReference(WeakReference<AudioResource> resourceReference)
|
||||||
|
{
|
||||||
|
lock (resources)
|
||||||
|
{
|
||||||
|
resources.Add(resourceReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RemoveResourceReference(WeakReference<AudioResource> resourceReference)
|
||||||
|
{
|
||||||
|
lock (resources)
|
||||||
|
{
|
||||||
|
resources.Remove(resourceReference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (!IsDisposed)
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using MoonWorks.Math;
|
||||||
|
|
||||||
|
namespace MoonWorks.Audio
|
||||||
|
{
|
||||||
|
public class AudioEmitter : AudioResource
|
||||||
|
{
|
||||||
|
internal FAudio.F3DAUDIO_EMITTER emitterData;
|
||||||
|
|
||||||
|
public float DopplerScale
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return emitterData.DopplerScaler;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value < 0.0f)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("AudioEmitter.DopplerScale must be greater than or equal to 0.0f");
|
||||||
|
}
|
||||||
|
emitterData.DopplerScaler = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Forward
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
emitterData.OrientFront.x,
|
||||||
|
emitterData.OrientFront.y,
|
||||||
|
-emitterData.OrientFront.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
emitterData.OrientFront.x = value.X;
|
||||||
|
emitterData.OrientFront.y = value.Y;
|
||||||
|
emitterData.OrientFront.z = -value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
emitterData.Position.x,
|
||||||
|
emitterData.Position.y,
|
||||||
|
-emitterData.Position.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
emitterData.Position.x = value.X;
|
||||||
|
emitterData.Position.y = value.Y;
|
||||||
|
emitterData.Position.z = -value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Vector3 Up
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
emitterData.OrientTop.x,
|
||||||
|
emitterData.OrientTop.y,
|
||||||
|
-emitterData.OrientTop.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
emitterData.OrientTop.x = value.X;
|
||||||
|
emitterData.OrientTop.y = value.Y;
|
||||||
|
emitterData.OrientTop.z = -value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Velocity
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
emitterData.Velocity.x,
|
||||||
|
emitterData.Velocity.y,
|
||||||
|
-emitterData.Velocity.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
emitterData.Velocity.x = value.X;
|
||||||
|
emitterData.Velocity.y = value.Y;
|
||||||
|
emitterData.Velocity.z = -value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly float[] stereoAzimuth = new float[]
|
||||||
|
{
|
||||||
|
0.0f, 0.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
private static readonly GCHandle stereoAzimuthHandle = GCHandle.Alloc(
|
||||||
|
stereoAzimuth,
|
||||||
|
GCHandleType.Pinned
|
||||||
|
);
|
||||||
|
|
||||||
|
public AudioEmitter(AudioDevice device) : base(device)
|
||||||
|
{
|
||||||
|
emitterData = new FAudio.F3DAUDIO_EMITTER();
|
||||||
|
|
||||||
|
DopplerScale = 1f;
|
||||||
|
Forward = Vector3.Forward;
|
||||||
|
Position = Vector3.Zero;
|
||||||
|
Up = Vector3.Up;
|
||||||
|
Velocity = Vector3.Zero;
|
||||||
|
|
||||||
|
/* Unexposed variables, defaults based on XNA behavior */
|
||||||
|
emitterData.pCone = IntPtr.Zero;
|
||||||
|
emitterData.ChannelCount = 1;
|
||||||
|
emitterData.ChannelRadius = 1.0f;
|
||||||
|
emitterData.pChannelAzimuths = stereoAzimuthHandle.AddrOfPinnedObject();
|
||||||
|
emitterData.pVolumeCurve = IntPtr.Zero;
|
||||||
|
emitterData.pLFECurve = IntPtr.Zero;
|
||||||
|
emitterData.pLPFDirectCurve = IntPtr.Zero;
|
||||||
|
emitterData.pLPFReverbCurve = IntPtr.Zero;
|
||||||
|
emitterData.pReverbCurve = IntPtr.Zero;
|
||||||
|
emitterData.CurveDistanceScaler = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Destroy() { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
using System;
|
||||||
|
using MoonWorks.Math;
|
||||||
|
|
||||||
|
namespace MoonWorks.Audio
|
||||||
|
{
|
||||||
|
public class AudioListener : AudioResource
|
||||||
|
{
|
||||||
|
internal FAudio.F3DAUDIO_LISTENER listenerData;
|
||||||
|
|
||||||
|
public Vector3 Forward
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
listenerData.OrientFront.x,
|
||||||
|
listenerData.OrientFront.y,
|
||||||
|
-listenerData.OrientFront.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
listenerData.OrientFront.x = value.X;
|
||||||
|
listenerData.OrientFront.y = value.Y;
|
||||||
|
listenerData.OrientFront.z = -value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
listenerData.Position.x,
|
||||||
|
listenerData.Position.y,
|
||||||
|
-listenerData.Position.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
listenerData.Position.x = value.X;
|
||||||
|
listenerData.Position.y = value.Y;
|
||||||
|
listenerData.Position.z = -value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Vector3 Up
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
listenerData.OrientTop.x,
|
||||||
|
listenerData.OrientTop.y,
|
||||||
|
-listenerData.OrientTop.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
listenerData.OrientTop.x = value.X;
|
||||||
|
listenerData.OrientTop.y = value.Y;
|
||||||
|
listenerData.OrientTop.z = -value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3 Velocity
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Vector3(
|
||||||
|
listenerData.Velocity.x,
|
||||||
|
listenerData.Velocity.y,
|
||||||
|
-listenerData.Velocity.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
listenerData.Velocity.x = value.X;
|
||||||
|
listenerData.Velocity.y = value.Y;
|
||||||
|
listenerData.Velocity.z = -value.Z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioListener(AudioDevice device) : base(device)
|
||||||
|
{
|
||||||
|
listenerData = new FAudio.F3DAUDIO_LISTENER();
|
||||||
|
Forward = Vector3.Forward;
|
||||||
|
Position = Vector3.Zero;
|
||||||
|
Up = Vector3.Up;
|
||||||
|
Velocity = Vector3.Zero;
|
||||||
|
|
||||||
|
/* Unexposed variables, defaults based on XNA behavior */
|
||||||
|
listenerData.pCone = IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Destroy() { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace MoonWorks.Audio
|
||||||
|
{
|
||||||
|
public abstract class AudioResource : IDisposable
|
||||||
|
{
|
||||||
|
public AudioDevice Device { get; }
|
||||||
|
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
|
private WeakReference<AudioResource> selfReference;
|
||||||
|
|
||||||
|
public AudioResource(AudioDevice device)
|
||||||
|
{
|
||||||
|
Device = device;
|
||||||
|
|
||||||
|
selfReference = new WeakReference<AudioResource>(this);
|
||||||
|
Device.AddResourceReference(selfReference);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void Destroy();
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (!IsDisposed)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
|
||||||
|
if (selfReference != null)
|
||||||
|
{
|
||||||
|
Device.RemoveResourceReference(selfReference);
|
||||||
|
selfReference = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
IsDisposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~AudioResource()
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using MoonWorks.Math;
|
||||||
|
|
||||||
namespace MoonWorks.Audio
|
namespace MoonWorks.Audio
|
||||||
{
|
{
|
||||||
public abstract class SoundInstance : IDisposable
|
public abstract class SoundInstance : AudioResource
|
||||||
{
|
{
|
||||||
protected AudioDevice Device { get; }
|
|
||||||
internal IntPtr Handle { get; }
|
internal IntPtr Handle { get; }
|
||||||
internal FAudio.FAudioWaveFormatEx Format { get; }
|
internal FAudio.FAudioWaveFormatEx Format { get; }
|
||||||
public bool Loop { get; }
|
public bool Loop { get; }
|
||||||
|
@ -13,7 +13,6 @@ namespace MoonWorks.Audio
|
||||||
protected FAudio.F3DAUDIO_DSP_SETTINGS dspSettings;
|
protected FAudio.F3DAUDIO_DSP_SETTINGS dspSettings;
|
||||||
|
|
||||||
protected bool is3D;
|
protected bool is3D;
|
||||||
private bool IsDisposed;
|
|
||||||
|
|
||||||
public abstract SoundState State { get; protected set; }
|
public abstract SoundState State { get; protected set; }
|
||||||
|
|
||||||
|
@ -54,22 +53,8 @@ namespace MoonWorks.Audio
|
||||||
get => _pitch;
|
get => _pitch;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
float doppler;
|
_pitch = MathHelper.Clamp(value, -1f, 1f);
|
||||||
if (!is3D || Device.DopplerScale == 0f)
|
UpdatePitch();
|
||||||
{
|
|
||||||
doppler = 1f;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
doppler = dspSettings.DopplerFactor * Device.DopplerScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
_pitch = value;
|
|
||||||
FAudio.FAudioSourceVoice_SetFrequencyRatio(
|
|
||||||
Handle,
|
|
||||||
(float) System.Math.Pow(2.0, _pitch) * doppler,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,9 +167,8 @@ namespace MoonWorks.Audio
|
||||||
uint samplesPerSecond,
|
uint samplesPerSecond,
|
||||||
bool is3D,
|
bool is3D,
|
||||||
bool loop
|
bool loop
|
||||||
) {
|
) : base(device)
|
||||||
Device = device;
|
{
|
||||||
|
|
||||||
var blockAlign = (ushort)(4 * channels);
|
var blockAlign = (ushort)(4 * channels);
|
||||||
var format = new FAudio.FAudioWaveFormatEx
|
var format = new FAudio.FAudioWaveFormatEx
|
||||||
{
|
{
|
||||||
|
@ -228,6 +212,32 @@ namespace MoonWorks.Audio
|
||||||
State = SoundState.Stopped;
|
State = SoundState.Stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Apply3D(AudioListener listener, AudioEmitter emitter)
|
||||||
|
{
|
||||||
|
is3D = true;
|
||||||
|
|
||||||
|
emitter.emitterData.CurveDistanceScaler = Device.CurveDistanceScalar;
|
||||||
|
emitter.emitterData.ChannelCount = dspSettings.SrcChannelCount;
|
||||||
|
|
||||||
|
FAudio.F3DAudioCalculate(
|
||||||
|
Device.Handle3D,
|
||||||
|
ref listener.listenerData,
|
||||||
|
ref emitter.emitterData,
|
||||||
|
FAudio.F3DAUDIO_CALCULATE_MATRIX | FAudio.F3DAUDIO_CALCULATE_DOPPLER,
|
||||||
|
ref dspSettings
|
||||||
|
);
|
||||||
|
|
||||||
|
UpdatePitch();
|
||||||
|
FAudio.FAudioVoice_SetOutputMatrix(
|
||||||
|
Handle,
|
||||||
|
Device.MasteringVoice,
|
||||||
|
dspSettings.SrcChannelCount,
|
||||||
|
dspSettings.DstChannelCount,
|
||||||
|
dspSettings.pMatrixCoefficients,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void Play();
|
public abstract void Play();
|
||||||
public abstract void Pause();
|
public abstract void Pause();
|
||||||
public abstract void Stop(bool immediate);
|
public abstract void Stop(bool immediate);
|
||||||
|
@ -257,6 +267,26 @@ namespace MoonWorks.Audio
|
||||||
SetPanMatrixCoefficients();
|
SetPanMatrixCoefficients();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdatePitch()
|
||||||
|
{
|
||||||
|
float doppler;
|
||||||
|
float dopplerScale = Device.DopplerScale;
|
||||||
|
if (!is3D || dopplerScale == 0.0f)
|
||||||
|
{
|
||||||
|
doppler = 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
doppler = dspSettings.DopplerFactor * dopplerScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
FAudio.FAudioSourceVoice_SetFrequencyRatio(
|
||||||
|
Handle,
|
||||||
|
(float) System.Math.Pow(2.0, _pitch) * doppler,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Taken from https://github.com/FNA-XNA/FNA/blob/master/src/Audio/SoundEffectInstance.cs
|
// Taken from https://github.com/FNA-XNA/FNA/blob/master/src/Audio/SoundEffectInstance.cs
|
||||||
private unsafe void SetPanMatrixCoefficients()
|
private unsafe void SetPanMatrixCoefficients()
|
||||||
{
|
{
|
||||||
|
@ -311,33 +341,12 @@ namespace MoonWorks.Audio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected override void Destroy()
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// dispose managed state (managed objects)
|
|
||||||
Stop(true);
|
Stop(true);
|
||||||
}
|
|
||||||
|
|
||||||
FAudio.FAudioVoice_DestroyVoice(Handle);
|
FAudio.FAudioVoice_DestroyVoice(Handle);
|
||||||
Marshal.FreeHGlobal(dspSettings.pMatrixCoefficients);
|
Marshal.FreeHGlobal(dspSettings.pMatrixCoefficients);
|
||||||
IsDisposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
~SoundInstance()
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace MoonWorks.Audio
|
namespace MoonWorks.Audio
|
||||||
{
|
{
|
||||||
public class StaticSound : IDisposable
|
public class StaticSound : AudioResource
|
||||||
{
|
{
|
||||||
internal AudioDevice Device { get; }
|
|
||||||
internal FAudio.FAudioBuffer Handle;
|
internal FAudio.FAudioBuffer Handle;
|
||||||
public ushort Channels { get; }
|
public ushort Channels { get; }
|
||||||
public uint SamplesPerSecond { get; }
|
public uint SamplesPerSecond { get; }
|
||||||
|
@ -14,8 +12,6 @@ namespace MoonWorks.Audio
|
||||||
public uint LoopStart { get; set; } = 0;
|
public uint LoopStart { get; set; } = 0;
|
||||||
public uint LoopLength { get; set; } = 0;
|
public uint LoopLength { get; set; } = 0;
|
||||||
|
|
||||||
private bool IsDisposed;
|
|
||||||
|
|
||||||
public static StaticSound LoadOgg(AudioDevice device, string filePath)
|
public static StaticSound LoadOgg(AudioDevice device, string filePath)
|
||||||
{
|
{
|
||||||
var filePointer = FAudio.stb_vorbis_open_filename(filePath, out var error, IntPtr.Zero);
|
var filePointer = FAudio.stb_vorbis_open_filename(filePath, out var error, IntPtr.Zero);
|
||||||
|
@ -54,9 +50,8 @@ namespace MoonWorks.Audio
|
||||||
float[] buffer,
|
float[] buffer,
|
||||||
uint bufferOffset, /* in floats */
|
uint bufferOffset, /* in floats */
|
||||||
uint bufferLength /* in floats */
|
uint bufferLength /* in floats */
|
||||||
) {
|
) : base(device)
|
||||||
Device = device;
|
{
|
||||||
|
|
||||||
Channels = channels;
|
Channels = channels;
|
||||||
SamplesPerSecond = samplesPerSecond;
|
SamplesPerSecond = samplesPerSecond;
|
||||||
|
|
||||||
|
@ -79,32 +74,9 @@ namespace MoonWorks.Audio
|
||||||
return new StaticSoundInstance(Device, this, false, loop);
|
return new StaticSoundInstance(Device, this, false, loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected override void Destroy()
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// dispose managed state (managed objects)
|
|
||||||
}
|
|
||||||
|
|
||||||
Marshal.FreeHGlobal(Handle.pAudioData);
|
Marshal.FreeHGlobal(Handle.pAudioData);
|
||||||
IsDisposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
|
|
||||||
~StaticSound()
|
|
||||||
{
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,6 @@ namespace MoonWorks.Audio
|
||||||
|
|
||||||
public int PendingBufferCount => queuedBuffers.Count;
|
public int PendingBufferCount => queuedBuffers.Count;
|
||||||
|
|
||||||
private bool IsDisposed;
|
|
||||||
|
|
||||||
public StreamingSound(
|
public StreamingSound(
|
||||||
AudioDevice device,
|
AudioDevice device,
|
||||||
ushort channels,
|
ushort channels,
|
||||||
|
@ -172,21 +170,9 @@ namespace MoonWorks.Audio
|
||||||
|
|
||||||
protected abstract void SeekStart();
|
protected abstract void SeekStart();
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Destroy()
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// dispose managed state (managed objects)
|
|
||||||
Stop(true);
|
Stop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dispose unmanaged state
|
|
||||||
IsDisposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@ namespace MoonWorks.Audio
|
||||||
|
|
||||||
public override SoundState State { get; protected set; }
|
public override SoundState State { get; protected set; }
|
||||||
|
|
||||||
private bool IsDisposed;
|
|
||||||
|
|
||||||
public static StreamingSoundOgg Load(
|
public static StreamingSoundOgg Load(
|
||||||
AudioDevice device,
|
AudioDevice device,
|
||||||
string filePath,
|
string filePath,
|
||||||
|
@ -83,22 +81,9 @@ namespace MoonWorks.Audio
|
||||||
FAudio.stb_vorbis_seek_start(FileHandle);
|
FAudio.stb_vorbis_seek_start(FileHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Destroy()
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
|
||||||
{
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
// dispose managed state (managed objects)
|
|
||||||
}
|
|
||||||
|
|
||||||
// dispose unmanaged state
|
|
||||||
FAudio.stb_vorbis_close(FileHandle);
|
FAudio.stb_vorbis_close(FileHandle);
|
||||||
|
|
||||||
IsDisposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue