Optimal use of XAudio2 in games

Started by
5 comments, last by Burnt_Fyr 12 years, 9 months ago
Hey, I would like to ask for some clues on how to create effective and low memory costing sounds system in my game. I might have about 200 characters displayed on the screen(bots) and each of them must have individual sounds. Every character has 100 sounds possible to play and one Source Voice can play only one sound at once. So I made an array of IXAudio2SourceVoice: [font="Lucida Console"] IXAudio2SourceVoice *pSourceVoice[100];[/font] for each of them so each character can play lots of sounds simultaneously. Now creating 200*100(chars amount*sounds amount) Source Voices costs a lot of memory and I would like to minimize the memory costs of my audios... I would really be extremaly grateful for any advice you could give me about improving my memory performance using XAudio2.
Advertisement
Its the same problem with textures and models. When loading, you should check to see if has already been loaded, if so, use that, if not, load from the disk.

Have a master list where the real allocated memory is stored, then pass out copies of the pointers or IDs as integers as needed. Then, when the program exists, free all the memory. This is what I use. I have objects ask to load the sound file and in return, I get an integer, which is really an ID into an array (but that doesn't matter). When the object is done using the sound, it tells the soundmanager it is done with he id. The soundmanager keeps an internal count of how many references are held to that id and free the memory if needed. This is basically a type of smart pointer but a little bit different because I dont want to hand out the actual pointer to the memory and I often times store other internal information along with the instance of the object so handing out pointers isnt best for me.

Thats all
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
I'm not sure what you mean, quite too professional words and phrases you use as for me :P, Could you explain me your idea once again with simpler words?
Sure. There are many ways this can be done and there will definately be people posting responses saying they would do it a little bit different. Try not to get to caught up in the details as you need to understand the more broad topic.

Create a class SoundManager This class is responsible for actually loading, and allocating any memory for sounds

You have your 200 Bots, all who want to play a sound.

Your SoundManager should have a function like this
unsigned short LoadSound(std::string file);

Inside your SoundManager class, you can use a container like std::map to store all the files you have already loaded.
So, search the map to see if it has been loaded. If not, load the sound file from the disk and insert the string into the map.
the return of this should be an integer which is really the index to an array where you placed the sound you loaded from the disk.
You will need to make sure you are handing out unique integers.

Create a function in SoundManager called
void PlaySound(unsigned short soundid)

the soundid is the integer returned from the call to LoadSound. So the SoundManager uses the integer to find the sound in the array it holds and starts playing the sound.

Create a function in SoundManager called
void ReleaseSound(unsigned short soundid)

This is to be passed the id from LoadSound. When you are totally done with the sound, call this passing the id. It should check to see if anyone else is still using the same id, if not, delete the memory used by the sound.

There are many other functions to create, but you have to start somwehere
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
Thanks a lot for reply! Now I get it, might be even effective solution. Worst is that I don't know how to free memory from IXAudioSourceVoice. I tried using delete but now I know that I can't use delete if I didn't create an array of IXAudio2SourceVoice with new operator. So it doesn't work... I tried ZeroMemory() but I didn't see a decrease of declared memory in windows task menager. I tried DestroyVoice() but after calling DestroyVoice I can't use the same IXAudio2SourceVoice variable in my program again and even didn't see a decrease in memory either. Are you using XAudio2? If so maybe you could know how to solve this problem?
PS: I want to be able to free and declare memory of the sounds while my game is open
Each sound that you want to play has to have its own IXAudio2SourceVoice. So, if you have 50 sounds, you need 50 IXAudio2SourceVoice's. In order to free the memory you have to call DestroyVoice on IXAudio2SourceVoice. Think of IXAudio2SourceVoice object as a type of middle man. Its job is to keep track of the sound it is playing, its volume, and what ever other settings that are specific to that individual sound. So, you can have the same sound file loaded, but different effects on each one by having different IXAudio2SourceVoice for each.
You need to Destroy each IXAudio2SourceVoice that you create as well.

You can save memory by storing the XAUDIO2_BUFFER_WMA parts seperate from the IXAudio2SourceVoice. Since the XAUDIO2_BUFFER_WMA is where the actual data of the sound is kept, you only need one of these. They can be shared amongst different IXAudio2SourceVoice to conserve on memory.
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
Your never possibly going to use all those source voices. In my code I have 3 main classes:

Mixer : a device with a set number of tracks, such as 32 or 64, which represents the max polyphony of the system, and a number of buses which allow things like separate levels for sounds vs music, etc. Each track is essentially a wrapper for a SourceVoice, and each bus a SubmixVoice.

SoundBank: this loads Sound files and stores the XAUDIO2_BUFFERs created.

AudioDevice: the main interface to the system.

On program start, AudioDevice is created, which in turn Creates the XAudio2Device and creates objects of the other 2 classes. When A sound is loaded it passes the file or memory location to SoundBank which in turn creates the buffer. When A sound is played it polls the mixer for an open track, gets the buffer from soundBank, and pushes it onto the track. It works well enough for me as is, but there is a ton of stuff I'd like to implement if I get time.

This topic is closed to new replies.

Advertisement