Sign in to follow this  
savail

Optimal use of XAudio2 in games

Recommended Posts

savail    333
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"][size="2"] IXAudio2SourceVoice *pSourceVoice[100];[/size][/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.

Share this post


Link to post
Share on other sites
smasherprog    568
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

Share this post


Link to post
Share on other sites
savail    333
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?

Share this post


Link to post
Share on other sites
smasherprog    568
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

Share this post


Link to post
Share on other sites
savail    333
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

Share this post


Link to post
Share on other sites
smasherprog    568
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.

Share this post


Link to post
Share on other sites
Burnt_Fyr    1665
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this