Good music adds a lot to a game, but only if it fits the action occurring on screen. Badly chosen music that doesn’t match the feel of your game, or is inappropriate for the tone of the gameplay, won’t do you much good. Dynamic music is one way to help make sure your music is always a good fit for the action occurring on-screen – it lets you adapt the music the player is hearing based on what’s happening.
There are various approaches for building dynamic music – some games go so far as to create hundreds of short music ‘snippets’ and string them together to create longer, more dynamic songs that never sound the same to the player once. Unfortunately, this is pretty complicated to do, especially if you’re just working with XNA and XACT. Luckily, there are some simpler techniques you can use to build dynamic music.
Below, you can see a short video clip showing one of my experiments with dynamic music. I’ll explain how it works in this post, so you can apply the technique to your games. In this video clip, I have two music tracks playing, and control the volume of one of them depending on whether or not the player character is within the blue rectangle. You can hear the track fading in and out as he moves.
The approach I’m using works like this: You take a song that you intend to use in your game, and in an audio tool, split it out into multiple wave files, one for each ‘track’ that you want to have control over. Depending on the complexity of your song, you might just want to split it out into a pair of tracks, and fade one of them in when you want the music to get more intense. If your music is more sophisticated and your gameplay has lots of variation, you may want lots of tracks that you can control individually based on what’s happening – fade in some anxious-sounding strings when powerful monsters are on screen, and temporarily fade in some ominous-sounding bass notes when the player is injured, for example.
In this article I’m going to be using two simple tracks I exported from a song using ModPlug tracker. This is about as simple as you can get, since I just wanted to grab a song I had lying around that I knew I could use without violating any copyright laws. To create the tracks, I went into MPT and loaded up the song. Then, I went into the pattern editor and muted part of the channels, and exported the song to a WAV. After that, I unmuted those channels and muted the remaining channels, and exported them to a second WAV file. This gives me two WAV files of equal length, each of which composes a portion of the song.
Now, to actually wire it up, you have to go into XACT and load up your audio project. You’re going to want to find the wave bank you keep your music in, and open it up. Once it’s open, select the tracks for your song and drag-drop them into the wave bank. Afterwards, you should have one entry in the wave bank for each track, as you see below.
Next, open up the sound bank that contains your music cues. This probably has the same name as your wave bank for music, but if it doesn’t, no big deal.
Now, drag one of your tracks out of your music wave bank, and drop it into the bottom portion of your sound bank, where the cues are listed. This will create a cue and associated sound for that track.
The cue and sound are automatically named after the track, which probably isn’t ideal, so you can rename both of them to something easier to remember – this will make it easier to work with them in your game code. After you’ve done that, select the sound for your music up in the top section of the sound bank. You should see your track on the right side of the window, listed as ‘Track 1′.
Next, you want to drag your remaining tracks out of your wave bank, and drop them directly onto the empty space below your track, in the top right portion of the sound bank window. This will create additional tracks for them, as a part of the sound.
You’re all done here, so go ahead and close your wave and sound banks. Next, you need to create a variable to control the volume of your tracks. Go to the treeview on the left side of the XACT window, and right click the ‘Global’ section under ‘Variables’. Select ‘New Global Variable’.
In the window that opens, choose a name for your variable – I chose ‘MusicTrackVolume’ – and then change its ‘Control’ to ‘Monitored’. Go ahead and close the variable settings window after this.
Next, right click the ‘RPC Presets’ section in the left side of the window, and select ‘New RPC Preset’.
A rather intimidating window will open up. The first few things you want to do in this window are:
- Select your variable in the ‘Variable’ dropdown at the top.
- Then, in the same row, change the ‘Object’ dropdown to point at the track for which you wish to control volume.
- Finally, change the ‘Parameter’ dropdown to ‘Volume’.
Once this is done, you need to set up the volume ramp, so that XACT knows how to adjust the volume of your track based on the value of the variable. To keep things simple, go ahead and set two points for the ramp:
- MusicTrackVolume = 0.00, Volume = -96.00 (dB)
- MusicTrackVolume = 1.00, Volume = 0.00 (dB)
This specifies that when your variable is set to 0.0, the volume will be set to -96.0 dB, basically silent, and when it is set to 1.0, the volume will be set to 0 dB – full volume.
Once this is done, you can close the RPC Preset window, and rename your new preset to something easier to identify, like ‘Music Volume Preset’. After that, open your sound bank back up. Drag your RPC preset out of the left side of the XACT window, and drop it directly onto the entry for your music in the top left portion of the sound bank window (the sounds portion, not the cues portion).
After you do this, your sound should be highlighted, and the bottom left portion of the XACT window (the properties viewer) should show your preset under ‘Attached Objects’. We’re done in XACT now, so you can save everything and close it if you like.
Once you have everything set up in XACT, you can use your cue as you normally would in-game. By default, you will only hear one of your tracks, because your variable’s value defaults to zero.
To make it so the player can hear the track, all you have to do is provide a value for your variable. You do this by using the SetGlobalVariable method of the XACT AudioEngine class, like so:
AudioEngine.SetGlobalVariable("MusicIntensity", 0.8f);
Given this, it’s straightforward to set up your game code so that XACT variables change in response to in-game events. Note that variables change immediately after you set them, so your volume changes will be abrupt and somewhat disconcerting. The best way to solve this is to interpolate your variable changes, something like this:
float fadeElapsedTime = (gameTime.TotalGameTime.TotalSeconds - FadeStartedWhen);
float musicIntensity = MathHelper.Clamp(fadeElapsedTime / FadeDuration, 0.0f, 1.0f);
AudioEngine.SetGlobalVariable("MusicIntensity", musicIntensity);
Doing that every frame will give you smooth transitions between values, so that the player hears tracks fade in and out instead of immediately stopping and starting.
It’s also important to note that since the relationship between volume and decibels (dB) is logarithmic, your tracks will sound like they are fading in very quickly. The best way to solve this is by creating a more advanced curve for your RPC Preset, so that the fading sounds smoother. Here’s the one I used in my example video clip above:
As you can see, I partially counteract the logarithmic nature of the dB scale by making the volume ramp up rapidly from -96dB to -32dB in the first quarter of the scale, and then ramp up more slowly from there to 0dB. For your needs, a more complex curve might be appropriate.
I hope this post has given you some ideas about how to integrate dynamic music into your own XNA games. Please don’t hesitate to comment if you have any questions!














#1 by Goombs on August 3, 2009 - 4:10 am
Quote
Thanks for this. I’ve been looking for a good guide on how to do this. Would it be possible to provide the project source code to see how everything is linked together?
#2 by Kael on August 4, 2009 - 3:59 pm
Quote
The game will be open source eventually, but in the interim I might find time to make a tutorial with downloadable source code.
Pingback: Dynamic Volume in Xact3
#3 by Volker on September 18, 2009 - 2:29 am
Quote
Hey Kael,
thanks a lot for this tutorial, it really helped by getting more controll over Xact and helped me with my own projekt.
http://blog.brightside-games.com/?p=109&preview=true
ceers Volker
#4 by 5p. on September 28, 2009 - 7:38 pm
Quote
Hi Kael,
I’ve been messing around with controlling different track volumes in XNA, but it seems like even when I set the percussion track volume to -96 via RPC, the percussion is still audible. Same for some other tracks. Any ideas?
#5 by 5p. on September 29, 2009 - 5:55 pm
Quote
Heh, this is embarrassing – I figured out what was going on. Turns out Audacity doesn’t mute tracks when you export, so the percussion got mixed in with all the other tracks. Fixed.
#6 by Dave Matney on August 3, 2010 - 2:17 pm
Quote
This tutorial is awesome. I haven’t seen ANYTHING explain variables or RPC Presets so well — this has revolutionized my current project.
Pingback: XACTing Siphon Spirit | Dave Matney : Forward
#7 by bostelk on December 1, 2010 - 10:17 am
Quote
Looking forward to trying this out. Thanks Kael!