1 ////////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2011 by The Allacrost Project
3 //            Copyright (C) 2012-2016 by Bertram (Valyria Tear)
4 //                         All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software
7 // and you may modify it and/or redistribute it under the terms of this license.
8 // See http://www.gnu.org/copyleft/gpl.html for details.
9 ////////////////////////////////////////////////////////////////////////////////
10 
11 /** ****************************************************************************
12 *** \file   audio_descriptor.h
13 *** \author Mois�s Ferrer Serra, byaku@allacrost.org
14 *** \author Tyler Olsen, roots@allacrost.org
15 *** \author Yohann Ferreira, yohann ferreira orange fr
16 *** \brief  Header file for audio descriptors, sources and buffers
17 ***
18 *** This code provides the interface for the sound and music descriptors, that
19 *** are the units for load and manage sounds in the engine.
20 ***
21 *** \note This code uses the OpenAL audio library. See http://www.openal.com/
22 *** ***************************************************************************/
23 
24 #ifndef __AUDIO_DESCRIPTOR_HEADER__
25 #define __AUDIO_DESCRIPTOR_HEADER__
26 
27 #include "audio_input.h"
28 #include "audio_stream.h"
29 #include "audio_effects.h"
30 
31 // OpenAL includes
32 #ifdef __APPLE__
33 #include <OpenAL/al.h>
34 #include <OpenAL/alc.h>
35 #else
36 #include "al.h"
37 #include "alc.h"
38 #endif
39 
40 #include <vector>
41 
42 namespace vt_mode_manager {
43 class GameMode;
44 }
45 
46 namespace vt_audio
47 {
48 
49 class AudioDescriptor;
50 
51 //! \brief The set of states that AudioDescriptor class objects may be in
52 enum AUDIO_STATE {
53     //! Audio data is not loaded
54     AUDIO_STATE_UNLOADED   = 0,
55     //! Audio is loaded, but is stopped
56     AUDIO_STATE_STOPPED    = 1,
57     //! Audio is loaded and is presently playing
58     AUDIO_STATE_PLAYING    = 2,
59     //! Audio is loaded and was playing, but is now paused
60     AUDIO_STATE_PAUSED     = 3,
61     //! Audio is fading out
62     AUDIO_STATE_FADE_OUT   = 4,
63     //! Audio is fading in
64     AUDIO_STATE_FADE_IN    = 5,
65 };
66 
67 //! \brief The possible ways for that a piece of audio data may be loaded
68 enum AUDIO_LOAD {
69     //! \brief Load audio statically by placing the entire contents of the audio into a single OpenAL buffer
70     AUDIO_LOAD_STATIC         = 0,
71     //! \brief Stream the audio data from a file into a pair of OpenAL buffers
72     AUDIO_LOAD_STREAM_FILE    = 1,
73     //! \brief Stream the audio data from memory into a pair of OpenAL buffers
74     AUDIO_LOAD_STREAM_MEMORY  = 2
75 };
76 
77 //! \brief ALfloat per 3D OpenAL sound vectors (position, direction, velocity)
78 const uint32_t ALFLOAT3D = 3;
79 typedef ALfloat ALfloatArray[ALFLOAT3D];
80 
81 namespace private_audio
82 {
83 
84 class AudioEffect;
85 
86 //! \brief The default buffer size (in bytes) for streaming buffers
87 const uint32_t DEFAULT_BUFFER_SIZE = 8192;
88 
89 //! \brief The number of buffers to use for streaming audio descriptors
90 const uint32_t NUMBER_STREAMING_BUFFERS = 4;
91 
92 /** ****************************************************************************
93 *** \brief Represents an OpenAL buffer
94 ***
95 *** A buffer in OpenAL is simply a structure which contains raw audio data.
96 *** Buffers must be attached to an OpenAL source in order to play. OpenAL
97 *** suppports an infinte number of buffers (as long as there is enough memory).
98 *** ***************************************************************************/
99 class AudioBuffer
100 {
101     friend class AudioEngine;
102 
103 public:
104     AudioBuffer();
105 
106     ~AudioBuffer();
107 
108     /** \brief Fills an OpenAL buffer with raw audio data
109     *** \param data A pointer to the raw data to fill the buffer with
110     *** \param format The format of the buffer data (mono/stereo, 8/16 bits per sample)
111     *** \param size The size of the data in number of bytes
112     *** \param frequency The audio frequency of the data in samples per second
113     **/
FillBuffer(uint8_t * data,ALenum format,uint32_t size,uint32_t frequency)114     void FillBuffer(uint8_t *data, ALenum format, uint32_t size, uint32_t frequency) {
115         alBufferData(buffer, format, data, size, frequency);
116     }
117 
118     //! \brief Returns true if this class object holds a reference to a valid OpenAL buffer
IsValid()119     bool IsValid() const {
120         return (buffer != 0 && alIsBuffer(buffer) == AL_TRUE);
121     }
122 
123     //! \brief The ID of the OpenAL buffer
124     ALuint buffer;
125 }; // class AudioBuffer
126 
127 
128 /** ****************************************************************************
129 *** \brief Represents an OpenAL source
130 ***
131 *** OpenAL is designed to take care of the complexity of panning sound to
132 *** different speakers; it does this by storing the locations in 3d space of
133 *** both the physical sources that a sound might originate from (for example,
134 *** the point in space where two swords clang together), and also the 3d
135 *** location of the listener's "ears". A source in OpenAL is simply metadata
136 *** about the position of the sound; the actual sound itself comes from audio
137 *** data which is loaded into a buffer, and then played back through one of
138 *** these sources.
139 ***
140 *** This metadata includes properties like position, velocity,
141 *** etc. None of these are actually altered by OpenAL; OpenAL does not use
142 *** velocity to move the sound sources for us each game tick; rather, it simply
143 *** uses these to calculate sound itself (velocity is actually used for
144 *** calculating doppler effects). We are expected to fill these values with
145 *** appropriate position/velocity data to keep them in sync with the game
146 *** objects they represent.
147 ***
148 *** Those properties are not managed by this class, but rather by the
149 *** AudioDescriptor to which the source is attached. OpenAL (or rather, the
150 *** audio hardware) only allows a limited number of audio sources to exist at
151 *** one time, so we can't create a source for every piece of audio that is
152 *** loaded by the game. Therefore, we create as many sources as we can (up to
153 *** MAX_DEFAULT_AUDIO_SOURCES) and have the audio descriptors share between
154 *** sources as they need them.
155 ***
156 *** \note OpenAL sources are created and by the AudioEngine class, not within the
157 *** AudioSource constructor. The sources are, however, deleted by the destructor.
158 ***
159 *** \note You should never really need to call the IsValid() function when
160 *** retrieving a new AudioSource to use. This is because all AudioSource objects
161 *** created by AudioEngine are guaranteed to have a valid OpenAL source contained
162 *** by the object.
163 *** ***************************************************************************/
164 class AudioSource
165 {
166 public:
167     //! \param al_source A valid OpenAL source that has been generated
AudioSource(ALuint al_source)168     explicit AudioSource(ALuint al_source) :
169         source(al_source), owner(nullptr) {}
170 
171     ~AudioSource();
172 
173     //! \brief Returns true if this class object holds a reference to a valid OpenAL source
IsValid()174     bool IsValid() const {
175         return (alIsSource(source) == AL_TRUE);
176     }
177 
178     //! \brief Resets the default properties of the OpenAL sources and removes the owner
179     void Reset();
180 
181     //! \brief The ID of the OpenAL source
182     ALuint source;
183 
184     //! \brief Pointer to the descriptor associated to this source.
185     AudioDescriptor *owner;
186 }; // class AudioSource
187 
188 } // namespace private_audio
189 
190 /** ****************************************************************************
191 *** \brief An abstract class for representing a piece of audio
192 ***
193 *** This class takes the OpenAL buffer and source concepts and ties them
194 *** together. This class enables playback, streaming, 3D source positioning,
195 *** and many other features for manipulating a piece of audio. Sounds and
196 *** music are defined by classes which derive from this class.
197 ***
198 *** \note Some features of this class are only available if the audio is loaded
199 *** in a streaming manner.
200 ***
201 *** \note You should <b>never</b> trust the value of _state when it is set to
202 *** AUDIO_STATE_PLAYING. This is because the audio may stop playing on its own
203 *** after the play state has been set. Instead, you should call the GetState()
204 *** method, which guarantees that the correct state value is set.
205 ***
206 *** \todo This class either needs to have its copy assignment operator defined
207 *** or it should be made private.
208 *** ***************************************************************************/
209 class AudioDescriptor
210 {
211     friend class AudioEngine;
212 
213 public:
214     AudioDescriptor();
215 
~AudioDescriptor()216     virtual ~AudioDescriptor() {
217         FreeAudio();
218     }
219 
220     AudioDescriptor(const AudioDescriptor &copy);
221 
222     /** \brief Loads a new piece of audio data from a file
223     *** \param filename The name of the file that contains the new audio data (should have a .wav or .ogg file extension)
224     *** \param load_type The type of loading to perform (default == AUDIO_LOAD_STATIC)
225     *** \param stream_buffer_size If the loading type is streaming, the buffer size to use (default == DEFAULT_BUFFER_SIZE)
226     *** \return True if the audio was successfully loaded, false if there was an error
227     ***
228     *** The action taken by this function depends on the load type selected. For static sounds, a single OpenAL buffer is
229     *** filled. For streaming, the file/memory is prepared.
230     **/
231     virtual bool LoadAudio(const std::string &filename, AUDIO_LOAD load_type = AUDIO_LOAD_STATIC, uint32_t stream_buffer_size = private_audio::DEFAULT_BUFFER_SIZE);
232 
233     /** \brief Frees all data resources and resets class parameters
234     ***
235     *** It resets the _state and _offset class members, as well as deleting _data, _stream, _input, _buffer, and resets _source.
236     **/
237     void FreeAudio();
238 
GetFilename()239     const std::string GetFilename() const {
240         if(_input == nullptr) return std::string();
241         else return _input->GetFilename();
242     }
243 
244     //! \brief Returns true if this audio represents a sound, false if the audio represents a music piece
245     virtual bool IsSound() const = 0;
246 
247     //! \brief Returns the state of the audio.
GetState()248     AUDIO_STATE GetState() {
249         return _state;
250     }
251 
252     /** \name Audio State Manipulation Functions
253     *** \brief Performs specified operation on the audio
254     ***
255     *** These functions will only take effect when the audio is in the state(s) specified below:
256     *** - PlayAudio()     <==>   all states but the playing state
257     *** - PauseAudio()    <==>   playing state
258     *** - ResumeAudio()   <==>   paused state
259     *** - StopAudio()     <==>   all states but the stopped state
260     *** - RewindAudio()   <==>   all states
261     **/
262     //@{
263     virtual bool Play();
264     virtual void Stop();
265     virtual void Pause();
266     virtual void Resume();
267     void Rewind();
268     //@}
269 
IsLooping()270     bool IsLooping() const {
271         return _looping;
272     }
273 
274     /** \brief Enables/disables looping for this audio
275     *** \param loop True to enable looping, false to disable it.
276     **/
277     void SetLooping(bool loop);
278 
279     /** \brief Sets the starting loop point, used for customized looping
280     *** \param loop_start The sample position for the start loop point
281     *** \note This function is only valid if the audio has been loaded with streaming support
282     **/
283     void SetLoopStart(uint32_t loop_start);
284 
285     /** \brief Sets the ending loop point, used for customized looping
286     *** \param loop_start The sample position for the end loop point
287     *** \note This function is only valid if the audio has been loaded with streaming support
288     **/
289     void SetLoopEnd(uint32_t loop_end);
290 
291     /** \brief Seeks to the requested sample position
292     *** \param sample The sample position to seek to
293     **/
294     void SeekSample(uint32_t sample);
295 
296     /** \brief Seeks to the requested playback time
297     *** \param second The time to seek to, in seconds (e.g. 4.5f == 4.5 second mark)
298     *** \note The position is aligned with a proper sample position, so the seek is not fully
299     *** accurate.
300     **/
301     void SeekSecond(float second);
302 
303     //! \brief Gets the current sample number (track offset)
304     uint32_t GetCurrentSampleNumber() const;
305 
306     //! \brief Returns the volume level for this audio
GetVolume()307     float GetVolume() const {
308         return _volume;
309     }
310 
311     /** \brief Sets the volume for this particular audio piece
312     *** \param volume The volume level to set, ranging from [0.0f, 1.0f]
313     **/
314     virtual void SetVolume(float volume) = 0;
315 
316     /** \name Functions for 3D Spatial Audio
317     *** These functions manipulate and retrieve the 3d properties of the audio. Note that only audio which
318     *** are mono channel will be affected by these methods. Stereo channel audio will see no difference.
319     **/
320     //@{
321     void SetPosition(const ALfloat position[ALFLOAT3D]);
322     void SetVelocity(const ALfloat velocity[ALFLOAT3D]);
323     void SetDirection(const ALfloat direction[ALFLOAT3D]);
324 
325     //! \brief Returns the pointer to corresponding ALfloat parameter array
GetPosition()326     const ALfloatArray& GetPosition() const {
327         return _position;
328     }
GetVelocity()329     const ALfloatArray& GetVelocity() const {
330         return _velocity;
331     }
GetDirection()332     const ALfloatArray& GetDirection() const {
333         return _direction;
334     }
335     //@}
336 
337     /**
338     *** Adds a new game mode owning the audio descriptor.
339     *** It is done to permit the engine to automatically free audio files
340     *** when the game mode is deleted.
341     *** This function won't add nullptr reference and won't permit duplicate owners.
342     **/
343     void AddGameModeOwner(vt_mode_manager::GameMode *gm);
344 
345     /**
346     *** Adds multiple owners at once.
347     *** @see AddOwner()
348     **/
349     void AddGameModeOwners(std::vector<vt_mode_manager::GameMode *>& owners);
350 
351     /**
352     *** Remove a game mode reference from the audio descriptor owners,
353     *** and checks whether the file data can be freed.
354     *** \returns whether the descriptor should be removed from the cache.
355     **/
356     bool RemoveGameModeOwner(vt_mode_manager::GameMode *gm);
357 
358     /**
359     *** Get the list of game mode claiming ownership over the audio descriptor.
360     **/
GetGameModeOwners()361     std::vector<vt_mode_manager::GameMode *>* GetGameModeOwners() {
362         return &_game_mode_owners;
363     }
364 
365     /** \brief Fades a music or sound in as it plays
366     *** \param audio A reference to the music or sound to fade in
367     *** \param time The amount of time that the fade should last for, in seconds
368     **/
369     void FadeIn(float time);
370 
371     /** \brief Fades a music or sound out as it finisheds
372     *** \param audio A referenece to the music or sound to fade out
373     *** \param time The amount of time that the fade should last for, in seconds
374     **/
375     void FadeOut(float time);
376 
377     //! Tells whether the audio descriptor is fading out.
378     bool IsFadingOut();
379 
380     //! \brief Remove effects.
381     void RemoveEffects();
382 
383     //! \brief Prints various properties about the audio data managed by this class
384     void DEBUG_PrintInfo();
385 
386 protected:
387     //! \brief The current state of the audio (playing, stopped, etc.)
388     AUDIO_STATE _state;
389 
390     //! \brief A pointer to the buffer(s) being used by the audio (1 buffer for static sounds, 2 for streamed ones)
391     private_audio::AudioBuffer *_buffer;
392 
393     //! \brief A pointer to the source object being used by the audio
394     private_audio::AudioSource *_source;
395 
396     //! \brief A pointer to the input object that manages the data
397     private_audio::AudioInput *_input;
398 
399     //! \brief A pointer to the stream object (set to nullptr if the audio was loaded statically)
400     private_audio::AudioStream *_stream;
401 
402     //! \brief A pointer to where the data is streamed to
403     uint8_t *_data;
404 
405     //! \brief The format of the audio (mono/stereo, 8/16 bits per second).
406     ALenum _format;
407 
408     //! \brief Flag for indicating if the audio should loop or not
409     bool _looping;
410 
411     //! \brief The audio position that was last seeked, in samples.
412     uint32_t _offset;
413 
414     /** \brief The volume of the audio, ranging from 0.0f to 1.0f
415     *** This isn't actually the true volume of the audio, but rather the modulation
416     *** value of the global sound or music volume level. For example, if this object
417     *** represented a sound and the volume was set to 0.75f, and the global sound
418     *** volume in AudioEngine was 0.80f, the true volume would be (0.75 * 0.8 = 0.6).
419     *** By default this member is set to 1.0f.
420     **/
421     float _volume;
422 
423     //! \brief Keeps in memory the fade out or in time.
424     float _fade_effect_time;
425 
426     //! \brief The volume of the audio when the fade effect was registered
427     float _original_volume;
428 
429     //! \brief Size of the streaming buffer, if the audio was loaded for streaming
430     uint32_t _stream_buffer_size;
431 
432     //! \brief The 3D orientation properties of the audio
433     //@{
434     ALfloat _position[ALFLOAT3D];
435     ALfloat _velocity[ALFLOAT3D];
436     ALfloat _direction[ALFLOAT3D];
437     //@}
438 
439     /** \brief The game modes loading the audio file.
440     *** On can usually free it whenever no owner is present for a given sound.
441     *** Note that data/sounds/musics are only freed when their owners are removed
442     *** and were the last in this list.
443     *** Musics and sounds that are never owned will have to be freed manually.
444     *** @see AddGameModeOwner(), RemoveGameModeOwner()
445     **/
446     std::vector<vt_mode_manager::GameMode *> _game_mode_owners;
447 
448     //! \brief Holds all active audio effects for this descriptor
449     std::vector<private_audio::AudioEffect *> _audio_effects;
450 
451     /** \brief Sets the local volume control for this particular audio piece
452     *** \param volume The volume level to set, ranging from [0.0f, 1.0f]
453     *** This should be thought of as a helper function to the SetVolume methods
454     *** for the derived classes, which modulate the volume level of the sound/music
455     *** by the global sound and music volume controls in the AudioEngine class.
456     **/
457     void _SetVolumeControl(float volume);
458 
459 private:
460     /** \brief Updates the audio during playback
461     *** This function is only useful for streaming audio that is currently in the play state. If either of these two
462     *** conditions are not met, the function will return since it has nothing to do.
463     **/
464     void _Update();
465 
466     //! \brief Handles the fading states volumes update.
467     void _HandleFadeStates();
468 
469     /** \brief Acquires an audio source for playback
470     *** This function is called whenever an audio piece is loaded and whenever the Play operation is specified on
471     *** the audio, but the audio currently does not have a source. It is not guaranteed that the source acquisition
472     *** will be successful, as all other sources may be occupied by other audio.
473     **/
474     void _AcquireSource();
475 
476     /** \brief Sets all of the relevant properties for the OpenAL source
477     *** This function should be called whenever a new source is allocated for the audio to use.
478     *** It sets all of the necessary properties for the OpenAL source, such as the volume (gain),
479     *** enables looping if requested, etc.
480     **/
481     void _SetSourceProperties();
482 
483     /** \brief Prepares streaming buffers when a new source is acquired or after a seeking operation.
484     *** This is a special case, since the already queued buffers must be unqueued, and the new
485     *** ones must be refilled. This function should only be called for streaming audio.
486     **/
487     void _PrepareStreamingBuffers();
488 }; // class AudioDescriptor
489 
490 
491 /** ****************************************************************************
492 *** \brief An class for representing a piece of sound audio
493 ***
494 *** Sounds are almost always in the .wav file format.
495 *** ***************************************************************************/
496 class SoundDescriptor : public AudioDescriptor
497 {
498 public:
499     SoundDescriptor();
500 
501     ~SoundDescriptor();
502 
503     SoundDescriptor(const SoundDescriptor &copy);
504 
IsSound()505     bool IsSound() const {
506         return true;
507     }
508 
509     /** \brief Sets the volume of the sound
510     *** \param volume The volume to set the sound, value between [0.0, 1.0]
511     *** This value will be modulated by the global sound volume found in the
512     *** AudioEngine class.
513     **/
514     void SetVolume(float volume);
515 
516     //! \brief Plays or restart the currently played sound.
517     bool Play();
518 }; // class SoundDescriptor : public AudioDescriptor
519 
520 
521 /** ****************************************************************************
522 *** \brief A class for representing a piece of music audio
523 ***
524 *** Music is almost always in the .ogg file format.
525 ***
526 *** \note Looping is enabled for music by default
527 *** ***************************************************************************/
528 class MusicDescriptor : public AudioDescriptor
529 {
530 public:
531     MusicDescriptor();
532 
533     ~MusicDescriptor();
534 
535     MusicDescriptor(const MusicDescriptor &copy);
536 
537     bool LoadAudio(const std::string &filename, AUDIO_LOAD load_type = AUDIO_LOAD_STREAM_FILE, uint32_t stream_buffer_size = private_audio::DEFAULT_BUFFER_SIZE);
538 
IsSound()539     bool IsSound() const {
540         return false;
541     }
542 
543     /** \brief Sets the volume of the music
544     *** \param volume The volume to set the music, value between [0.0, 1.0]
545     *** This value will be modulated by the global music volume found in the
546     *** AudioEngine class.
547     **/
548     void SetVolume(float volume);
549 
550     /** \brief Plays the selected music, after stopping the previous playing music
551     *** No two pieces of music are allowed to play simultaneously, meaning that
552     *** calling this method on one music also effectively calls stop on another
553     *** piece of music that was playing when the call was made
554     **/
555     bool Play();
556 }; // class MusicDescriptor : public AudioDescriptor
557 
558 } // namespace vt_audio
559 
560 #endif
561