//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Engine.Audio { #region Using Statements using System; using System.Collections.Generic; using System.Diagnostics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using System.Xml; #endregion using Globals; using Physics; using GameObjects; #region Game Audio /// /// Supports 2D and 3D audio. /// Functions are named after the effect they use in simple functions that /// wrap the audio file name, making it easy to change sounds that are /// scattered throughout the engine by changing a single reference. /// public static class Audio { #region Properties /// /// XNA audio engine API /// static AudioEngine audioEngine; /// /// Background Music /// static WaveBank music; /// /// Sound Effects /// static WaveBank effects; /// /// Provides access to WaveBank entries /// public static SoundBank soundBank; /// /// Holds the xml branch contatining music data. /// static XmlNode backgoundAudioNode; /// /// Background music queue. Effects don't need queues b/c they aren't looped. /// static List cues; /// /// True if background music is playing. /// static bool musicPlaying = true; /// /// Used for 3D sound.. don't play if out of range.. wastes proccesses /// public static float SOUND_CUTOFF_DISTANCE = 1500; #endregion /// /// Loads audioEngine, soundBank, music waveBank, and effects waveBank. /// public static void Initialize() { // Load Audio Engine Files audioEngine = new AudioEngine("Content/_audio/Elemental.xgs"); soundBank = new SoundBank(audioEngine, "Content/_audio/Sound Bank.xsb"); music = new WaveBank(audioEngine, "Content/_audio/Music.xwb"); effects = new WaveBank(audioEngine, "Content/_audio/Effects.xwb"); if (backgoundAudioNode != null) { backgoundAudioNode.RemoveAll(); } // Clear music cue list cues = new List(); } /// /// Loads xml data for audio tag and play's level song. /// /// Audio xml node. public static void LoadXML(XmlNode musicNode) { // Save for later backgoundAudioNode = musicNode; if (backgoundAudioNode.Name == "Music") { try { PlayLevelSong(backgoundAudioNode.Attributes["background"].Value); } catch { System.Diagnostics.Debug.WriteLine("Error reading music filename"); return; } } } /// /// Play's a song in the background. /// /// Song Name contained in the loaded SoundBank. public static void PlayLevelSong(string songName) { // Kill everthing for (int i = 0; i < cues.Count; i++) { cues[i].Stop(AudioStopOptions.Immediate); } // Unload all the cues cues.Clear(); // Start new theme Cue playCue = soundBank.GetCue(songName); musicPlaying = true; cues.Add(playCue); if (Statics_Engine.SystemSettings.music) { playCue.Play(); } } /// /// Update XNA audio engine. /// See if user has requested to mute or unmute music. /// public static void Update() { if (Statics_Engine.SystemSettings.music && !musicPlaying) { for (int i = 0; i < cues.Count; i++) { cues[i].Resume(); musicPlaying = true; } } else if (!Statics_Engine.SystemSettings.music && musicPlaying) { for (int i = 0; i < cues.Count; i++) { cues[i].Pause(); musicPlaying = false; } } if (audioEngine != null) { audioEngine.Update(); } } #region 3D Sounds /// /// Sound coming from a particle on the board, used in attacks. /// Sound is attached to the particle itself. /// /// Sound wrapper containing particle-based sounds. /// Particle emmitting sound. /// Player listening to sounds. /// Used to cut off sound after a given time. public static void Play3D_LoopTrack_TimedKill(Cue3D pSound, Mass emitter, Mass listener, float timestep) { //check the distance first! if (Vector3.Distance(emitter.currentPosition, listener.currentPosition) > SOUND_CUTOFF_DISTANCE) {return;} if (timestep < 1000){timestep = 1.0f;} else{timestep /= 1000.0f;} pSound.emitter.Position = emitter.currentPosition * timestep; pSound.emitter.Velocity = emitter.velocity; pSound.listener.Position = listener.currentPosition * timestep; pSound.listener.Velocity = listener.velocity; pSound.cue.Apply3D(pSound.listener, pSound.emitter); if (!pSound.cue.IsPlaying) { pSound.cue = Audio.soundBank.GetCue(pSound.name); pSound.cue.Apply3D(pSound.listener, pSound.emitter); pSound.cue.Play(); } } /// /// Sound used when Player terrainMods. /// /// Class containing cues for Player-based sounds. /// Location of the Attacker. /// Location of the Listener. public static void Play3D_LoopTrack(Cue3D pSound, Vector3 emitterPosition, Vector3 listenerPosition) { int loopDelay = 900; //check the distance first! if (Vector3.Distance(emitterPosition, listenerPosition) > SOUND_CUTOFF_DISTANCE) { return; } //pSound.cue.Apply3D(pSound.listener, pSound.emitter); //if (pSound.terrainModSoundTimer.ElapsedMilliseconds > loopDelay) { //pSound.cue = soundBank.GetCue(pSound.name); pSound.emitter.Position = emitterPosition; pSound.listener.Position = listenerPosition; pSound.cue.Apply3D(pSound.listener, pSound.emitter); pSound.cue.Play(); pSound.terrainModSoundTimer.Reset(); pSound.terrainModSoundTimer.Start(); } } /// /// Sound used when Player jumps. /// /// Class containing cues for Player-based sounds. /// Location of the Attacker. /// Location of the Listener. public static void Play3D_OneTimeTrack(Cue3D pSound, Vector3 emitterPosition, Vector3 listenerPosition) { //check the distance first! if (Vector3.Distance(emitterPosition, listenerPosition) > SOUND_CUTOFF_DISTANCE) { return; } pSound.cue = soundBank.GetCue(pSound.name); pSound.emitter.Position = emitterPosition; pSound.listener.Position = listenerPosition; pSound.cue.Apply3D(pSound.listener, pSound.emitter); pSound.cue.Play(); } #endregion //Audio.soundBank.GetCue("EarthBurst"); //Audio.soundBank.GetCue("WaterBurst"); //Audio.soundBank.GetCue("AirBurst"); //Audio.soundBank.GetCue("Jump"); //Audio.soundBank.GetCue("Hit"); //Audio.soundBank.GetCue("Walking"); //Audio.soundBank.GetCue("TerrainMod"); //Audio.soundBank.GetCue("FireBurst"); #region 2D Sounds /// /// Base function called by all 2D sounds. /// /// Name of cue to play public static void PlayCue2D(string cueName) { if (Statics_Engine.SystemSettings.soundFX) { soundBank.PlayCue(cueName); } } /// /// Sound played when player finds a Key. /// public static void KeyFound() { PlayCue2D("KeyFound"); } /// /// Sound played when Start button is pressed in menu system. /// public static void MenuStart() { PlayCue2D("Tin"); } /// /// Sound played when Back button is pressed in menu system. /// public static void MenuBack() { PlayCue2D("Tin"); } /// /// Sound played when Up button is pressed in menu system. /// public static void MenuUp() { PlayCue2D("Tin"); } /// /// Sound played when Down button is pressed in menu system. /// public static void MenuDown() { PlayCue2D("Tin"); } /// /// Sound played when Left button is pressed in menu system. /// public static void MenuLeft() { PlayCue2D("Tin"); } /// /// Sound played when Right button is pressed in menu system. /// public static void MenuRight() { PlayCue2D("Tin"); } /// /// Sound played when Player selection is changed in menu system. /// public static void MenuPlayerShuffleRight() { PlayCue2D("Tin"); } /// /// Sound played when Player selection is changed in menu system. /// public static void MenuPlayerShuffleLeft() { PlayCue2D("Tin"); } /// /// Sound played when Dpad button is pressed in Game. /// public static void MenuDPad() { PlayCue2D("Tin"); } #endregion } #endregion }