Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
File last commit:
Show/Diff file:
Action:
FNA/src/Audio/SoundBank.cs
282 lines | 5.0 KiB | text/x-csharp | CSharpLexer
#region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
* Copyright 2009-2020 Ethan Lee and the MonoGame Team
*
* Released under the Microsoft Public License.
* See LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.Runtime.InteropServices;
#endregion
namespace Microsoft.Xna.Framework.Audio
{
// http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.audio.soundbank.aspx
public class SoundBank : IDisposable
{
#region Public Properties
public bool IsDisposed
{
get;
private set;
}
public bool IsInUse
{
get
{
uint state;
FAudio.FACTSoundBank_GetState(handle, out state);
return (state & FAudio.FACT_STATE_INUSE) != 0;
}
}
#endregion
#region Internal Variables
internal AudioEngine engine;
internal FAudio.F3DAUDIO_DSP_SETTINGS dspSettings;
#endregion
#region Private Variables
private IntPtr handle;
private WeakReference selfReference;
#endregion
#region Disposing Event
public event EventHandler<EventArgs> Disposing;
#endregion
#region Public Constructor
public SoundBank(AudioEngine audioEngine, string filename)
{
if (audioEngine == null)
{
throw new ArgumentNullException("audioEngine");
}
if (String.IsNullOrEmpty(filename))
{
throw new ArgumentNullException("filename");
}
byte[] buffer = TitleContainer.ReadAllBytes(filename);
GCHandle pin = GCHandle.Alloc(buffer, GCHandleType.Pinned);
FAudio.FACTAudioEngine_CreateSoundBank(
audioEngine.handle,
pin.AddrOfPinnedObject(),
(uint) buffer.Length,
0,
0,
out handle
);
pin.Free();
buffer = null;
engine = audioEngine;
selfReference = new WeakReference(this, true);
dspSettings = new FAudio.F3DAUDIO_DSP_SETTINGS();
dspSettings.SrcChannelCount = 1;
dspSettings.DstChannelCount = engine.channels;
dspSettings.pMatrixCoefficients = Marshal.AllocHGlobal(
4 *
(int) dspSettings.SrcChannelCount *
(int) dspSettings.DstChannelCount
);
engine.RegisterSoundBank(handle, selfReference);
IsDisposed = false;
}
#endregion
#region Destructor
~SoundBank()
{
if (AudioEngine.ProgramExiting)
{
return;
}
if (!IsDisposed && IsInUse)
{
// STOP LEAKING YOUR BANKS, ARGH
GC.ReRegisterForFinalize(this);
return;
}
Dispose(false);
}
#endregion
#region Public Dispose Method
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
#region Protected Dispose Method
protected void Dispose(bool disposing)
{
lock (engine.gcSync)
{
if (!IsDisposed)
{
if (Disposing != null)
{
Disposing.Invoke(this, null);
}
// If this is disposed, stop leaking memory!
if (!engine.IsDisposed)
{
engine.UnregisterSoundBank(handle);
FAudio.FACTSoundBank_Destroy(handle);
Marshal.FreeHGlobal(dspSettings.pMatrixCoefficients);
}
OnSoundBankDestroyed();
}
}
}
#endregion
#region Public Methods
public Cue GetCue(string name)
{
if (String.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
ushort cue = FAudio.FACTSoundBank_GetCueIndex(
handle,
name
);
if (cue == FAudio.FACTINDEX_INVALID)
{
throw new InvalidOperationException(
"Invalid cue name!"
);
}
IntPtr result;
FAudio.FACTSoundBank_Prepare(
handle,
cue,
0,
0,
out result
);
return new Cue(result, name, this);
}
public void PlayCue(string name)
{
if (String.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
ushort cue = FAudio.FACTSoundBank_GetCueIndex(
handle,
name
);
if (cue == FAudio.FACTINDEX_INVALID)
{
throw new InvalidOperationException(
"Invalid cue name!"
);
}
FAudio.FACTSoundBank_Play(
handle,
cue,
0,
0,
IntPtr.Zero
);
}
public void PlayCue(
string name,
AudioListener listener,
AudioEmitter emitter
) {
if (String.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
if (listener == null)
{
throw new ArgumentNullException("listener");
}
if (emitter == null)
{
throw new ArgumentNullException("emitter");
}
ushort cue = FAudio.FACTSoundBank_GetCueIndex(
handle,
name
);
if (cue == FAudio.FACTINDEX_INVALID)
{
throw new InvalidOperationException(
"Invalid cue name!"
);
}
emitter.emitterData.ChannelCount = dspSettings.SrcChannelCount;
emitter.emitterData.CurveDistanceScaler = float.MaxValue;
FAudio.FACT3DCalculate(
engine.handle3D,
ref listener.listenerData,
ref emitter.emitterData,
ref dspSettings
);
FAudio.FACTSoundBank_Play3D(
handle,
cue,
0,
0,
ref dspSettings,
IntPtr.Zero
);
}
#endregion
#region Internal Methods
internal void OnSoundBankDestroyed()
{
IsDisposed = true;
handle = IntPtr.Zero;
selfReference = null;
}
#endregion
}
}