/flixel/FlxSound.cs

http://github.com/StAidan/X-flixel · C# · 313 lines · 219 code · 26 blank · 68 comment · 40 complexity · 48b0ca473c9b3d0a4950c9a0f2951dd7 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Audio;
  5. namespace org.flixel
  6. {
  7. public class FlxSound : FlxObject
  8. {
  9. /**
  10. * Whether or not this sound should be automatically destroyed when you switch states.
  11. */
  12. public bool survive;
  13. /**
  14. * Whether the sound is currently playing or not.
  15. */
  16. public bool playing;
  17. protected bool _init;
  18. protected SoundEffectInstance _sound;
  19. protected float _position;
  20. protected float _volume;
  21. protected float _volumeAdjust;
  22. protected bool _looped
  23. {
  24. get { if (_sound == null) return false; return _sound.IsLooped; }
  25. set { if (_sound != null) _sound.IsLooped = value; }
  26. }
  27. protected FlxObject _core;
  28. protected float _radius;
  29. protected bool _pan;
  30. protected float _fadeOutTimer;
  31. protected float _fadeOutTotal;
  32. protected bool _pauseOnFadeOut;
  33. protected float _fadeInTimer;
  34. protected float _fadeInTotal;
  35. protected Vector2 _point2;
  36. public FlxSound()
  37. {
  38. @fixed = true; //no movement usually
  39. }
  40. /**
  41. * An internal function for clearing all the variables used by sounds.
  42. */
  43. protected void init()
  44. {
  45. _sound = null;
  46. _position = 0;
  47. _volume = 1.0f;
  48. _volumeAdjust = 1.0f;
  49. _looped = false;
  50. _core = null;
  51. _radius = 0;
  52. _pan = false;
  53. _fadeOutTimer = 0;
  54. _fadeOutTotal = 0;
  55. _pauseOnFadeOut = false;
  56. _fadeInTimer = 0;
  57. _fadeInTotal = 0;
  58. active = false;
  59. visible = false;
  60. solid = false;
  61. playing = false;
  62. }
  63. /**
  64. * One of two main setup functions for sounds, this function loads a sound from an embedded MP3.
  65. *
  66. * @param EmbeddedSound An embedded Class object representing an MP3 file.
  67. * @param Looped Whether or not this sound should loop endlessly.
  68. *
  69. * @return This <code>FlxSound</code> instance (nice for chaining stuff together, if you're into that).
  70. */
  71. public FlxSound loadEmbedded(string EmbeddedSound, bool Looped)
  72. {
  73. stop();
  74. init();
  75. _sound = FlxSoundManager.getSound(EmbeddedSound);
  76. //NOTE: can't pull ID3 info from embedded sound currently
  77. _looped = Looped;
  78. updateTransform();
  79. active = true;
  80. return this;
  81. }
  82. /**
  83. * Call this function if you want this sound's volume to change
  84. * based on distance from a particular FlxCore object.
  85. *
  86. * @param X The X position of the sound.
  87. * @param Y The Y position of the sound.
  88. * @param Core The object you want to track.
  89. * @param Radius The maximum distance this sound can travel.
  90. *
  91. * @return This FlxSound instance (nice for chaining stuff together, if you're into that).
  92. */
  93. public FlxSound proximity(float X, float Y, FlxObject Core, float Radius)
  94. {
  95. return proximity(X,Y,Core,Radius,true);
  96. }
  97. public FlxSound proximity(float X, float Y, FlxObject Core, float Radius, bool Pan)
  98. {
  99. x = X;
  100. y = Y;
  101. _core = Core;
  102. _radius = Radius;
  103. _pan = Pan;
  104. return this;
  105. }
  106. /**
  107. * Call this function to play the sound.
  108. */
  109. public void play()
  110. {
  111. if (_sound == null) return;
  112. _sound.Play();
  113. playing = true;
  114. active = true;
  115. _position = 0;
  116. }
  117. /**
  118. * Call this function to pause this sound.
  119. */
  120. public void pause()
  121. {
  122. if (_sound == null) return;
  123. _sound.Pause();
  124. playing = false;
  125. }
  126. /**
  127. * Call this function to stop this sound.
  128. */
  129. public void stop()
  130. {
  131. _position = 0;
  132. playing = false;
  133. active = false;
  134. if (_sound == null) return;
  135. _sound.Stop();
  136. }
  137. /**
  138. * Call this function to make this sound fade out over a certain time interval.
  139. *
  140. * @param Seconds The amount of time the fade out operation should take.
  141. * @param PauseInstead Tells the sound to pause on fadeout, instead of stopping.
  142. */
  143. public void fadeOut(float Seconds)
  144. {
  145. fadeOut(Seconds, false);
  146. }
  147. public void fadeOut(float Seconds, bool PauseInstead)
  148. {
  149. _pauseOnFadeOut = PauseInstead;
  150. _fadeInTimer = 0;
  151. _fadeOutTimer = Seconds;
  152. _fadeOutTotal = _fadeOutTimer;
  153. }
  154. /**
  155. * Call this function to make a sound fade in over a certain
  156. * time interval (calls <code>play()</code> automatically).
  157. *
  158. * @param Seconds The amount of time the fade-in operation should take.
  159. */
  160. public void fadeIn(float Seconds)
  161. {
  162. _fadeOutTimer = 0;
  163. _fadeInTimer = Seconds;
  164. _fadeInTotal = _fadeInTimer;
  165. play();
  166. }
  167. /**
  168. * Set <code>volume</code> to a value between 0 and 1 to change how loud this sound is.
  169. */
  170. public float volume
  171. {
  172. get { return _volume; }
  173. set
  174. {
  175. _volume = value;
  176. if (_volume < 0)
  177. _volume = 0;
  178. else if (_volume > 1)
  179. _volume = 1;
  180. updateTransform();
  181. }
  182. }
  183. /**
  184. * Internal function that performs the actual logical updates to the sound object.
  185. * Doesn't do much except optional proximity and fade calculations.
  186. */
  187. protected void updateSound()
  188. {
  189. if(_position != 0)
  190. return;
  191. float radial = 1.0f;
  192. float fade = 1.0f;
  193. if (_sound.State != SoundState.Playing)
  194. {
  195. active = false;
  196. }
  197. //Distance-based volume control
  198. if(_core != null)
  199. {
  200. Vector2 _point = new Vector2();
  201. Vector2 _point2 = new Vector2();
  202. _point = _core.getScreenXY();
  203. _point2 = getScreenXY();
  204. float dx = _point.X - _point2.X;
  205. float dy = _point.Y - _point2.Y;
  206. radial = (float)(_radius - Math.Sqrt(dx*dx + dy*dy))/_radius;
  207. if(radial < 0) radial = 0;
  208. if(radial > 1) radial = 1;
  209. if(_pan)
  210. {
  211. float d = -dx/_radius;
  212. if(d < -1) d = -1;
  213. else if(d > 1) d = 1;
  214. if (_sound != null)
  215. {
  216. _sound.Pan = d;
  217. }
  218. }
  219. }
  220. //Cross-fading volume control
  221. if(_fadeOutTimer > 0)
  222. {
  223. _fadeOutTimer -= FlxG.elapsed;
  224. if(_fadeOutTimer <= 0)
  225. {
  226. if(_pauseOnFadeOut)
  227. pause();
  228. else
  229. stop();
  230. }
  231. fade = _fadeOutTimer/_fadeOutTotal;
  232. if(fade < 0) fade = 0;
  233. }
  234. else if(_fadeInTimer > 0)
  235. {
  236. _fadeInTimer -= FlxG.elapsed;
  237. fade = _fadeInTimer/_fadeInTotal;
  238. if(fade < 0) fade = 0;
  239. fade = 1 - fade;
  240. }
  241. _volumeAdjust = radial*fade;
  242. updateTransform();
  243. }
  244. /**
  245. * The basic game loop update function. Just calls <code>updateSound()</code>.
  246. */
  247. override public void update()
  248. {
  249. base.update();
  250. updateSound();
  251. }
  252. /**
  253. * The basic class destructor, stops the music and removes any leftover events.
  254. */
  255. override public void destroy()
  256. {
  257. if(active)
  258. stop();
  259. }
  260. /**
  261. * An internal function used to help organize and change the volume of the sound.
  262. */
  263. internal void updateTransform()
  264. {
  265. if (_sound == null)
  266. return;
  267. _sound.Volume = FlxG.getMuteValue() * FlxG.volume * _volume * _volumeAdjust;
  268. }
  269. }
  270. public static class FlxSoundManager
  271. {
  272. private static List<SoundEffect> _sounds = new List<SoundEffect>();
  273. public static SoundEffectInstance getSound(string EmbeddedSound)
  274. {
  275. for (int i = 0; i < _sounds.Count; i++)
  276. {
  277. if (_sounds[i].Name.CompareTo(EmbeddedSound) == 0)
  278. {
  279. return _sounds[i].CreateInstance();
  280. }
  281. }
  282. _sounds.Add(FlxG.Content.Load<SoundEffect>(EmbeddedSound));
  283. _sounds[_sounds.Count - 1].Name = EmbeddedSound;
  284. return _sounds[_sounds.Count - 1].CreateInstance();
  285. }
  286. }
  287. }