AudioManager.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. //-----------------------------------------------------------------------------
  2. // AudioManager.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System.Collections.Generic;
  8. using Microsoft.Xna.Framework;
  9. using Microsoft.Xna.Framework.Audio;
  10. namespace Audio3D
  11. {
  12. /// <summary>
  13. /// Audio manager keeps track of what 3D sounds are playing, updating
  14. /// their settings as the camera and entities move around the world, and
  15. /// automatically disposing sound effect instances after they finish playing.
  16. /// </summary>
  17. public class AudioManager : Microsoft.Xna.Framework.GameComponent
  18. {
  19. // List of all the sound effects that will be loaded into this manager.
  20. static string[] soundNames =
  21. {
  22. "CatSound0",
  23. "CatSound1",
  24. "CatSound2",
  25. "DogSound",
  26. };
  27. // The listener describes the ear which is hearing 3D sounds.
  28. // This is usually set to match the camera.
  29. public AudioListener Listener
  30. {
  31. get { return listener; }
  32. }
  33. AudioListener listener = new AudioListener();
  34. // The emitter describes an entity which is making a 3D sound.
  35. AudioEmitter emitter = new AudioEmitter();
  36. // Store all the sound effects that are available to be played.
  37. Dictionary<string, SoundEffect> soundEffects = new Dictionary<string, SoundEffect>();
  38. // Keep track of all the 3D sounds that are currently playing.
  39. List<ActiveSound> activeSounds = new List<ActiveSound>();
  40. public AudioManager(Game game)
  41. : base(game)
  42. { }
  43. /// <summary>
  44. /// Initializes the audio manager.
  45. /// </summary>
  46. public override void Initialize()
  47. {
  48. // Set the scale for 3D audio so it matches the scale of our game world.
  49. // DistanceScale controls how much sounds change volume as you move further away.
  50. // DopplerScale controls how much sounds change pitch as you move past them.
  51. SoundEffect.DistanceScale = 2000;
  52. SoundEffect.DopplerScale = 0.1f;
  53. // Load all the sound effects.
  54. foreach (string soundName in soundNames)
  55. {
  56. soundEffects.Add(soundName, Game.Content.Load<SoundEffect>(soundName));
  57. }
  58. base.Initialize();
  59. }
  60. /// <summary>
  61. /// Unloads the sound effect data.
  62. /// </summary>
  63. protected override void Dispose(bool disposing)
  64. {
  65. try
  66. {
  67. if (disposing)
  68. {
  69. foreach (SoundEffect soundEffect in soundEffects.Values)
  70. {
  71. soundEffect.Dispose();
  72. }
  73. soundEffects.Clear();
  74. }
  75. }
  76. finally
  77. {
  78. base.Dispose(disposing);
  79. }
  80. }
  81. /// <summary>
  82. /// Updates the state of the 3D audio system.
  83. /// </summary>
  84. public override void Update(GameTime gameTime)
  85. {
  86. // Loop over all the currently playing 3D sounds.
  87. int index = 0;
  88. while (index < activeSounds.Count)
  89. {
  90. ActiveSound activeSound = activeSounds[index];
  91. if (activeSound.Instance.State == SoundState.Stopped)
  92. {
  93. // If the sound has stopped playing, dispose it.
  94. activeSound.Instance.Dispose();
  95. // Remove it from the active list.
  96. activeSounds.RemoveAt(index);
  97. }
  98. else
  99. {
  100. // If the sound is still playing, update its 3D settings.
  101. Apply3D(activeSound);
  102. index++;
  103. }
  104. }
  105. base.Update(gameTime);
  106. }
  107. /// <summary>
  108. /// Triggers a new 3D sound.
  109. /// </summary>
  110. public SoundEffectInstance Play3DSound(string soundName, bool isLooped, IAudioEmitter emitter)
  111. {
  112. ActiveSound activeSound = new ActiveSound();
  113. // Fill in the instance and emitter fields.
  114. activeSound.Instance = soundEffects[soundName].CreateInstance();
  115. activeSound.Instance.IsLooped = isLooped;
  116. activeSound.Emitter = emitter;
  117. // Set the 3D position of this sound, and then play it.
  118. Apply3D(activeSound);
  119. activeSound.Instance.Play();
  120. // Remember that this sound is now active.
  121. activeSounds.Add(activeSound);
  122. return activeSound.Instance;
  123. }
  124. /// <summary>
  125. /// Updates the position and velocity settings of a 3D sound.
  126. /// </summary>
  127. private void Apply3D(ActiveSound activeSound)
  128. {
  129. emitter.Position = activeSound.Emitter.Position;
  130. emitter.Forward = activeSound.Emitter.Forward;
  131. emitter.Up = activeSound.Emitter.Up;
  132. emitter.Velocity = activeSound.Emitter.Velocity;
  133. activeSound.Instance.Apply3D(listener, emitter);
  134. }
  135. /// <summary>
  136. /// Internal helper class for keeping track of an active 3D sound,
  137. /// and remembering which emitter object it is attached to.
  138. /// </summary>
  139. private class ActiveSound
  140. {
  141. public SoundEffectInstance Instance;
  142. public IAudioEmitter Emitter;
  143. }
  144. }
  145. }