====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: 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.