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