The audio tool Xact from XNA provides a lot of functionallity necessary for your own game. But sometimes it can be very exhausting to find out how a specific task can be done, even if that task seems to be very easy like controlling the volume of a cue. Documentations are mostly not very detailled, if you could manage to find one. Due to the fakt that I had some work to find out how to handle volume changes properly (at least more than I expected), I’d like to write about that.
Basically there are two ways to controll the volume of a running cue. There can be more, but thats all I found out.
1. Categories
The first one works with categories. You can create a category in the Xact tool, stick some sounds to it and change the category volume at runtime. Rightclick on the Categroies entry in Xact or on an existing category to add a new one or a subcategory. Give it a name and select the sounds you want to add to this category in your soundbank. Now select the new category in the lower left menu from a dropdown list.
In the component that cares for the audio of your game you should somewhere have an AudioEngine instance, if you want to work with Xact. This AudioEngine provides access to lots of properties and entities of your Xact .xap project. With GetCategory and the corresponding name as a string, you can grap your category and set the volume level with SetVolume. This could look like that:
public class AudioInterface : GameComponent
{
private AudioEngine audioEngine;
private WaveBank waveBank;
private SoundBank soundBank;
public AudioInterface(Game _game) : base(_game)
{
audioEngine = new AudioEngine("Content/Audio/myGameAudio.xgs");
waveBank = new WaveBank(audioEngine, "Content/Audio/Wave Bank.xwb");
soundBank = new SoundBank(audioEngine, "Content/Audio/Sound Bank.xsb");
}
private void SetCategoryVolume(string _name, float _level)
{
AudioCategory cat = audioEngine.GetCategory(_name);
cat.SetVolume(_level);
}
public override void Update(GameTime _gameTime)
{
audioEngine.Update();
}
//TODO add some more usfull audio stuff
}
Working with categories is cool because you can modify a lot of sound cues at once, but changing volumes via categories for single music tracks is pretty anoying. The number and subcategory structure of your Xact project can become very big and confusing. A better way are variables.
2. Variables
Right below the Categories entry in Xact is an entry called Variables. Here you can create your own variables, set a range or an initial value and change the value at runtime via the AudioEngine instance. By connecting that variable to a sound from the soundbank, you can controll a lots of properties for that sound at runtime with the variable. One of them is volume. To do that you need a RPC (Runtime Parameter Controll) Preset which can be added right below the variables. That preset holds one ore more curves wich are connected to your variable and defines how the specified property changes, if you increase or decrease the variable value at runtime. If that preset is made, hook your sounds to it and thats it.
A wonderful tutorial about variables, presets and dynaming music volume can be found at Kevin Gadd’s blog. This one has a lot of pictures and code snippets and should give you a lot of information about that topic.
After doing all the Xact work you could extend your audio engine with something like that
public void setGlobalVariable(string _name, float _value)
{
m_audioEngine.SetGlobalVariable(_name, _value);
}
public float getGlobalVariable(string _name)
{
return m_audioEngine.GetGlobalVariable(_name);
}
and change the music volume by setting your volume variable to fade the music or set a specified level directly.
private enum FadeState { None, FadeIn, FadeOut }
private float FadeValue(GameTime _gameTime, FadeState _mode, float _start,
float _duration, string _variable)
{
float fadeElapsedTime = (float)(_gameTime.TotalGameTime.TotalSeconds - _start);
float intensity = MathHelper.Clamp(fadeElapsedTime / _duration, 0f, 1f);
switch (_mode)
{
case FadeState.FadeIn:
audioInterface.setGlobalVariable(_variable, intensity);
break;
case FadeState.FadeOut:
audioInterface.setGlobalVariable(_variable, 1f - intensity);
break;
default:
//do nothing
break;
}
return intensity;
}
The presets together with variables are pretty migthy. For example I used a variable and a preset with two curves (as you can see in the image above) to crossfade two sounds by connecting a rising curve to the first track and a falling to the second and modifying them with the corresponding variable.
So much for now, have fun with Xact and dynamic volume.
Cheers Volker

Hi. Very nice Blog. Not really what i have searched over Google, but thanks for the information.
Not bad! Although I don’t visit your blog much but I must say that you always post amazing information and the theme is quite good. Keep us updated mate! I love your blog and will keep on appreciating your effort every time I visit.