1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright (C) 2004-2010 by The Allacrost Project 3 // All Rights Reserved 4 // 5 // This code is licensed under the GNU GPL version 2. It is free software 6 // and you may modify it and/or redistribute it under the terms of this license. 7 // See http://www.gnu.org/copyleft/gpl.html for details. 8 /////////////////////////////////////////////////////////////////////////////// 9 10 /** **************************************************************************** 11 *** \file audio.h 12 *** \author Tyler Olsen - roots@allacrost.org 13 *** \author Mois�s Ferrer Serra - byaku@allacrost.org 14 *** \author Aaron Smith - etherstar@allacrost.org 15 *** \brief Header file for audio engine interface. 16 *** 17 *** This code provides an easy-to-use API for managing all music and sounds used 18 *** in the game. 19 *** 20 *** \note This code uses the OpenAL audio library. See http://www.openal.com/ 21 *** ***************************************************************************/ 22 23 #ifndef __AUDIO_HEADER__ 24 #define __AUDIO_HEADER__ 25 26 #ifdef __MACH__ 27 #include <OpenAL/al.h> 28 #include <OpenAL/alc.h> 29 #else 30 #include "al.h" 31 #include "alc.h" 32 #endif 33 34 #include "defs.h" 35 #include "utils.h" 36 37 #include "audio_descriptor.h" 38 #include "audio_effects.h" 39 40 //! \brief All related audio engine code is wrapped within this namespace 41 namespace hoa_audio { 42 43 //! \brief The singleton pointer responsible for all audio operations. 44 extern AudioEngine* AudioManager; 45 46 //! \brief Determines whether the code in the hoa_audio namespace should print debug statements or not. 47 extern bool AUDIO_DEBUG; 48 49 //! \brief Enable whether the audio engine should function 50 extern bool AUDIO_ENABLE; 51 52 namespace private_audio { 53 54 //! \brief The maximum default number of audio sources that the engine tries to create 55 const uint16 MAX_DEFAULT_AUDIO_SOURCES = 64; 56 57 58 59 //! \brief A container class for an element of the LRU audio cache managed by the AudioEngine class 60 class AudioCacheElement { 61 public: AudioCacheElement(uint32 time,AudioDescriptor * aud)62 AudioCacheElement(uint32 time, AudioDescriptor* aud) : 63 last_update_time(time), audio(aud) {} 64 65 //! \brief Retains the time that the audio was last updated through any operation 66 uint32 last_update_time; 67 68 //! \brief A pointer to the audio descriptor described by the cache element 69 AudioDescriptor* audio; 70 }; 71 72 } // namespace private_audio 73 74 /** **************************************************************************** 75 *** \brief A singleton class that manages all audio related data and operations 76 *** 77 *** This class is provided as a singleton so it is conveniently accesible where needed. Here 78 *** there is internal control of the audio device and available sources. Interfaces for the 2 79 *** main groups (sound and music) are available. Also the listener funtionality is provided 80 *** from here. 81 *** 82 *** \note Make sure to later resume paused sounds, otherwise the sources that they hold 83 *** will never be released 84 *** ***************************************************************************/ 85 class AudioEngine : public hoa_utils::Singleton<AudioEngine> { 86 friend class hoa_utils::Singleton<AudioEngine>; 87 // friend class private_audio::SoundData; 88 // friend class private_audio::MusicData; 89 friend class AudioDescriptor; 90 friend class SoundDescriptor; 91 friend class MusicDescriptor; 92 friend class Effects; 93 94 public: 95 ~AudioEngine(); 96 97 /** \brief Opens all audio libraries and initializes the audio device, context, and states 98 *** \return True if there were no errors during initialization 99 **/ 100 bool SingletonInitialize(); 101 102 //! \brief Updates various parts of the audio state, such as streaming buffers 103 void Update(); 104 GetSoundVolume()105 float GetSoundVolume() const 106 { return _sound_volume; } 107 GetMusicVolume()108 float GetMusicVolume() const 109 { return _music_volume; } 110 111 /** \brief Sets the global volume level for all sounds 112 *** \param volume The sound volume level to set. The valid range is: [0.0 (mute), 1.0 (max volume)] 113 **/ 114 void SetSoundVolume(float volume); 115 116 /** \brief Sets the global volume level for all music 117 *** \param volume The music volume level to set. The valid range is: [0.0 (mute), 1.0 (max volume)] 118 **/ 119 void SetMusicVolume(float volume); 120 121 /** \name Global Audio State Manipulation Functions 122 *** \brief Performs specified operation on all sounds and music. 123 *** 124 *** These functions will only effect audio data that is in the state(s) specified below: 125 *** - PlayAudio() <==> all states but the playing state 126 *** - PauseAudio() <==> playing state 127 *** - ResumeAudio() <==> paused state 128 *** - StopAudio() <==> all states but the stopped state 129 *** - RewindAudio() <==> all states 130 **/ 131 //@{ PauseAudio()132 void PauseAudio() 133 { PauseAllSounds(); PauseAllMusic(); } 134 ResumeAudio()135 void ResumeAudio() 136 { ResumeAllSounds(); ResumeAllMusic(); } 137 StopAudio()138 void StopAudio() 139 { StopAllSounds(); StopAllMusic(); } 140 RewindAudio()141 void RewindAudio() 142 { RewindAllSounds(); RewindAllMusic(); } 143 //@} 144 145 /** \name Global Sound State Manipulation Functions 146 *** \brief Performs specified operation on all sounds 147 **/ 148 //@{ 149 void PauseAllSounds(); 150 void ResumeAllSounds(); 151 void StopAllSounds(); 152 void RewindAllSounds(); 153 //@} 154 155 /** \name Global Sound State Manipulation Functions 156 *** \brief Performs specified operation on all sounds 157 *** Since there is only one music source, these functions only affect that source. 158 *** They are equivalent to calling the {Pause/Resume/Stop/Rewind}Music functions on 159 *** the MusicDescriptor which currently has posession of the source. 160 **/ 161 //@{ 162 void PauseAllMusic(); 163 void ResumeAllMusic(); 164 void StopAllMusic(); 165 void RewindAllMusic(); 166 //@} 167 168 /** \name Three Dimensional Audio Properties Functions 169 *** \brief Used to manipulate the shared 3D state members that all sounds share 170 *** Refer to the OpenAL documentation to understand what effect each of these 171 *** properties have (listener position, velocity, and orientation). 172 **/ 173 //@{ 174 void SetListenerPosition(const float position[3]); 175 void SetListenerVelocity(const float velocity[3]); 176 void SetListenerOrientation(const float orientation[3]); 177 GetListenerPosition(float position[3])178 void GetListenerPosition(float position[3]) const 179 { memcpy(position, _listener_position, sizeof(float) * 3); } 180 GetListenerVelocity(float velocity[3])181 void GetListenerVelocity(float velocity[3]) const 182 { memcpy(velocity, _listener_velocity, sizeof(float) * 3); } 183 GetListenerOrientation(float orientation[3])184 void GetListenerOrientation(float orientation[3]) const 185 { memcpy(orientation, _listener_orientation, sizeof(float) * 3); } 186 //@} 187 188 //! \name Audio Effect Functions 189 //@{ 190 /** \brief Fades a music or sound in as it plays 191 *** \param audio A reference to the music or sound to fade in 192 *** \param time The amount of time that the fade should last for, in seconds 193 **/ FadeIn(AudioDescriptor & audio,float time)194 void FadeIn(AudioDescriptor& audio, float time) 195 { _audio_effects.push_back(new private_audio::FadeInEffect(audio, time)); } 196 197 /** \brief Fades a music or sound out as it finisheds 198 *** \param audio A referenece to the music or sound to fade out 199 *** \param time The amount of time that the fade should last for, in seconds 200 **/ FadeOut(AudioDescriptor & audio,float time)201 void FadeOut(AudioDescriptor& audio, float time) 202 { _audio_effects.push_back(new private_audio::FadeOutEffect(audio, time)); } 203 //@} 204 205 /** \brief Plays a sound once with no looping 206 *** \param filename The name of the sound file to play 207 *** This method of playback is useful because it doesn't require any SoundDescriptor 208 *** objects to be managed by the user. This is ideal for the case of scripts which 209 *** wish to play a sound only once. The sound is loaded (if necessary) into the 210 *** sound cache and played from there. 211 **/ 212 213 /** \brief Methods for manipulating audio contained within the audio cache 214 *** \param filename The name of the sound or music file to operate on 215 *** 216 *** These methods invoke the named operation on the piece of audio contained 217 *** within the AudioEngine's LRU audio cache. The primary intended use for these 218 *** functions are for scripts which simply wish to play a sound once to indicate 219 *** an event or action. 220 *** 221 *** The LoadSound/Music functions are not required to use, as invoking a PlaySound/Music 222 *** function will automatically load the audio data if it is not inside the cache already. 223 *** The play, stop, pause, and resume audio operations are the only operations that the user is 224 *** provided with a direct interface to. For any other operations (rewind, seek, volume control, 225 *** looping, etc.), the user must call the RetrieveSound/Music functions to obtain a pointer 226 *** to the audio data and make the desired call on the AudioDescriptor object itself. 227 *** 228 *** \note The default parameters for audio loading (static/streaming data type, stream buffer size) 229 *** can not be set nor manipulated with cached audio. 230 **/ 231 //@{ 232 /** \brief Creates a new SoundDescriptor using the given filename and loads it into the audio cache 233 *** \return True if the sound was loaded into the cache successfully 234 **/ 235 bool LoadSound(const std::string& filename); 236 237 /** \brief Creates a new MusicDescriptor using the given filename and loads it into the audio cache 238 *** \return True if the music was loaded into the cache successfully 239 **/ 240 bool LoadMusic(const std::string& filename); 241 242 //! \brief Plays a sound that is contained within the audio cache 243 void PlaySound(const std::string& filename); 244 245 //! \brief Plays a piece of music that is contained within the audio cache 246 void PlayMusic(const std::string& filename); 247 248 //! \brief Stops a sound that is playing from within the audio cache 249 void StopSound(const std::string& filename); 250 251 //! \brief Stops a piece of music that is playing from within the audio cache StopMusic(const std::string & filename)252 void StopMusic(const std::string& filename) 253 { StopSound(filename); } 254 255 //! \brief Pauses a sound that is playing from within the audio cache 256 void PauseSound(const std::string& filename); 257 258 //! \brief Pauses a piece of music that is playing from within the audio cache PauseMusic(const std::string & filename)259 void PauseMusic(const std::string& filename) 260 { PauseSound(filename); } 261 262 //! \brief Resumes a sound that has been paused from within the audio cache 263 void ResumeSound(const std::string& filename); 264 265 //! \brief Resumes a piece of music that has been paused from within the audio cache ResumeMusic(const std::string & filename)266 void ResumeMusic(const std::string& filename) 267 { ResumeSound(filename); } 268 269 //! \return A pointer to the SoundDescriptor contained within the cache, or NULL if it could not be found 270 SoundDescriptor* RetrieveSound(const std::string& filename); 271 272 //! \return A pointer to the MusicDescriptor contained within the cache, or NULL if it could not be found 273 MusicDescriptor* RetrieveMusic(const std::string& filename); 274 //@} 275 276 /** \name Error Detection and Processing methods 277 *** Code external to the audio engine should not need to make use of the following methods, 278 *** as error detection is routinely done by the engine itself. 279 **/ 280 //@{ 281 /** \brief Retrieves the OpenAL error code and retains it in the _al_error_code member 282 *** \return True if an OpenAL error has been detected, false if no errors were detected 283 **/ CheckALError()284 bool CheckALError() 285 { _al_error_code = alGetError(); return (_al_error_code != AL_NO_ERROR); } 286 287 /** \brief Retrieves the OpenAL context error code and retains it in the _alc_error_code member 288 *** \return True if an OpenAL context error has been detected, false if no errors were detected 289 **/ CheckALCError()290 bool CheckALCError() 291 { _alc_error_code = alcGetError(_device); return (_alc_error_code != ALC_NO_ERROR); } 292 GetALError()293 ALenum GetALError() 294 { return _al_error_code; } 295 GetALCError()296 ALCenum GetALCError() 297 { return _alc_error_code; } 298 299 ///! \brief Returns a string representation of the most recently fetched OpenAL error code 300 const std::string CreateALErrorString(); 301 302 //! \brief Returns a string representation of the most recently fetched OpenAL context error code 303 const std::string CreateALCErrorString(); 304 //@} 305 306 //! \brief Prints information about the audio properties and settings of the user's machine 307 void DEBUG_PrintInfo(); 308 309 private: 310 //! \note Constructors are kept private since this class is a singleton 311 //@{ 312 AudioEngine(); 313 AudioEngine(const AudioEngine &game_audio); 314 //@} 315 316 //! \brief The global volume level of all sounds (0.0f is mute, 1.0f is max) 317 float _sound_volume; 318 319 //! \brief The global volume level of all music (0.0f is mute, 1.0f is max) 320 float _music_volume; 321 322 //! \brief The OpenAL device currently being utilized by the audio engine 323 ALCdevice* _device; 324 325 //! \brief The current OpenAL context that the audio engine is using 326 ALCcontext* _context; 327 328 //! \brief Holds the most recently fetched OpenAL error code 329 ALenum _al_error_code; 330 331 //! \brief Holds the most recently fetched OpenAL context error code 332 ALCenum _alc_error_code; 333 334 //! \brief Contains the maximum number of available audio sources that can exist simultaneously 335 uint16 _max_sources; 336 337 //! \brief The listener properties used by audio which plays in a multi-dimensional space 338 //@{ 339 float _listener_position[3]; 340 float _listener_velocity[3]; 341 float _listener_orientation[3]; 342 //@} 343 344 //! \brief A pointer to the last music descriptor which was played 345 MusicDescriptor* _active_music; 346 347 //! \brief Contains all available audio sources 348 std::vector<private_audio::AudioSource*> _audio_sources; 349 350 //! \brief Holds all active audio effects 351 std::list<private_audio::AudioEffect*> _audio_effects; 352 353 /** \brief Lists of pointers to all audio descriptor objects which have been created by the user 354 *** These lists are kept so that when the global sound or music volume levels are changed, all 355 *** sound and music objects will also have their volumes updated. 356 **/ 357 //@{ 358 std::list<SoundDescriptor*> _registered_sounds; 359 std::list<MusicDescriptor*> _registered_music; 360 //@} 361 362 /** \brief A LRU cache of audio which is managed internally by the audio engine 363 *** The purpose of this cache is to allow the user to quickly and easily play 364 *** sounds and music without having to maintain a Sound//MusicDescriptor object in memory. 365 *** This is used, for example, by script functions which simply want to play a sound to 366 *** indicate an action or event has occurred. 367 *** 368 *** The audio cache is a LRU (least recently used) structure, meaning that if an 369 *** entry needs to be evicted or replaced to make room for another, the least 370 *** recently used sound or music is deleted from the cache (as long as it is not playing). 371 *** The key in the STL map is the filename for the audio contained within the cache, while 372 *** the second is a container wrapping the audio descriptor pointer and the LRU time. 373 **/ 374 std::map<std::string, private_audio::AudioCacheElement> _audio_cache; 375 376 /** \brief The maximum number of entries that are allowed within the audio cache 377 *** The default size is set to 1/4th of _max_sources 378 **/ 379 uint16 _max_cache_size; 380 381 /** \brief Acquires an available audio source that may be used 382 *** \return A pointer to the available source, or NULL if no available source could be found 383 *** \todo Add an algoihtm to give priority to some sounds/music over others. 384 **/ 385 private_audio::AudioSource* _AcquireAudioSource(); 386 387 /** \brief A helper function to LoadSound and LoadMusic that takes care of the messy details of cache managment 388 *** \param audio A pointer to a newly created, unitialized AudioDescriptor object to load into the cache 389 *** \param filename The filename of the audio to load 390 *** \return True if the audio was successfully added to the cache, false if it was not. 391 *** \note If this function returns false, you should delete the pointer that you passed to it. 392 **/ 393 bool _LoadAudio(AudioDescriptor* audio, const std::string& filename); 394 }; // class AudioEngine : public hoa_utils::Singleton<AudioEngine> 395 396 } // namespace hoa_audio 397 398 #endif // __AUDIO_HEADER__ 399