diff --git a/MLEM/Misc/SoundEffectInfo.cs b/MLEM/Misc/SoundEffectInfo.cs
index ad923ef..1a4d649 100644
--- a/MLEM/Misc/SoundEffectInfo.cs
+++ b/MLEM/Misc/SoundEffectInfo.cs
@@ -1,3 +1,7 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
@@ -25,8 +29,6 @@ namespace MLEM.Misc {
///
public float Pan;
- private AudioEmitter emitter;
-
///
/// Creates a new sound effect info with the given values.
///
@@ -49,33 +51,6 @@ namespace MLEM.Misc {
return this.Sound.Play(this.Volume, this.Pitch, this.Pan);
}
- ///
- /// Plays this info's once, with 3d positioning applied, to the given .
- /// The required is automatically created and cached for future use.
- ///
- /// Data about the listener
- /// The position to play the sound at
- /// Whether to loop the sound effect instance
- /// The emitter's doppler scale, defaults to 1
- /// The emitter's forward vector, defaults to
- /// The emitter's up vector, defaults to
- /// The emitter's velocity, defaults to
- public SoundEffectInstance Play3D(AudioListener listener, Vector3 pos, bool loop = false, float? dopplerScale = null, Vector3? forward = null, Vector3? up = null, Vector3? velocity = null) {
- if (this.emitter == null)
- this.emitter = new AudioEmitter();
- this.emitter.Position = pos;
- this.emitter.DopplerScale = dopplerScale ?? 1;
- this.emitter.Forward = forward ?? Vector3.Forward;
- this.emitter.Up = up ?? Vector3.Up;
- this.emitter.Velocity = velocity ?? Vector3.Zero;
-
- var inst = this.CreateInstance();
- inst.IsLooped = loop;
- inst.Apply3D(listener, this.emitter);
- inst.Play();
- return inst;
- }
-
///
/// Creates a new with this sound effect info's data.
///
@@ -89,4 +64,99 @@ namespace MLEM.Misc {
}
}
+
+ ///
+ /// A simple class that handles automatically removing and disposing objects once they are done playing to free up the audio source for new sounds.
+ /// Additionally, a callback can be registered that is invoked when the finishes playing.
+ /// Note that an object of this class can be added to a using .
+ ///
+ public class SoundEffectInstanceHandler : GameComponent, IEnumerable {
+
+ private readonly List playingSounds = new List();
+
+ ///
+ /// Creates a new sound effect instance handler with the given settings
+ ///
+ /// The game instance
+ public SoundEffectInstanceHandler(Game game) : base(game) {
+ }
+
+ ///
+ public override void Update(GameTime gameTime) {
+ this.Update();
+ }
+
+ ///
+ /// Updates this sound effect handler and manages all of the objects in it.
+ /// This should be called each update frame.
+ ///
+ public void Update() {
+ for (var i = this.playingSounds.Count - 1; i >= 0; i--) {
+ var entry = this.playingSounds[i];
+ if (entry.Instance.IsDisposed || entry.Instance.State == SoundState.Stopped) {
+ entry.Instance.Stop(true);
+ entry.OnStopped?.Invoke(entry.Instance);
+ this.playingSounds.RemoveAt(i);
+ }
+ }
+ }
+
+ ///
+ /// Adds a new to this handler.
+ /// This also starts playing the instance.
+ ///
+ /// The instance to add
+ /// The function that should be invoked when this instance stops playing, defaults to null
+ /// The passed instance, for chaining
+ public SoundEffectInstance Add(SoundEffectInstance instance, Action onStopped = null) {
+ this.playingSounds.Add(new Entry(instance, onStopped));
+ instance.Play();
+ return instance;
+ }
+
+ ///
+ /// Adds a new to this handler.
+ /// This also starts playing the created instance.
+ ///
+ /// The info for which to add a
+ /// The function that should be invoked when this instance stops playing, defaults to null
+ /// The newly created
+ public SoundEffectInstance Add(SoundEffectInfo info, Action onStopped = null) {
+ return this.Add(info.CreateInstance(), onStopped);
+ }
+
+ ///
+ /// Adds a new to this handler.
+ /// This also starts playing the created instance.
+ ///
+ /// The sound for which to add a
+ /// The function that should be invoked when this instance stops playing, defaults to null
+ /// The newly created
+ public SoundEffectInstance Add(SoundEffect effect, Action onStopped = null) {
+ return this.Add(effect.CreateInstance(), onStopped);
+ }
+
+ ///
+ public IEnumerator GetEnumerator() {
+ foreach (var sound in this.playingSounds)
+ yield return sound.Instance;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return this.GetEnumerator();
+ }
+
+ private readonly struct Entry {
+
+ public readonly SoundEffectInstance Instance;
+ public readonly Action OnStopped;
+
+ public Entry(SoundEffectInstance instance, Action onStopped) {
+ this.Instance = instance;
+ this.OnStopped = onStopped;
+ }
+
+ }
+
+ }
}
\ No newline at end of file