1
\$\begingroup\$

I've started coding a new game project and I've implemented Ogre for the graphics rendering and begun thinking about the audio side of things.

I was considering using the SFML audio component for implementing audio. It is cross platform and can handle streaming music from the file or playing sounds loaded into memory from a buffer.

My initial thoughts were along the line of creating an audio manager class that can load all the relevant sounds into memory and then just be able to play them by reference when required. My concern there was the potential memory use of having a whole lot of sounds loaded into memory.

This is the code I came up with as a very rough test of what I was thinking. Obviously it would need to be improved a lot but it does seem to work.

#include <vector>
#include <string>
#include <iostream>
#include <unistd.h>

#include <SFML/Audio.hpp>

class gameSound
{
public:
gameSound();
~gameSound();

bool loadSound(std::string filename);

std::string name;
sf::SoundBuffer buffer;
sf::Sound sound;
};

gameSound::gameSound(){}
gameSound::~gameSound(){}

bool gameSound::loadSound(std::string filename) {
if(!buffer.loadFromFile(filename))
    return false;

sound.setBuffer(buffer);

return true;
}



class SoundManager
{
public:
SoundManager();
~SoundManager();

void PlaySoundByName(std::string name);
void AddSound(gameSound* snd);

std::vector<gameSound*> sounds;
};

SoundManager::SoundManager(){}
SoundManager::~SoundManager(){

while(!sounds.empty())
{
    sounds.pop_back();
}

}

void SoundManager::AddSound(gameSound* snd) {
sounds.push_back(snd);
std::cout << "gameSound added with name: " << snd->name << " total sounds : " << sounds.size() << std::endl;
}

void SoundManager::PlaySoundByName(std::string name) {

for(std::vector<int>::size_type i = 0; i != sounds.size(); i++) {
    if(sounds[i]->name == name) {
        std::cout << "Match found for " << name << std::endl;
        sounds[i]->sound.play();
    }
}

}

int main()
{

SoundManager* smgr = new SoundManager();

gameSound* s1 = new gameSound();
s1->loadSound("sound.ogg");
s1->name = "Sound";

gameSound* s2 = new gameSound();
s2->loadSound("alarm.ogg");
s2->name = "Alarm";

gameSound* s3 = new gameSound();
s3->loadSound("dog-grunt.ogg");
s3->name = "DogGrunt";

smgr->AddSound(s1);
smgr->AddSound(s2);
smgr->AddSound(s3);

smgr->PlaySoundByName("DogGrunt");

sleep(2);

smgr->PlaySoundByName("Alarm");

sleep(2);
return 0;
}

I know with most systems these days, especially gaming systems, there is usually plenty of memory so it might not be an issue. I was considering implementing a way to load the most important sounds into memory for instant access and then have less common sounds loaded and freed from memory as they are required.

I am interested to know how others have approached the handling of audio required for a game and if I am on the right track.

\$\endgroup\$
3
\$\begingroup\$

From a conceptual point of view you seem to be on the right track. Here is the way I did it.

I'm currently developing a 3D game that I wanted to be able to run on low-memory Windows Phones. My game has lots of 20k tri models, so memory management was a problem.

In essence, to solve my problem I broke my game down into about 4 sections: Global, menu, space, and station. At the beginning all global data (like UI and basic sounds) were loaded. Every time the game changes state, it unloads whatever is unnecessary an loads the data for the new state.

Note that I did this for all assets, not just sounds. This vastly improved performance. Obviously, you can make it as granular as you want, but remember that the law of diminishing returns applies.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.