User Tools

Site Tools


proton:audiomanager

AudioManager - One interface, many implementations

If you look in BaseApp.h you'll see this near the bottom:

AudioManager * GetAudioManager();  //supply this yourself

It means it expects you to implement this function somewhere in your App code. Shared-level components and code will be able to use audio through the AudioManager interface, without knowing how you implemented it. (Just standard C++ subclassing with virtuals)

The minimum you have to do is this:

AudioManager g_audioManager; //to disable sound
AudioManager * GetAudioManager()
{
    return &g_audioManager;
}

The above will let everything “think” they are using sound functions, but do nothing. To actually hear sound on windows (or iOS using FMOD), do:

#include "Audio/AudioManagerFMOD.h"
AudioManagerFMOD g_audioManager; //play with the FMOD implementation
 
AudioManager * GetAudioManager()
{
    return &g_audioManager;
}

RTSimpleApp uses #ifdefs to use the correct implementation for the correct platform.

BaseApp will run Init() on it, you don't.

Playing a sound

GetAudioManager()->Play("click.wav");

Internally, the audio manager will play it and keep the sound object around for future calls.

Caching/preloading manually

Auto caching is good enough, but if you notice jerks in your game the first time audio is loading you should probably preload them.

GetAudioManager()->Preload("click.wav");

All of audio implementations handle playing compressed music (ogg or mp3, or both) and at a minimum, .wav sounds for effects with mixing. FMOD supports more formats like .mid and .xm as well.

Music has its own special way of being called by using the bIsMusic flag:

//defined as:  virtual AudioHandle Play(string fName, bool bLooping = false, bool bIsMusic = false, bool bAddBasePath = true, bool bForceStreaming = false);
 
GetAudioManager()->Play("song.ogg", false, true);

When you say, “this is music” here is what happens:

  • If the same song is already playing, the call is ignored
  • If another song is playing, it kills it first
  • The file is streamed from disk, not loaded or cached
  • On systems that can only decode one compressed audio in hardware at a time, it is reserved for music
  • If AudioManager::SetMusicEnabled was set with false, it is ignored
  • The volume it plays at is set by AudioManager::SetMusicVol

Advanced controls with AudioHandles

If you want to be able to kill a sound or perform other effects on it during playback, you need to keep track of the AudioHandle returned from the Play() command. (it's just a uint32)

//init somewhere
 AudioHandle npcTalk = 0;
 
//entities AI sees the player
 npcTalk = GetAudioManager()->Play(taunt.wav);
 GetAudioManager()->SetPan(npcTalk, -1.0f); //left speaker only
 GetAudioManager()->SetVol(npcTalk, 1.0f); //max volume
 
//but soon after he starts to taunt, he is killed and should do his deathscream
GetAudioManager()->Stop(npcTalk);
npcTalk = GetAudioManager()->Play("scream.wav");

Using old/dead handles doesn't cause problems.

Note: Some of the more advanced audio functions such as AudioManager::SetPan and AudioManager::SetFrequency are not available on all sound implementations.

Controlling memory

You know that FPS debug text that always shows up in the examples? The A:<number> is how much memory is allocated in audio. (if it says 0, it means this implementation doesn't know and is returning 0 from AudioManager::GetMemoryUsed)

If you are running low on memory you can use AudioManager::KillCachedSounds between levels, or even during levels. Its parameters allow you to further refine what is killed; including by last usage time and priority level.

Good vibrations

For some reason its the AudioManager's job to phone vibration. Called vibration on a platform that can't do it (like PC) will be ignored or write “VIBRATE!” to the debug text.

GetAudioManager()->Vibrate(); //hmm, I may need a VibrateEx() at some point with more options.

If GetAudioManager()→SetVibrateDisabled was set to true, it will be ignored.

proton/audiomanager.txt · Last modified: 2010/10/28 06:40 by seth