#region File Description //----------------------------------------------------------------------------- // AudioManager.cs // // Microsoft XNA Community Game Platform // Copyright (C) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- #endregion #region Using Statements using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; #endregion namespace Audio3D { /// /// Audio manager keeps track of what 3D sounds are playing, updating /// their settings as the camera and entities move around the world, and /// automatically disposing sound effect instances after they finish playing. /// public class AudioManager : Microsoft.Xna.Framework.GameComponent { #region Fields // List of all the sound effects that will be loaded into this manager. static string[] soundNames = { "CatSound0", "CatSound1", "CatSound2", "DogSound", }; // The listener describes the ear which is hearing 3D sounds. // This is usually set to match the camera. public AudioListener Listener { get { return listener; } } AudioListener listener = new AudioListener(); // The emitter describes an entity which is making a 3D sound. AudioEmitter emitter = new AudioEmitter(); // Store all the sound effects that are available to be played. Dictionary soundEffects = new Dictionary(); // Keep track of all the 3D sounds that are currently playing. List activeSounds = new List(); #endregion public AudioManager(Game game) : base(game) { } /// /// Initializes the audio manager. /// public override void Initialize() { // Set the scale for 3D audio so it matches the scale of our game world. // DistanceScale controls how much sounds change volume as you move further away. // DopplerScale controls how much sounds change pitch as you move past them. SoundEffect.DistanceScale = 2000; SoundEffect.DopplerScale = 0.1f; // Load all the sound effects. foreach (string soundName in soundNames) { soundEffects.Add(soundName, Game.Content.Load(soundName)); } base.Initialize(); } /// /// Unloads the sound effect data. /// protected override void Dispose(bool disposing) { try { if (disposing) { foreach (SoundEffect soundEffect in soundEffects.Values) { soundEffect.Dispose(); } soundEffects.Clear(); } } finally { base.Dispose(disposing); } } /// /// Updates the state of the 3D audio system. /// public override void Update(GameTime gameTime) { // Loop over all the currently playing 3D sounds. int index = 0; while (index < activeSounds.Count) { ActiveSound activeSound = activeSounds[index]; if (activeSound.Instance.State == SoundState.Stopped) { // If the sound has stopped playing, dispose it. activeSound.Instance.Dispose(); // Remove it from the active list. activeSounds.RemoveAt(index); } else { // If the sound is still playing, update its 3D settings. Apply3D(activeSound); index++; } } base.Update(gameTime); } /// /// Triggers a new 3D sound. /// public SoundEffectInstance Play3DSound(string soundName, bool isLooped, IAudioEmitter emitter) { ActiveSound activeSound = new ActiveSound(); // Fill in the instance and emitter fields. activeSound.Instance = soundEffects[soundName].CreateInstance(); activeSound.Instance.IsLooped = isLooped; activeSound.Emitter = emitter; // Set the 3D position of this sound, and then play it. Apply3D(activeSound); activeSound.Instance.Play(); // Remember that this sound is now active. activeSounds.Add(activeSound); return activeSound.Instance; } /// /// Updates the position and velocity settings of a 3D sound. /// private void Apply3D(ActiveSound activeSound) { emitter.Position = activeSound.Emitter.Position; emitter.Forward = activeSound.Emitter.Forward; emitter.Up = activeSound.Emitter.Up; emitter.Velocity = activeSound.Emitter.Velocity; activeSound.Instance.Apply3D(listener, emitter); } /// /// Internal helper class for keeping track of an active 3D sound, /// and remembering which emitter object it is attached to. /// private class ActiveSound { public SoundEffectInstance Instance; public IAudioEmitter Emitter; } } }