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_descriptor.h
12 *** \author Mois�s Ferrer Serra, byaku@allacrost.org
13 *** \author Tyler Olsen, roots@allacrost.org
14 *** \brief  Header file for audio descriptors, sources and buffers
15 ***
16 *** This code provides the interface for the sound and music descriptors, that
17 *** are the units for load and manage sounds in the engine.
18 ***
19 *** \note This code uses the OpenAL audio library. See http://www.openal.com/
20 *** ***************************************************************************/
21 
22 #ifndef __AUDIO_DESCRIPTOR_HEADER__
23 #define __AUDIO_DESCRIPTOR_HEADER__
24 
25 #ifdef __MACH__
26 	#include <OpenAL/al.h>
27 	#include <OpenAL/alc.h>
28 #else
29 	#include "al.h"
30 	#include "alc.h"
31 #endif
32 
33 #include "defs.h"
34 #include "utils.h"
35 
36 #include "audio_input.h"
37 #include "audio_stream.h"
38 
39 namespace hoa_audio {
40 
41 //! \brief The set of states that AudioDescriptor class objects may be in
42 enum AUDIO_STATE {
43 	//! Audio data is not loaded
44 	AUDIO_STATE_UNLOADED   = 0,
45 	//! Audio is loaded, but is stopped
46 	AUDIO_STATE_STOPPED    = 1,
47 	//! Audio is loaded and is presently playing
48 	AUDIO_STATE_PLAYING    = 2,
49 	//! Audio is loaded and was playing, but is now paused
50 	AUDIO_STATE_PAUSED     = 3
51 };
52 
53 //! \brief The possible ways for that a piece of audio data may be loaded
54 enum AUDIO_LOAD {
55 	//! \brief Load audio statically by placing the entire contents of the audio into a single OpenAL buffer
56 	AUDIO_LOAD_STATIC         = 0,
57 	//! \brief Stream the audio data from a file into a pair of OpenAL buffers
58 	AUDIO_LOAD_STREAM_FILE    = 1,
59 	//! \brief Stream the audio data from memory into a pair of OpenAL buffers
60 	AUDIO_LOAD_STREAM_MEMORY  = 2
61 };
62 
63 namespace private_audio {
64 
65 //! \brief The default buffer size (in bytes) for streaming buffers
66 const uint32 DEFAULT_BUFFER_SIZE = 8192;
67 
68 //! \brief The number of buffers to use for streaming audio descriptors
69 const uint32 NUMBER_STREAMING_BUFFERS = 4;
70 
71 /** ****************************************************************************
72 *** \brief Represents an OpenAL buffer
73 ***
74 *** A buffer in OpenAL is simply a structure which contains raw audio data.
75 *** Buffers must be attached to an OpenAL source in order to play. OpenAL
76 *** suppports an infinte number of buffers (as long as there is enough memory).
77 *** ***************************************************************************/
78 class AudioBuffer {
79 	friend class AudioEngine;
80 
81 public:
82 	AudioBuffer();
83 
84 	~AudioBuffer();
85 
86 	/** \brief Fills an OpenAL buffer with raw audio data
87 	*** \param data A pointer to the raw data to fill the buffer with
88 	*** \param format The format of the buffer data (mono/stereo, 8/16 bits per sample)
89 	*** \param size The size of the data in number of bytes
90 	*** \param frequency The audio frequency of the data in samples per second
91 	**/
FillBuffer(uint8 * data,ALenum format,uint32 size,uint32 frequency)92 	void FillBuffer(uint8* data, ALenum format, uint32 size, uint32 frequency)
93 		{ alBufferData(buffer, format, data, size, frequency); }
94 
95 	//! \brief Returns true if this class object holds a reference to a valid OpenAL buffer
IsValid()96 	bool IsValid() const
97 		{ return (alIsBuffer(buffer) == AL_TRUE); }
98 
99 	//! \brief The ID of the OpenAL buffer
100 	ALuint buffer;
101 }; // class AudioBuffer
102 
103 
104 /** ****************************************************************************
105 *** \brief Represents an OpenAL source
106 ***
107 *** OpenAL is designed to take care of the complexity of panning sound to
108 *** different speakers; it does this by storing the locations in 3d space of
109 *** both the physical sources that a sound might originate from (for example,
110 *** the point in space where two swords clang together), and also the 3d
111 *** location of the listener's "ears". A source in OpenAL is simply metadata
112 *** about the position of the sound; the actual sound itself comes from audio
113 *** data which is loaded into a buffer, and then played back through one of
114 *** these sources.
115 ***
116 *** This metadata includes properties like position, velocity,
117 *** etc. None of these are actually altered by OpenAL; OpenAL does not use
118 *** velocity to move the sound sources for us each game tick; rather, it simply
119 *** uses these to calculate sound itself (velocity is actually used for
120 *** calculating doppler effects). We are expected to fill these values with
121 *** appropriate position/velocity data to keep them in sync with the game
122 *** objects they represent.
123 ***
124 *** Those properties are not managed by this class, but rather by the
125 *** AudioDescriptor to which the source is attached. OpenAL (or rather, the
126 *** audio hardware) only allows a limited number of audio sources to exist at
127 *** one time, so we can't create a source for every piece of audio that is
128 *** loaded by the game. Therefore, we create as many sources as we can (up to
129 *** MAX_DEFAULT_AUDIO_SOURCES) and have the audio descriptors share between
130 *** sources as they need them.
131 ***
132 *** \note OpenAL sources are created and by the AudioEngine class, not within the
133 *** AudioSource constructor. The sources are, however, deleted by the destructor.
134 ***
135 *** \note You should never really need to call the IsValid() function when
136 *** retrieving a new AudioSource to use. This is because all AudioSource objects
137 *** created by AudioEngine are guaranteed to have a valid OpenAL source contained
138 *** by the object.
139 *** ***************************************************************************/
140 class AudioSource {
141 public:
142 	//! \param al_source A valid OpenAL source that has been generated
AudioSource(ALuint al_source)143 	AudioSource(ALuint al_source) :
144 		source(al_source), owner(NULL) {}
145 
146 	~AudioSource();
147 
148 	//! \brief Returns true if this class object holds a reference to a valid OpenAL source
IsValid()149 	bool IsValid() const
150 		{ return (alIsSource(source) == AL_TRUE); }
151 
152 	//! \brief Resets the default properties of the OpenAL sources and removes the owner
153 	void Reset();
154 
155 	//! \brief The ID of the OpenAL source
156 	ALuint source;
157 
158 	//! \brief Pointer to the descriptor associated to this source.
159 	AudioDescriptor* owner;
160 }; // class AudioSource
161 
162 } // namespace private_audio
163 
164 /** ****************************************************************************
165 *** \brief An abstract class for representing a piece of audio
166 ***
167 *** This class takes the OpenAL buffer and source concepts and ties them
168 *** together. This class enables playback, streaming, 3D source positioning,
169 *** and many other features for manipulating a piece of audio. Sounds and
170 *** music are defined by classes which derive from this class.
171 ***
172 *** \note Some features of this class are only available if the audio is loaded
173 *** in a streaming manner.
174 ***
175 *** \note You should <b>never</b> trust the value of _state when it is set to
176 *** AUDIO_STATE_PLAYING. This is because the audio may stop playing on its own
177 *** after the play state has been set. Instead, you should call the GetState()
178 *** method, which guarantees that the correct state value is set.
179 ***
180 *** \todo This class either needs to have its copy assignment operator defined
181 *** or it should be made private.
182 *** ***************************************************************************/
183 class AudioDescriptor {
184 	friend class AudioEngine;
185 
186 public:
187 	AudioDescriptor();
188 
~AudioDescriptor()189 	virtual ~AudioDescriptor()
190 		{ FreeAudio(); }
191 
192 	AudioDescriptor(const AudioDescriptor& copy);
193 
194 	/** \brief Loads a new piece of audio data from a file
195 	*** \param filename The name of the file that contains the new audio data (should have a .wav or .ogg file extension)
196 	*** \param load_type The type of loading to perform (default == AUDIO_LOAD_STATIC)
197 	*** \param stream_buffer_size If the loading type is streaming, the buffer size to use (default == DEFAULT_BUFFER_SIZE)
198 	*** \return True if the audio was succesfully loaded, false if there was an error
199 	***
200 	*** The action taken by this function depends on the load type selected. For static sounds, a single OpenAL buffer is
201 	*** filled. For streaming, the file/memory is prepared.
202 	**/
203 	virtual bool LoadAudio(const std::string& filename, AUDIO_LOAD load_type = AUDIO_LOAD_STATIC, uint32 stream_buffer_size = private_audio::DEFAULT_BUFFER_SIZE);
204 
205 	/** \brief Frees all data resources and resets class parameters
206 	***
207 	*** It resets the _state and _offset class members, as well as deleting _data, _stream, _input, _buffer, and resets _source.
208 	**/
209 	void FreeAudio();
210 
GetFilename()211 	const std::string GetFilename() const
212 		{ if (_input == NULL) return ""; else return _input->GetFilename(); }
213 
214 	//! \brief Returns true if this audio represents a sound, false if the audio represents a music piece
215 	virtual bool IsSound() const = 0;
216 
217 	/** \brief Returns the state of the audio,
218 	*** \note This function does not simply return the _state member. If _state is set
219 	*** to AUDIO_STATE_PLAYING, the source state is queried to assure that it is still
220 	*** playing.
221 	**/
222 	AUDIO_STATE GetState();
223 
224 	/** \name Audio State Manipulation Functions
225 	*** \brief Performs specified operation on the audio
226 	***
227 	*** These functions will only take effect when the audio is in the state(s) specified below:
228 	*** - PlayAudio()     <==>   all states but the playing state
229 	*** - PauseAudio()    <==>   playing state
230 	*** - ResumeAudio()   <==>   paused state
231 	*** - StopAudio()     <==>   all states but the stopped state
232 	*** - RewindAudio()   <==>   all states
233 	**/
234 	//@{
235 	virtual void Play();
236 	virtual void Stop();
237 	virtual void Pause();
238 	virtual void Resume();
239 	void Rewind();
240 	//@}
241 
IsLooping()242 	bool IsLooping() const
243 		{ return _looping; }
244 
245 	/** \brief Enables/disables looping for this audio
246 	*** \param loop True to enable looping, false to disable it.
247 	**/
248 	void SetLooping(bool loop);
249 
250 	/** \brief Sets the starting loop point, used for customized looping
251 	*** \param loop_start The sample position for the start loop point
252 	*** \note This function is only valid if the audio has been loaded with streaming support
253 	**/
254 	void SetLoopStart(uint32 loop_start);
255 
256 	/** \brief Sets the ending loop point, used for customized looping
257 	*** \param loop_start The sample position for the end loop point
258 	*** \note This function is only valid if the audio has been loaded with streaming support
259 	**/
260 	void SetLoopEnd(uint32 loop_end);
261 
262 	/** \brief Seeks to the requested sample position
263 	*** \param sample The sample position to seek to
264 	**/
265 	void SeekSample(uint32 sample);
266 
267 	/** \brief Seeks to the requested playback time
268 	*** \param second The time to seek to, in seconds (e.g. 4.5f == 4.5 second mark)
269 	*** \note The position is aligned with a proper sample position, so the seek is not fully
270 	*** accurate.
271 	**/
272 	void SeekSecond(float second);
273 
274 	//! \brief Returns the volume level for this audio
GetVolume()275 	float GetVolume() const
276 		{ return _volume; }
277 
278 	/** \brief Sets the volume for this particular audio piece
279 	*** \param volume The volume level to set, ranging from [0.0f, 1.0f]
280 	**/
281 	virtual void SetVolume(float volume) = 0;
282 
283 	/** \name Functions for 3D Spatial Audio
284 	*** These functions manipulate and retrieve the 3d properties of the audio. Note that only audio which
285 	*** are mono channel will be affected by these methods. Stereo channel audio will see no difference.
286 	**/
287 	//@{
288 	void SetPosition(const float position[3]);
289 	void SetVelocity(const float velocity[3]);
290 	void SetDirection(const float direction[3]);
291 
GetPosition(float position[3])292 	void GetPosition(float position[3]) const
293 		{ memcpy(&position, _position, sizeof(float) * 3); }
294 
GetVelocity(float velocity[3])295 	void GetVelocity(float velocity[3]) const
296 		{ memcpy(&velocity, _velocity, sizeof(float) * 3); }
297 
GetDirection(float direction[3])298 	void GetDirection(float direction[3]) const
299 		{ memcpy(&direction, _direction, sizeof(float) * 3); }
300 	//@}
301 
302 	//! \brief Prints various properties about the audio data managed by this class
303 	void DEBUG_PrintInfo();
304 
305 protected:
306 	//! \brief The current state of the audio (playing, stopped, etc.)
307 	AUDIO_STATE _state;
308 
309 	//! \brief A pointer to the buffer(s) being used by the audio (1 buffer for static sounds, 2 for streamed ones)
310 	private_audio::AudioBuffer* _buffer;
311 
312 	//! \brief A pointer to the source object being used by the audio
313 	private_audio::AudioSource* _source;
314 
315 	//! \brief A pointer to the input object that manages the data
316 	private_audio::AudioInput* _input;
317 
318 	//! \brief A pointer to the stream object (set to NULL if the audio was loaded statically)
319 	private_audio::AudioStream* _stream;
320 
321 	//! \brief A pointer to where the data is streamed to
322 	uint8* _data;
323 
324 	//! \brief The format of the audio (mono/stereo, 8/16 bits per second).
325 	ALenum _format;
326 
327 	//! \brief Flag for indicating if the audio should loop or not
328 	bool _looping;
329 
330 	//! \brief The audio position that was last seeked, in samples.
331 	uint32 _offset;
332 
333 	/** \brief The volume of the audio, ranging from 0.0f to 1.0f
334 	*** This isn't actually the true volume of the audio, but rather the modulation
335 	*** value of the global sound or music volume level. For example, if this object
336 	*** represented a sound and the volume was set to 0.75f, and the global sound
337 	*** volume in AudioEngine was 0.80f, the true volume would be (0.75 * 0.8 = 0.6).
338 	*** By default this member is set to 1.0f.
339 	**/
340 	float _volume;
341 
342 	//! \brief Size of the streaming buffer, if the audio was loaded for streaming
343 	uint32 _stream_buffer_size;
344 
345 	//! \brief The 3D orientation properties of the audio
346 	//@{
347 	float _position[3];
348 	float _velocity[3];
349 	float _direction[3];
350 	//@}
351 
352 	/** \brief Sets the local volume control for this particular audio piece
353 	*** \param volume The volume level to set, ranging from [0.0f, 1.0f]
354 	*** This should be thought of as a helper function to the SetVolume methods
355 	*** for the derived classes, which modulate the volume level of the sound/music
356 	*** by the global sound and music volume controls in the AudioEngine class.
357 	**/
358 	void _SetVolumeControl(float volume);
359 
360 private:
361 	/** \brief Updates the audio during playback
362 	*** This function is only useful for streaming audio that is currently in the play state. If either of these two
363 	*** conditions are not met, the function will return since it has nothing to do.
364 	**/
365 	void _Update();
366 
367 	/** \brief Acquires an audio source for playback
368 	*** This function is called whenever an audio piece is loaded and whenever the Play operation is specified on
369 	*** the audio, but the audio currently does not have a source. It is not guaranteed that the source acquisition
370 	*** will be successful, as all other sources may be occupied by other audio.
371 	**/
372 	void _AcquireSource();
373 
374 	/** \brief Sets all of the relevant properties for the OpenAL source
375 	*** This function should be called whenever a new source is allocated for the audio to use.
376 	*** It sets all of the necessary properties for the OpenAL source, such as the volume (gain),
377 	*** enables looping if requested, etc.
378 	**/
379 	void _SetSourceProperties();
380 
381 	/** \brief Prepares streaming buffers when a new source is acquired or after a seeking operation.
382 	*** This is a special case, since the already queued buffers must be unqueued, and the new
383 	*** ones must be refilled. This function should only be called for streaming audio.
384 	**/
385 	void _PrepareStreamingBuffers();
386 }; // class AudioDescriptor
387 
388 
389 /** ****************************************************************************
390 *** \brief An class for representing a piece of sound audio
391 ***
392 *** Sounds are almost always in the .wav file format.
393 *** ***************************************************************************/
394 class SoundDescriptor : public AudioDescriptor {
395 public:
396 	SoundDescriptor();
397 
398 	~SoundDescriptor();
399 
400 	SoundDescriptor(const SoundDescriptor& copy);
401 
IsSound()402 	bool IsSound() const
403 		{ return true; }
404 
405 	/** \brief Sets the volume of the sound
406 	*** \param volume The volume to set the sound, value between [0.0, 1.0]
407 	*** This value will be modulated by the global sound volume found in the
408 	*** AudioEngine class.
409 	**/
410 	void SetVolume(float volume);
411 }; // class SoundDescriptor : public AudioDescriptor
412 
413 
414 /** ****************************************************************************
415 *** \brief A class for representing a piece of music audio
416 ***
417 *** Music is almost always in the .ogg file format.
418 ***
419 *** \note Looping is enabled for music by default
420 *** ***************************************************************************/
421 class MusicDescriptor : public AudioDescriptor {
422 public:
423 	MusicDescriptor();
424 
425 	~MusicDescriptor();
426 
427 	MusicDescriptor(const MusicDescriptor& copy);
428 
429 	bool LoadAudio(const std::string& filename, AUDIO_LOAD load_type = AUDIO_LOAD_STREAM_FILE, uint32 stream_buffer_size = private_audio::DEFAULT_BUFFER_SIZE);
430 
IsSound()431 	bool IsSound() const
432 		{ return false; }
433 
434 	/** \brief Sets the volume of the music
435 	*** \param volume The volume to set the music, value between [0.0, 1.0]
436 	*** This value will be modulated by the global music volume found in the
437 	*** AudioEngine class.
438 	**/
439 	void SetVolume(float volume);
440 
441 	/** \brief Plays the selected music, after stopping the previous playing music
442 	*** No two pieces of music are allowed to play simultaneously, meaning that
443 	*** calling this method on one music also effectively calls stop on another
444 	*** piece of music that was playing when the call was made
445 	**/
446 	void Play();
447 }; // class MusicDescriptor : public AudioDescriptor
448 
449 } // namespace hoa_audio
450 
451 #endif
452