XNA UK User Group
A helping hand for bedroom coders throughout the land.
Sound in XNA 3.1, Part I

Sound in XNA seems to have traditionally been a bit of a black art, i.e.. rather difficult and best left to someone else to do! The root cause of all this anguish was that you had to use the Cross-platform Audio Creation Tool, otherwise known as XACT.

XACT actually consists of two components:

  1. An audio engine in XNA to play your sounds (there is some coding needed).
  2. A stand-alone application that is installed alongside XNA Game Studio, which provides a powerful GUI that you use to load and design your game audio. This is where most of the work needs to be done, and where most of the problems arise. It is very powerful tool, and, as is so often the case with powerful programs, it has a bit of a steep learning curve.

In XNA 3.1, life got a lot easier, with the new SoundEffect and Song classes allowing you to do everything in code. As the names rather suggest, the SoundEffect class is intended to be used to play back the kind of samples that are typically used for sound effects, i.e. short samples that are repeated, and the Song class is intended for music files, i.e. longer samples with minimal or no repetition. With these classes, you add your audio files to your game project content pipeline (in the form of wav, mp3, or wma files), and then load them up and play them directly in your code. [ As a side note, if you are developing for the Zune platform, then this is your only option. ]

For example, to play a simple sound effect takes the following two lines of code:

 SoundEffect soundEffect = Content.Load<SoundEffect>(@"Content\Audio\LaserShot");

 soundEffect.Play();

Nice and easy!

However, XACT was also updated in XNA 3, and whilst I couldn’t tell you if it is any easier to use than earlier versions, it does give you a lot of functionality that you would otherwise have to code yourself, which I think makes battling with the learning curve worthwhile. To give you a hand with that, let’s create a project and go through the basics of putting some sound effects into your game.

Creating an XACT project

First things first, you need to open up XACT 3 (it's under Tools in the XNA Game Studio Start Menu folder), and create a new project. With XACT, you only need to add your XACT project file to your game’s content pipeline, as XNA Game Studio includes an importer for these files. Given that, I prefer to create an audio folder in the content area of the game project, and save the XACT project in there. You don’t need to add your audio files, which has the added advantage of abstracting your audio files away from your game project.

For this tutorial, I’ve used the name SimpleSoundEffects. This will create a file with the extension xap, which is, rather annoyingly, the same extension as a Silverlight application!

 

New_Project

 

Your XACT window should look something like the image above; you have the project tree on the top left-hand side of the window, and a properties pane below it. This shows the properties of whatever item you have selected, which will be the general settings at this stage. So, how do we go about importing our audio files to our project? By creating a Wave Bank, of course!

Creating a Wave Bank

In order to import some audio files, we first need something to import them into. That something is a Wave Bank. The wave bank is a container for audio files, and you can have as many wave banks as you want in a project. We'll make do with one for now, so either right-click on the Wave Bank node or click on the Wave Banks menu item, and select New Wave Bank. We'll stick with the default name (Wave Bank). The Properties pane will now be showing the Wave Bank's properties:

 

Create_Wave_Bank

 

You can see that there are two green buttons that allow you to specify the Type of the Wave Bank. You have two options here; an In Memory wave bank is loaded entirely into memory and all the audio files are played from there, whereas a Streaming wave bank streams the sound files from the disk as they are played. Streaming is primarily aimed at game music, where the files tend to be a lot bigger than sound effect files, so you'd really rather not load them entirely into memory.

As well as specifying the Type, you can associate a Compression Preset with the Wave Bank. XACT will only use uncompressed audio files, but it can compress the files in the wave bank. However, there are no default Compression Presets in a project, so we’ll need to create one.

Creating a Compression Preset

Right-click on the Compression Presets node in the project tree, and select New Compression Preset. Stick with the default name (Compression Preset). The Properties pane will now show the following information:

 

Create_Compression_Preset

 

A Compression Preset allows you to have different settings for the Xbox 360 and for Windows. For each platform, you can select a format to save the wave bank in:

  • PCM is uncompressed audio.
  • XMA is the original compression format for the XBox 360. It is based on WMA, and does a reasonable job.
  • ADPCM is the older format for Windows. Again, it does a reasonable job.
  • xWMA was only introduced in XNA 3, and provides the best compression out of all the options available. However, it doesn’t loop seamlessly and there is a processor overhead, so it’s best for non-repeating music and dialogue.

For the compressed formats, you get to set the compression level. With XMA and xWMA, the higher the number, the higher the quality, but with ADPCM, the opposite is true (it refers to the block size of the ADPCM file, so the smaller the block, the better the quality of the audio).

Once created, you can either go back to the Wave Bank property window and select the compression preset from the drop-down menu, or you can drag the compression preset node in the project tree to the wave bank node (or vice-versa).

Importing audio files

Now our wave bank is set up, we can import a couple of sounds. As I’ve previously mentioned, XACT will only accept uncompressed audio, in the form of pcm wav and aiff files. If you only have files in other formats, you can use a program such as Audacity to convert them. As I’ve just described, you can get XACT to compress them again for you, so you don't have to worry about them taking up too much space. Right-click in the Wave Bank window, and select Insert Wave File(s).

 

Insert_Wav_Files

 

Select the files that you want to import and click Open. You’ll notice that the files in the wave bank are marked in red, which indicates that they are not being used by anything in the project. To remedy that, they need to be referenced by Sound objects, and to create a Sound object, we first need to create a SoundBank.

Create a Sound Bank

Again, you can either right-click on the Sound Banks node or click on the Sound Banks menu item, and select New Sound Bank. We'll stick with the default name (Sound Bank) once again. The Properties pane will now be showing the sound bank's properties, but there’s nothing to interest us there.

In the main part of the XACT window, you will now see the Sound Bank window, which is split into four panes:

 

Create_Sound_Bank_1ED3C9B4

 

  1. The top left pane lists all the Sounds in the Sound Bank.
  2. The top right pane lists all the Tracks and Events in the selected Sound (note that I’m not going to be dealing with Tracks and Events in any kind of detail in this post).
  3. The bottom left pane lists all the Cues in the Sound Bank. Cues reference Sound objects and are these are what you use in code to play a sound.
  4. The bottom right pane lists all the Sounds attached to the selected Cue.

Whilst you can create Sounds, Tracks and Cues and link them together manually, you can also just simply drag and drop the wavs from the wave bank into the Cue pane, and everything you need gets automatically created. Do that with both of our wavs, and you’ll see that two Sounds, each with a single Track and Event, as well as two Cues have been created, and also that the wavs in the Wave Bank have now turned green to signify that they are being used in the project.

Playing a sound

So, we have now set up an XACT project with everything we need to play a simple sound effect. Save the project and open Visual Studio. Add the .xap file to the content pipeline. When you build your project now, Visual Studio will now build the wave banks (creating an .xwb file for each one) and sound banks (creating a .xsb file for each one) for you, as well as the global settings file for the XACT project (a .xgs file). These files will be created in the content folder of the bin directory that the rest of the project is built to (Debug or Release, depending on which build configuration you are in).

And now, finally, to the code! We first need to create three global objects, an instance of the XACT audio engine, a sound bank and a wave bank.

 private AudioEngine _audioEngine;

 private SoundBank _soundEffectsSoundBank;

 private WaveBank _soundEffectsWaveBank;

Now we need to load those objects. The Audio Engine loads up the XACT project global settings files, whilst the other two load up their files.

 // Initialise audio

 _audioEngine = new AudioEngine(@"Content\Audio\SimpleSoundEffects.xgs");

 

 // Load up the banks

 _soundEffectsSoundBank = new SoundBank(_audioEngine, @"Content\Audio\Sound Bank.xsb");

 _soundEffectsWaveBank = new WaveBank(_audioEngine, @"Content\Audio\Wave Bank.xwb");

 

 // Prime the audio engine for use

 _audioEngine.Update();

Notice the last line of code; you need to call the Update method on the Audio Engine before you try to play any sounds. You also need to call it regularly during your game’s execution, so I suggest that you put it in your game's Update method.

Now we can play a sound:

 _soundEffectsSoundBank.PlayCue("Laser Shot");

And that's all it takes to play a simple sound effect. However, that’s a lot of work for no apparent gain over the pure code method, so in Part II we’ll explore some of the benefits that XACT can give us.


Posted Thu, Jan 21 2010 10:37 PM by manzanotti
Filed under: ,

Comments

Nemo Krad wrote re: Sound in XNA 3.1, Part I
on Fri, Jan 22 2010 3:31 PM

Great post, will have to have another look at XACT, played with it in 1.0,1.1 and 2.0 but once we had the new audio classes in 3.0 never bothered with it.

Now, the only issue I now have with XACT is file compression :(

VeraShackle wrote re: Sound in XNA 3.1, Part I
on Sat, Jan 23 2010 12:18 PM

Really nice job - no wonder, you went quiet after your introductory post! Looking forward to Part II...

GameDevKicks.com wrote Sound in XNA 3.1, Part I
on Mon, Jan 25 2010 8:59 PM

You've been kicked (a good thing) - Trackback from GameDevKicks.com

RaaR wrote re: Sound in XNA 3.1, Part I
on Thu, Feb 4 2010 4:44 PM

sweet just what i was going to need to look up over the next few weeks.  just getting to the stage of recording the sounds so this is a great help

Nemo Krad wrote re: Sound in XNA 3.1, Part I
on Tue, Feb 9 2010 10:02 PM

Just though I would mention, I am using XNA 3.1 and writing stuff for the ZuneHD, and I can use the Song, SoundEffect and MediaPlayer objects.....