Sound Class


Creating the sound class is really simple. You already saw several sound classes in the first chapters and sound cue playback is easy. To make your life even easier you can define an enum with all the sound cue names in it. This way you make sure that every sound cue really exists and you don’t mistype any sound. Another great advantage of this approach is IntelliSense, which will now show you all the available sound cues that are hidden in the XACT project if you don’t have an enum like this. Spending two minutes to write this enum is the most valuable thing you can do for sound playback in XNA. Playing a sound cue is easy now with help of the Play method in the Sound class.

  /// <summary> /// Play /// </summary> /// <param name="soundName">Sound name</param> public static void Play(string soundName) {   if (soundBank == null)     return;   try   {     soundBank.PlayCue(soundName);   } // try   catch (Exception ex)   {     Log.Write("Playing sound " + soundName + " failed: " +       ex.ToString());   } // catch } // Play(soundName) /// <summary> /// Play /// </summary> /// <param name="sound">Sound</param> public static void Play(Sounds sound) {   Play(sound.ToString()); } // Play(sound) 

You can also make the string version private to only allow the Sounds enum version. In case the sound bank could not be initialized in the constructor (for example, if the file is missing) this method will immediately return and you are not able to play any sounds. A log file error was already reported in the constructor if that happened. Then you just call PlayCue to play and forget about the sound cue. In case this fails you log an error message, but you don’t throw the exception down to the caller because you always want to have the sound be played and not to interrupt your program logic just because some sound file is missing or some effect did not work out.

As you saw before you can also use the GetCue method to remember a sound cue and then do multiple things with it. This is also useful if you want to stop the cue yourself instead of waiting until it is finished playing. As an example, this is used to stop music playback:

  someSoundCue = soundBank.GetCue("SomeSound"); someSoundCue.Play(); ... someSoundCue.Stop(AudioStopOptions.Immediate); 

Though most of the Sound class is the same for most of the projects in this book, take a look at the differences and the special functionality because the basic playback code was already discussed (see Figure 9-14).

image from book
Figure 9-14

The first thing you will notice is the different sound cue names in the Sounds enum. Both Rocket Commander XNA and the Racing Game use the custom pitch cue variable discussed a minute ago. The XNA Shooter game does not use anything special; you just start the music at the beginning of the game, and then play all sound effects as you need them and that’s it.

To make typing in the code to play sounds more comfortable, several helper methods were created. For example, PlayExplosionSound just replaces the following code making it faster and easier to write the code required to play this sound effect:

  Sound.Play(Sound.Sounds.Explosion); 

For music playback two additional methods are added, which also keep track of the music cue in case you want to stop or restart the music: StartMusic and StopMusic.

There is also a unit test in each sound class to check if the sound playback works the way you want it to, which is also used to check if all sounds have the proper volume settings. This is the unit test from the Rocket Commander XNA Sound class:

  /// <summary> /// Test play sounds /// </summary> public static void TestPlaySounds() {   TestGame.Start(     delegate     {       if (Input.MouseLeftButtonJustPressed ||         Input.GamePadAJustPressed)         Sound.Play(Sounds.Bomb);       else if (Input.MouseRightButtonJustPressed ||         Input.GamePadBJustPressed)         Sound.Play(Sounds.Click);       else if (Input.KeyboardKeyJustPressed(Keys.D1))          Sound.Play(Sounds.GameMusic);       else if (Input.KeyboardKeyJustPressed(Keys.D2))          Sound.Play(Sounds.MenuMusic);       else if (Input.KeyboardKeyJustPressed(Keys.D3))          Sound.Play(Sounds.Explosion);       else if (Input.KeyboardKeyJustPressed(Keys.D4))          Sound.Play(Sounds.Fuel);       else if (Input.KeyboardKeyJustPressed(Keys.D5))          Sound.Play(Sounds.Victory);       else if (Input.KeyboardKeyJustPressed(Keys.D6))          Sound.Play(Sounds.Defeat);       else if (Input.KeyboardKeyJustPressed(Keys.D7))       {         Sound.PlayRocketMotorSound(0.75f);         Sound.ChangeRocketMotorPitchEffect(0.5f);       } // else if       else if (Input.KeyboardKeyJustPressed(Keys.D8))         Sound.StopRocketMotorSound();       TextureFont.WriteText(2, 30,         "Press 1-8 or A/B or left/right "+         "mouse buttons to play back sounds!");   }); } // TestPlaySounds() 

Finally, the Update method is called automatically by the Update method of your BaseGame class inside the graphics engine. The Update method just makes sure that all parameters, looping, and timing values are updated inside XACT for you.

Rocket Motor Sound

Take a quick look at the Rocket Motor sound from Rocket Commander XNA. You already saw all the code required for this to work, but it might be nice to see it all thrown together and compatible with the Rocket Commander engine, which was written for DirectSound initially, but works fine with XACT now too:

  /// <summary> /// Play rocket motor sound /// </summary> public static void PlayRocketMotorSound() {   // Get new cue everytime this is called, else we get Xact throwing   // this: The method or function called cannot be used in the manner   // requested.   rocketMotorSound = soundBank.GetCue(Sounds.RocketMotor.ToString());   // Plays the sound looped, set in XACT   rocketMotorSound.Play();   // Make motor category a little silent   motorCategory.SetVolume(0.86f); } // PlayRocketMotorSound(volume) /// <summary> /// Change rocket motor pitch effect /// </summary> /// <param name="pitchFactor">Pitch factor</param> public static void ChangeRocketMotorPitchEffect(float pitchFactor) {   rocketMotorSound.SetVariable("Pitch",     55 * MathHelper.Clamp(pitchFactor - 1, -1, 1)); } // ChangeRocketMotorPitchEffect(pitchFactor) /// <summary> /// Stop rocket motor sound /// </summary> public static void StopRocketMotorSound() {   rocketMotorSound.Stop(AudioStopOptions.Immediate); } // StopRocketMotorSound() 

To start the rocket sound you just call the PlayRocketMotorSound method after a mission starts, then you modify it during the flight with the help of the ChangeRocketMotorPitchEffect method:

  // Adjust rocket playback frequency to flying speed Sound.ChangeRocketMotorPitchEffect(0.66f + speed * 0.9f); 

And finally StopRocketMotorSound can be called to stop the rocket sound when you die or the mission is over.

The gear sound logic in the racing game works in a similar way, but it is a little bit more complicated because you have 13 different gear motor sounds and not just one rocket motor sound like in Rocket Commander XNA. Check out the Sound class of the racing game for more details.

Whoosh, What Was That?

The original Rocket Commander game used its own 3D sound calculation formula and used the volume and panning properties of a DirectSound sample to achieve the correct effect for the player. In XNA it’s sadly not possible to change the panning. All sounds are played the way they are created and set in XACT. For 3D sounds you should use real 3D sound code anyway and in the XNA beta 1 I wrote some code to play 3D sounds and have a 3D listener object moving around the 3D world.

This 3D listener object is now missing from XNA; you can’t use 3D sound effects currently. Hopefully this will change in the future and I will certainly update the code for the games in this book when 3D sounds are possible again, but for now you can only play back sounds in mono; there’s no stereo or surround sound support.

In case you can use X3DAudio and X3DAudioListener (the classes might have different names; it is just important that you can somehow set and play 3D audio and that you can position yourself with the help of the 3D listener class), the following code could be used to play 3D sounds after you set all important cue variables:

  // Setup 3D listener for 3D sound Sound.Listener = new X3DAudioListener(   zAxis, yAxis, cameraPosition, movementVector); 

Now set the emitter for each sound you want to play in your 3D world and play the 3D audio instances. Currently there is no C# code available to do this and if you are still puzzling about this when XNA finally supports it some time in the future, you can check out the following link to see how the X3DAudio classes are used in C++. The ideas will be the same in C#, but hopefully much easier to write.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/ audio_xact_overview_x3daudio.asp

Menu Sounds

To finish this chapter here are some quick tips for menu sounds:

  • Use helper methods like PlayMenuHighlight or PlayMenuClick to play menu sound effects instead of using the Sounds enum.

  • If you want to play certain menu sounds at different volumes, for example a loud highlight sound for major buttons and a more silent highlight sound for smaller controls, then create two sound cues in XACT instead of writing your own custom volume code, which is more work and not necessary at all.

  • Try to write helper methods to find out if the mouse was moved over a control this frame and reuse this code or method for all controls to unify the highlight or mouse click code. This way you don’t have to play click or highlight sounds yourself for every custom button method you use in your game.

  • Make sure you also support the Xbox 360 controller and the keyboard. Writing a mouse-only game makes no sense on the Xbox 360 because you have absolutely zero mouse support in XNA for your Xbox 360.

  • Play highlight sounds when navigating through menu entries and play click sounds when the user clicks the gamepad or presses space or Enter on the keyboard to go into the current menu selection.




Professional XNA Game Programming
Professional XNA Programming: Building Games for Xbox 360 and Windows with XNA Game Studio 2.0
ISBN: 0470261285
EAN: 2147483647
Year: 2007
Pages: 138

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net