3D Audio Effects - Location
Xna4.png

Overview

This tutorial, and the one immediately following it, will discuss some of the basics of 3D audio effects. We will start of this tutorial with a brief look at what 3D audio effects are, and when we might want to use them. We will then spend the rest of this tutorial looking at how to perform a simple 3D audio effect. We will make our sound cue seem like it is coming from a point in space.

If you haven't done anything with XACT yet, you should probably go through the tutorials on using XACT and playing sound in XNA. Also, when I made this tutorial, I used the information in the XACT sound loops tutorial. You won't need this, but it might come in handy anyway.

3D Audio Effects

A 3D audio effect is simply altering how your sound is played, to give the illusion that they are happening in 3D space. In other words, an explosion isn't just an explosion in the game, but the player can tell where the explosion happened.

3D audio effects help players feel much more involved in the game. They feel like the sound is coming from all around them, rather than from just the computer screen.

3D audio effects also give players an indication of where events are taking place. Imagine you are playing a first person shooter, and someone is shooting at you. Without 3D effects, you would be able to hear that you are being shot at. With 3D audio effects though, you could tell where the other player is, and you would know which way to turn to find them.

One of the coolest examples that I've seen of what 3D audio effects can do is the Virtual Barbershop. I've included the "video" below. It works best if you use headphones, and if you close your eyes. Give it a try!

Setup

In a minute we will discuss how to write the code that does 3D audio effects. You can perform these effects with any sound cue. I felt like it would be a good idea to explain what I used for this tutorial, though.

In order to do this, you will need to already have an XACT project ready to use. (And it must have at least one sound cue!) If you haven't done this yet, take a look at the tutorial about using XACT.

I've picked a sound effect that is just a helicopter that can loop. I wanted it to loop so that I could have the sound keep going and going (and sound nice) while the source of the sound moved around. I found the sound effect at flashkit.com. That should link to the page that has it on it, but if the link ever gets broken, you should be able to find it again by searching their 'Sound FX' page for 'helicopter loop'. Also, I've set up my helicopter cue to loop forever, as discussed in the sound loops tutorial.

Finally, I've already written the code to play my helicopter sound without any 3D audio effects, as discussed in the Playing Sound tutorial.

Coding the Effect

The first thing that we need to do is get a reference to our sound cue. This means that we will also want to tell our sound cue to play in a slightly different way. So first, let's add the following line as an instance variable to our game:

private Cue cue;

Now go to the place where you told the sound to play. We will want to change this. The code used to say:

soundBank.PlayCue("helicopter");

We want to change this to:

cue = soundBank.GetCue("helicopter");
cue.Play();

At this point, you should be able to run your game again, and it should all work like it did before.

So now let's move on to the next step: telling our game where the sound is being emitted from, and where the listener is located at. I'm going to set up my game so that the source of the sound moves in a circle around the listener. So to do this, the first thing I'm going to do is add the following code as instance variables to the main game class:

        private AudioEmitter emitter = new AudioEmitter();
        private AudioListener listener = new AudioListener();
 
        private float angle = 0;
        private float distance = 5;

The AudioEmitter class will tell us information about the emitter. In this tutorial, we will only look at the emitter's location, but there are several other options available that you can experiment with. The AudioListener class wil specify similar information about where the listener (player) is located at. The angle and distance variables will be used to calculate the location of the emitter as it spins around the listener.

Next, I've created a method that will convert the emitter's angle and distance into a Vector3 location in 3D space, as shown below:

        private Vector3 CalculateLocation(float angle, float distance)
        {
            return new Vector3(
                (float)Math.Cos(angle) * distance,
                0,
                (float)Math.Sin(angle) * distance);
        }

This method basically converts polar coordinates into cartesian coordinates (which if you're interesting in knowing a bit more about, see the math tutorial on coordinate systems).

Next I'm going to add the following code to my Update() method. This is the code that will change the location of my audio emitter, and also tell the cue to apply the new 3D audio effect:

            angle += 0.01f;  // rotate the emitter around a little bit
            listener.Position = Vector3.Zero;  // the listener just stays at the origin the whole time
            emitter.Position = CalculateLocation(angle, distance);  // calculate the location of the emitter again
 
            cue.Apply3D(listener, emitter); // apply the 3D transform to the cue

This should do everything that we need it to do. We have only one other change left. If you want to apply a 3D effect to a Cue object, you have to have told it to apply a 3D effect some point before you tell the cue to play. It gets the cue to be initialized in a different way. So be sure to add something like the code below, just before you tell the cue to start playing initially:

    // tell it to apply a 3D transform even before you play the cue
    cue.Apply3D(listener, emitter);
 
    // and then you can tell it to start playing
    cue.Play();

With all of this, you should now be able to play your project and hear your sound moving around! I've added all of the code for my project below, because I realize this is kind of a complicated tutorial. It brings in things from multiple other tutorials, add adds new stuff on.

What's Next?

In this tutorial we've looked at how to get XNA to play sound that seems like it is coming from a location in space. You might also find it useful to see the tutorial on Using Attenuation in 3D Audio Affects, which tells you how to get XNA to change the volume of a sound, based on how far away from the listener it is.


Troubleshooting.png Having problems with this tutorial? Try the troubleshooting page!