audio.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00016 #include "audio.h"
00017 #include "audio_sound.h"
00018 #include "audio_music.h"
00019 #include "system.h"
00020 
00021 using namespace std;
00022 
00023 using namespace hoa_utils;
00024 using namespace hoa_system;
00025 
00026 
00027 template<> hoa_audio::GameAudio* Singleton<hoa_audio::GameAudio>::_singleton_reference = 0;
00028 
00029 namespace hoa_audio {
00030 
00031 GameAudio* AudioManager = NULL;
00032 bool AUDIO_DEBUG = false;
00033 
00034 
00035 namespace private_audio {
00036 
00037 
00038 } // namespace private_audio
00039 
00040 using namespace hoa_audio::private_audio;
00041 
00042 // ****************************************************************************
00043 // *********************** GameAudio Class Functions *************************
00044 // ****************************************************************************
00045 
00046 GameAudio::GameAudio() {
00047   if (AUDIO_DEBUG) cout << "AUDIO: GameAudio constructor invoked" << endl;
00048 }
00049 
00050 
00051 // The destructor halts all audio, frees up all allocated memory, and closes the context and device
00052 GameAudio::~GameAudio() {
00053   if (AUDIO_DEBUG) cout << "AUDIO: GameAudio destructor invoked" << endl;
00054 
00055   Mix_HaltMusic();
00056   Mix_HaltChannel(ALL_CHANNELS);
00057 
00058   // Delete all sound and music data
00059   for (std::map<string, SoundData*>::iterator i = _sound_data.begin(); i != _sound_data.end(); i++) {
00060     delete i->second;
00061   }
00062   _sound_data.clear();
00063   
00064   for (std::map<string, MusicData*>::iterator i = _music_data.begin(); i != _music_data.end(); i++) {
00065     delete i->second;
00066   }
00067   _music_data.clear();
00068 
00069   Mix_CloseAudio();
00070 }
00071 
00072 
00073 // Initializes OpenAL and creates the global audio context
00074 bool GameAudio::SingletonInitialize() {
00075   if (AUDIO_DEBUG) cout << "AUDIO: GameAudio constructor" << endl;
00076 
00077   if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) {
00078     cerr << "AUDIO ERROR: Could not initalize SDL audio subsystem: " << SDL_GetError() << endl;
00079     return false;
00080   }
00081 
00082   // Open 22.05KHz, signed 16bit, system byte order, stereo audio, using 1024 byte chunks
00083   if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, BUFFER_SIZE) == -1) {
00084     cerr << "AUDIO ERROR: Could not initialize mixer audio: " << Mix_GetError() << endl;
00085     return false;
00086   }
00087   
00088   Mix_AllocateChannels(SOUND_CHANNELS);
00089   return true;
00090 }
00091 
00092 
00093 
00094 void GameAudio::Update() {
00095   // The countdown timer to examine the list of temporary seconds, initialized to 5 seconds
00096   static int32 examine_time = 5000;
00097 
00098   examine_time -= SystemManager->GetUpdateTime();
00099   if (examine_time < 0) { // 5 seconds have expired, reset timer and examine list for temporary sounds that are stopped
00100     examine_time = 5000;
00101 
00102     // NOTE: Everytime a sound is deleted, we have to traverse back to the list begin.
00103     // Probably an alternative container would suit _temp_sounds better (std::deque anyone?)
00104     for (list<SoundDescriptor*>::iterator i = _temp_sounds.begin(); i != _temp_sounds.end();) {
00105       if ((*i)->GetSoundState() == AUDIO_STATE_STOPPED) {
00106         delete(*i);
00107         _temp_sounds.erase(i);
00108         i = _temp_sounds.begin();
00109       }
00110       else {
00111         i++;
00112       }
00113     }
00114   }
00115 }
00116 
00117 
00118 
00119 void GameAudio::PlaySound(string filename) {
00120   SoundDescriptor* new_sound = new SoundDescriptor();
00121 
00122   if (new_sound->LoadSound(filename) == false) {
00123     if (AUDIO_DEBUG)
00124       cerr << "AUDIO ERROR: GameAudio::PlaySound() failed because the sound file could not be loaded" << endl;
00125     delete(new_sound);
00126   }
00127 
00128   new_sound->PlaySound();
00129   _temp_sounds.push_front(new_sound);
00130 }
00131 
00132 
00133 // Returns a pointer to the sound buffer for the file. Loads the file from memory if it isn't already. Returns NULL if there was an error.
00134 SoundData* GameAudio::_AcquireSoundData(string filename) {
00135   // If the data in question is already loaded, return a pointer to it.
00136   if (_sound_data.find(filename) != _sound_data.end()) {
00137     return _sound_data[filename];
00138   }
00139 
00140   // The data is not loaded, so load it, place it in the data map, and return a pointer to it
00141   else {
00142     SoundData *SD = new SoundData(filename);
00143     // Return a pointer to the new data if it was created successfully, otherwise return NULL.
00144     if (SD->IsValid()) {
00145       _sound_data[filename] = SD;
00146       return SD;
00147     }
00148     else {
00149       // Note: No error code is set here because this function is only called from LoadMusic() in MusicDescriptor
00150       if (AUDIO_DEBUG) cerr << "AUDIO ERROR: Unable to create a new SoundData" << endl;
00151       delete(SD);
00152       return NULL;
00153     }
00154   }
00155 }
00156 
00157 // Returns a pointer to the music buffer for the file. Loads the file from memory if it isn't already. Returns NULL if there was an error.
00158 MusicData* GameAudio::_AcquireMusicData(string filename) {
00159   // If the buffer in question is already loaded, return a pointer to it.
00160   if (_music_data.find(filename) != _music_data.end()) {
00161     return _music_data[filename];
00162   }
00163 
00164   // The data is not loaded, so load it, place it in the data map, and return a pointer to it
00165   else {
00166     MusicData *MD = new MusicData(filename);
00167     // Return a pointer to the new data if it was created successfully, otherwise return NULL.
00168     if (MD->IsValid()) {
00169       _music_data[filename] = MD;
00170       return MD;
00171     }
00172     else {
00173       // Note: No error code is set here because this function is only called from LoadMusic() in MusicDescriptor
00174       if (AUDIO_DEBUG) cerr << "AUDIO ERROR: Unable to create a new MusicData" << endl;
00175       delete(MD);
00176       return NULL;
00177     }
00178   }
00179 }
00180 
00181 
00182 void GameAudio::SetMusicVolume(float vol) {
00183   if (vol > 1.0f) {
00184     if (AUDIO_DEBUG) cerr << "AUDIO WARNING: Tried to set music volume above maximum level" << endl;
00185     _music_volume = 1.0f;
00186   }
00187   else if (vol < 0.0f)
00188   {
00189     if (AUDIO_DEBUG) cerr << "AUDIO WARNING: Tried to set music volume below minimum level" << endl;
00190     _music_volume = 0.0f;
00191   }
00192   else {
00193     _music_volume = vol;
00194   }
00195 
00196   uint8 volume = static_cast<uint8>(_music_volume * 128.0f); // scale for SDL_Mixer
00197   Mix_VolumeMusic(volume);
00198 }
00199 
00200 
00201 void GameAudio::SetSoundVolume(float vol) {
00202   if (vol > 1.0f) {
00203     if (AUDIO_DEBUG) cerr << "AUDIO WARNING: Tried to set sound volume above maximum level" << endl;
00204     _sound_volume = 1.0f;
00205   }
00206   else if (vol < 0.0f)
00207   {
00208     if (AUDIO_DEBUG) cerr << "AUDIO WARNING: Tried to set sound volume below minimum level" << endl;
00209     _sound_volume = 0.0f;
00210   }
00211   else {
00212     _sound_volume = vol;
00213   }
00214 
00215   uint8 volume = static_cast<uint8>(_sound_volume * 128.0f); // scale for SDL_Mixer
00216   Mix_Volume(ALL_CHANNELS, volume);
00217 }
00218 
00219 
00220 void GameAudio::PauseAudio() {
00221   PauseAllMusic();
00222   PauseAllSounds();
00223 }
00224 
00225 void GameAudio::ResumeAudio() {
00226   ResumeAllMusic();
00227   ResumeAllSounds();
00228 }
00229 
00230 void GameAudio::StopAudio() {
00231   StopAllMusic();
00232   StopAllSounds();
00233 }
00234 
00235 void GameAudio::RewindAudio() {
00236   RewindAllMusic();
00237 //  RewindAllSounds();
00238 }
00239 
00240 
00241 void GameAudio::PauseAllSounds() {
00242   Mix_Pause(ALL_CHANNELS);
00243 }
00244 
00245 
00246 void GameAudio::ResumeAllSounds() {
00247   Mix_Resume(ALL_CHANNELS);
00248 }
00249 
00250 
00251 void GameAudio::StopAllSounds() {
00252   Mix_HaltChannel(ALL_CHANNELS);
00253 }
00254 
00255 
00256 // void GameAudio::RewindAllSounds() {}
00257 
00258 
00259 void GameAudio::PauseAllMusic() {
00260   Mix_PauseMusic();
00261   for (std::map<string, MusicData*>::iterator i = _music_data.begin(); i != _music_data.end(); i++) {
00262     i->second->playing = false;
00263   }
00264 }
00265 
00266 
00267 void GameAudio::ResumeAllMusic() {
00268   Mix_ResumeMusic();
00269   for (std::map<string, MusicData*>::iterator i = _music_data.begin(); i != _music_data.end(); i++) {
00270     i->second->playing = true;
00271   }
00272 }
00273 
00274 
00275 void GameAudio::StopAllMusic() {
00276   Mix_HaltMusic();
00277   for (std::map<string, MusicData*>::iterator i = _music_data.begin(); i != _music_data.end(); i++) {
00278     i->second->playing = false;
00279   }
00280 }
00281 
00282 
00283 void GameAudio::RewindAllMusic() {
00284   Mix_RewindMusic();
00285 }
00286 
00287 
00288 // Prints information about that audio settings on the user's machine
00289 void GameAudio::DEBUG_PrintInfo() {
00290   printf("SDL_mixer version (compiled): %d.%d.%d\n", MIX_MAJOR_VERSION, MIX_MINOR_VERSION, MIX_PATCHLEVEL);
00291   printf("SDL_mixer version (linked):   %d.%d.%d\n", Mix_Linked_Version()->major, Mix_Linked_Version()->minor, Mix_Linked_Version()->patch);
00292   printf("Number of playback channels:  %d\n", MIX_DEFAULT_CHANNELS);
00293   printf("Number of mixing channels:  %d\n", MIX_CHANNELS);
00294   printf("Playback frequency:  %d\n", MIX_DEFAULT_FREQUENCY);
00295   printf("Playback format:  %d\n", MIX_DEFAULT_FORMAT);
00296   printf("Maximum volume:  %d\n", MIX_MAX_VOLUME);
00297 }
00298 
00299 } // namespace hoa_audio

Generated on Fri Jul 6 23:11:09 2007 for Hero of Allacrost by  doxygen 1.5.1