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 ©); 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 ©); 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 ©); 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