namespace DarkWynterEngine.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;
public static class AudioMixer
{
///
/// Background Music
///
static WaveBank music;
///
/// Sound Effects
///
static WaveBank effects;
///
/// Provides access to WaveBank entries
///
static SoundBank soundBank;
public struct AudioBackground
{
///
/// Earth Attack sound.
///
public static List background;
}
public struct Audio3D
{
///
/// Earth Attack sound.
///
public static AudioCue earthAttack;
///
/// Water Attack sound.
///
public static AudioCue waterAttack;
///
/// Air Attack sound.
///
public static AudioCue airAttack;
///
/// 3D Cue used with jump sound.
///
public static AudioCue jump;
///
/// 3D Cue used with hit sound.
///
public static AudioCue smackDownHit;
///
/// 3D Cue used with walk sound.
///
public static AudioCue walking;
///
/// 3D Cue used with terrainMod sound.
///
public static AudioCue terrainMod;
///
/// 3D Cue used with fire attack sound.
///
/// Sound played when player finds a Key.
///
public static AudioCue KeyFound;
///
/// Sound played when Start button is pressed in menu system.
///
public static AudioCue MenuStart;
///
/// Sound played when Back button is pressed in menu system.
///
public static AudioCue MenuBack;
///
/// Sound played when Up button is pressed in menu system.
///
public static AudioCue MenuUp;
///
/// Sound played when Down button is pressed in menu system.
///
public static AudioCue MenuDown;
///
/// Sound played when Left button is pressed in menu system.
///
public static AudioCue MenuLeft;
///
/// Sound played when Right button is pressed in menu system.
///
public static AudioCue MenuRight;
///
/// Sound played when Player selection is changed in menu system.
///
public static AudioCue MenuShuffleRight;
///
/// Sound played when Player selection is changed in menu system.
///
public static AudioCue MenuShuffleLeft;
///
/// Sound played when Dpad button is pressed in Game.
///
public static AudioCue MenuDPad();
}
}
///
/// Supports 2D and 3D audio in the form of an AudioCue.
/// 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 AudioProcessor
{
///
/// XNA audio engine API
///
static AudioEngine audioEngine;
///
/// Keeps metranome synchronous time
///
public static Stopwatch currentGameTime;
///
/// Delay before playing another walk cue.
/// Used to stop too many sounds from being played at once.
///
public Stopwatch walkingSoundTimer;
///
/// Delay before playing another terrainMod cue.
/// Used to stop too many sounds from being played at once.
///
public Stopwatch terrainModSoundTimer;
///
/// Background music queue.
/// Effects don't have cues b/c the sound isn't looped.
///
static List cues;
///
/// True if background music is playing.
///
///
/// Used for 3D sound.. don't play if out of range.. wastes proccesses
///
public static float SOUND_CUTOFF_DISTANCE = 1500;
///
/// Loads audioEngine, soundBank, music waveBank, and effects waveBank.
/// Hand out instruments to the musicians.
///
public static void Initialize(XmlNode node)
{
// Clear music cue list
cues = new List();
// Used to measure track elapsed time.
currentGameTime = new Stopwatch();
currentGameTime.Start();
// Load Audio xml file and associate with engine sounds
if (node.Name == "AudioConfig")
{
try
{
// 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");
// Load Background Sounds
if (node.ChildNodes[i].Name() == "Background")
{
for (int i = 0; i < node.ChildNodes; i++)
{
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "EarthAttack")
{
AudioBackground.background = new AudioCue(node.ChildNodes[i].Value);
}
}
}
// Load Menu Sounds
if (node.ChildNodes[i].Name() == "Menu")
{
for (int i = 0; i < node.ChildNodes; i++)
{
// ABSTRACT = CREATE ABSTRACT ENGINE SOUND CLASS
// ALLOW GAME OVERRIDE OF SINGLE IF STATEMENT LIKE ONE BELOW
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "MenuStart")
{
Audio2D.MenuStart = new AudioCue(node.ChildNodes[i].Value);
}
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "MenuBack")
{
Audio2D.MenuBack = new AudioCue(node.ChildNodes[i].Value);
}
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "MenuShuffleRight")
{
Audio2D.MenuShuffleRight = new AudioCue(node.ChildNodes[i].Value);
}
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "MenuShuffleLeft")
{
Audio2D.MenuShuffleLeft = new AudioCue(node.ChildNodes[i].Value);
}
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "MenuUp")
{
Audio2D.MenuUp = new AudioCue(node.ChildNodes[i].Value);
}
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "MenuDown")
{
Audio2D.MenuDown = new AudioCue(node.ChildNodes[i].Value);
}
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "MenuLeft")
{
Audio2D.MenuLeft = new AudioCue(node.ChildNodes[i].Value);
}
// Get Child Nodes and replace strings GetCue methods
if (node.ChildNodes[i].Name() == "MenuRight")
{
Audio2D.MenuRight = new AudioCue(node.ChildNodes[i].Value);
}
}
}
// Load Engine Sounds
if (node.ChildNodes[i].Name() == "Engine")
{
for (int i = 0; i < node.ChildNodes; i++)
{
if (node.ChildNodes[i].Name() == "EarthAttack")
{
Audio3D.earthAttack.cue = new AudioCue(node.ChildNodes[i].Value);
}
if (node.ChildNodes[i].Name() == "Jump")
{
Audio3D.jump.cue = new AudioCue(node.ChildNodes[i].Value);
}
if (node.ChildNodes[i].Name() == "Hit")
{
Audio3D.smackDownHit.cue = new AudioCue(node.ChildNodes[i].Value);
}
if (node.ChildNodes[i].Name() == "Walking")
{
Audio3D.walking.cue = new AudioCue(node.ChildNodes[i].Value);
}
if (node.ChildNodes[i].Name() == "TerrainMod")
{
Audio3D.terrainMod.cue = new AudioCue(node.ChildNodes[i].Value);
}
if (node.ChildNodes[i].Name() == "FireBurst")
{
Audio3D.fireAttack.cue = new AudioCue(node.ChildNodes[i].Value);
}
if (node.ChildNodes[i].Name() == "WaterBurst")
{
Audio3D.waterAttack.cue = new AudioCue(node.ChildNodes[i].Value);
}
if (node.ChildNodes[i].Name() == "AirBurst")
{
Audio3D.airAttack.cue = new AudioCue(node.ChildNodes[i].Value);
}
walkingSoundTimer.Start();
terrainModSoundTimer.Start();
/// Play's level song.
PlayLevelSong(orchestration.Attributes["background"].Value);
}
}
}
catch
{
System.Diagnostics.Debug.WriteLine("Error reading music filename");
return;
}
}
}
///
/// Update XNA audio engine.
/// See if user has requested to mute or unmute music.
///
public static void Update()
{
//
if (Statics.SystemSettings.music && !musicPlaying)
{
for (int i = 0; i < cues.Count; i++)
{
cues[i].Resume();
musicPlaying = true;
}
}
else if (!Statics.SystemSettings.music && musicPlaying)
{
for (int i = 0; i < cues.Count; i++)
{
cues[i].Pause();
musicPlaying = false;
}
}
audioEngine.Update();
}
#region 3D Sounds
///
/// Sound used in Fire attacks.
/// Not based on particles, unlike Attack.
///
/// Class containing cues for Player-based sounds.
/// Location of the Attacker.
/// Location of the Listener.
public static void PlayAudio(AudioCue audioCue)
{
//check the distance first!
if (Vector3.Distance(audioCue.emitterPosition, audioCue.listenerPosition) > SOUND_CUTOFF_DISTANCE)
{
return;
}
pSound.fireAttack.cue.Apply3D(audioCue.emitterPosition, audioCue.listenerPosition);
if (!pSound.fireAttack.cue.IsPlaying)
{
pSound.fireAttack.cue = AudioProcessor.soundBank.GetCue("FireBurst");
pSound.fireAttack.cue.Apply3D(pSound.fireAttack.listener, pSound.fireAttack.emitter);
pSound.fireAttack.cue.Play();
}
if (pSound.terrainModSoundTimer.ElapsedMilliseconds > 900)
{
pSound.terrainMod.cue = soundBank.GetCue("TerrainMod");
pSound.terrainMod.cue.Apply3D(pSound.terrainMod.listener, pSound.terrainMod.emitter);
pSound.terrainMod.cue.Play();
pSound.terrainModSoundTimer = Stopwatch.StartNew();
}
}
#endregion
///
/// Kills all Attack sounds.
///
/// Wrapper contatining attack cues.
public static void StopAttack(EngineSounds pSound)
{
// Stop Sound
if (pSound.earthAttack.cue != null)
{
pSound.earthAttack.cue.Stop(AudioStopOptions.Immediate);
}
if (pSound.waterAttack.cue != null)
{
pSound.waterAttack.cue.Stop(AudioStopOptions.Immediate);
}
if (pSound.airAttack.cue != null)
{
pSound.airAttack.cue.Stop(AudioStopOptions.Immediate);
}
}
///
/// 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.SystemSettings.music)
{
playCue.Play();
}
}
#region 2D Sounds
///
/// Base function called by all 2D sounds.
///
/// Name of cue to play
public static void PlayCue2D(string cueName)
{
if (Statics.SystemSettings.soundFX)
{
soundBank.PlayCue(cueName);
}
}
#endregion
}
#region Audio Cue
///
/// Contains the neccessary information for 2D and 3D sound processing.
///
public class AudioCue
{
int length;
int starttime;
Enums.AudioType audioType;
// 3D components
///
/// Cue contatining sound used in 3D audio.
///
public Cue cue;
///
/// A sound generator.
///
public AudioEmitter emitter;
///
/// A sound receiver.
///
public AudioListener listener;
// Create a 2D sound
public AudioCue(int TrackLength, string TrackName, Enums.AudioType type)
{
cue = AudioProcessor.soundBank.GetCue(TrackName);
length = TrackLength;
audioType = type;
}
// Create a 3D sound
public AudioCue(int TrackLength, string TrackName, Enums.AudioType type,
AudioEmitter EmitterObject, AudioListener ListenerObject)
{
cue = AudioProcessor.soundBank.GetCue(TrackName);
length = TrackLength;
emitter = EmitterObject;
listener = ListenerObject;
}
}
#endregion
}