Open Source Tomb Raider Engine
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SoundAL.cpp 6.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*!
  2. * \file src/system/SoundAL.cpp
  3. * \brief This is the OpenAL audio manager Implementation
  4. *
  5. * \author Mongoose
  6. * \author xythobuz
  7. */
  8. #ifdef __APPLE__
  9. #include <OpenAL/al.h>
  10. #else
  11. #include <AL/al.h>
  12. #endif
  13. #include <AL/alut.h>
  14. #include "global.h"
  15. #include "Log.h"
  16. #include "system/SoundAL.h"
  17. const static float soundTravelSectors = 15.0f;
  18. const static float referenceDistance = 1024.0f;
  19. const static float maxDistance = referenceDistance * soundTravelSectors;
  20. bool SoundAL::init = false;
  21. bool SoundAL::enabled = true;
  22. float SoundAL::volume = 1.0f;
  23. std::vector<unsigned int> SoundAL::buffers;
  24. std::vector<unsigned int> SoundAL::sources;
  25. std::vector<unsigned int> SoundAL::listenerSources;
  26. glm::vec3 SoundAL::lastPosition(0.0f, 0.0f, 0.0f);
  27. int SoundAL::initialize() {
  28. if (init) {
  29. Log::get(LOG_WARNING) << "SoundAL Warning: Already initialized..." << Log::endl;
  30. return 0;
  31. }
  32. ALCdevice* device = alcOpenDevice(nullptr);
  33. ALCcontext* context = alcCreateContext(device, nullptr);
  34. alcMakeContextCurrent(context);
  35. if (alutInitWithoutContext(nullptr, nullptr) == AL_FALSE) {
  36. Log::get(LOG_ERROR) << "SoundAL Error: " << alutGetErrorString(alutGetError()) << Log::endl;
  37. return -1;
  38. }
  39. init = true;
  40. setVolume(volume);
  41. alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
  42. lastPosition = glm::vec3(0.0f, 0.0f, 0.0f);
  43. glm::vec3 at(0.0f, 0.0f, -1.0f);
  44. glm::vec3 up(0.0f, 1.0f, 0.0f);
  45. listenAt(lastPosition, at, up);
  46. return 0;
  47. }
  48. void SoundAL::shutdown() {
  49. if (!init) {
  50. Log::get(LOG_ERROR) << "SoundAL Error: Shutdown but not initialized!" << Log::endl;
  51. return;
  52. }
  53. clear();
  54. init = false;
  55. if (alutExit() == AL_FALSE)
  56. Log::get(LOG_ERROR) << "SoundAL Error: " << alutGetErrorString(alutGetError()) << Log::endl;
  57. }
  58. void SoundAL::clear() {
  59. if (!init) {
  60. Log::get(LOG_ERROR) << "SoundAL Error: Clear but not initialized!" << Log::endl;
  61. return;
  62. }
  63. stopAll();
  64. alGetError();
  65. alDeleteSources(sources.size(), &sources[0]);
  66. sources.clear();
  67. if (alGetError() != AL_NO_ERROR) {
  68. Log::get(LOG_ERROR) << "SoundAL: Error while deleting sources!" << Log::endl;
  69. }
  70. alGetError();
  71. alDeleteSources(listenerSources.size(), &listenerSources[0]);
  72. listenerSources.clear();
  73. if (alGetError() != AL_NO_ERROR) {
  74. Log::get(LOG_ERROR) << "SoundAL: Error while deleting listener sources!" << Log::endl;
  75. }
  76. alGetError();
  77. alDeleteBuffers(buffers.size(), &buffers[0]);
  78. buffers.clear();
  79. if (alGetError() != AL_NO_ERROR) {
  80. Log::get(LOG_ERROR) << "SoundAL: Error while deleting buffers!" << Log::endl;
  81. }
  82. lastPosition = glm::vec3(0.0f, 0.0f, 0.0f);
  83. glm::vec3 at(0.0f, 0.0f, -1.0f);
  84. glm::vec3 up(0.0f, 1.0f, 0.0f);
  85. listenAt(lastPosition, at, up);
  86. }
  87. int SoundAL::numBuffers() {
  88. return buffers.size();
  89. }
  90. int SoundAL::loadBuffer(unsigned char* buffer, unsigned int length) {
  91. if (!init) {
  92. Log::get(LOG_ERROR) << "SoundAL Error: Buffer load, but not initialized!" << Log::endl;
  93. return -1;
  94. }
  95. alGetError();
  96. unsigned int r = alutCreateBufferFromFileImage(buffer, length);
  97. if (r == AL_NONE) {
  98. Log::get(LOG_ERROR) << "SoundAL Error: " << alutGetErrorString(alutGetError()) << Log::endl;
  99. return -2;
  100. }
  101. buffers.push_back(r);
  102. return r;
  103. }
  104. int SoundAL::numSources(bool atListener) {
  105. if (atListener)
  106. return listenerSources.size();
  107. else
  108. return sources.size();
  109. }
  110. int SoundAL::addSource(int buffer, float volume, bool atListener, bool loop) {
  111. if (!init) {
  112. Log::get(LOG_ERROR) << "SoundAL Error: Adding source, but not initialized!" << Log::endl;
  113. return -1;
  114. }
  115. if ((buffer < 0) || (buffer >= buffers.size())) {
  116. Log::get(LOG_ERROR) << "SoundAL Error: Adding source, but '" << buffer
  117. << "' invalid (max '" << buffers.size() << "')!" << Log::endl;
  118. return -2;
  119. }
  120. unsigned int id;
  121. alGetError();
  122. alGenSources(1, &id);
  123. if (alGetError() != AL_NO_ERROR) {
  124. Log::get(LOG_ERROR) << "SoundAL Error: Could not create source!" << Log::endl;
  125. return -3;
  126. }
  127. alSourcei(id, AL_BUFFER, buffers.at(buffer));
  128. alSourcef(id, AL_GAIN, volume);
  129. alSourcef(id, AL_REFERENCE_DISTANCE, referenceDistance);
  130. alSourcef(id, AL_MAX_DISTANCE, maxDistance);
  131. if (loop)
  132. alSourcei(id, AL_LOOPING, AL_TRUE);
  133. if (atListener) {
  134. alSourcefv(id, AL_POSITION, &lastPosition[0]);
  135. listenerSources.push_back(id);
  136. return listenerSources.size() - 1;
  137. } else {
  138. sources.push_back(id);
  139. return sources.size() - 1;
  140. }
  141. }
  142. int SoundAL::sourceAt(int source, glm::vec3 pos) {
  143. if (!init) {
  144. Log::get(LOG_ERROR) << "SoundAL Error: Positioning source, but not initialized!" << Log::endl;
  145. return -1;
  146. }
  147. if ((source < 0) || (source >= sources.size())) {
  148. Log::get(LOG_ERROR) << "SoundAL: Can't position non-existing source!" << Log::endl;
  149. return -2;
  150. }
  151. alSourcefv(sources.at(source), AL_POSITION, &pos[0]);
  152. return 0;
  153. }
  154. void SoundAL::listenAt(glm::vec3 pos, glm::vec3 at, glm::vec3 up) {
  155. if (!init) {
  156. Log::get(LOG_ERROR) << "SoundAL Error: Positioning listener, but not initialized!" << Log::endl;
  157. return;
  158. }
  159. float orientation[6] = { at.x, at.y, at.z, up.x, up.y, up.z };
  160. alListenerfv(AL_POSITION, &pos[0]);
  161. alListenerfv(AL_ORIENTATION, orientation);
  162. for (auto& s : listenerSources) {
  163. alSourcefv(s, AL_POSITION, &pos[0]);
  164. }
  165. lastPosition = pos;
  166. }
  167. void SoundAL::play(int source, bool atListener) {
  168. if ((!init) || (!enabled))
  169. return;
  170. if (atListener) {
  171. if ((source >= 0) && (source < listenerSources.size()))
  172. alSourcePlay(listenerSources.at(source));
  173. else
  174. Log::get(LOG_ERROR) << "SoundAL: Can't play non-existing listener source!" << Log::endl;
  175. } else {
  176. if ((source >= 0) && (source < sources.size()))
  177. alSourcePlay(sources.at(source));
  178. else
  179. Log::get(LOG_ERROR) << "SoundAL: Can't play non-existing source!" << Log::endl;
  180. }
  181. }
  182. void SoundAL::stop(int source) {
  183. if (!init)
  184. return;
  185. if ((source >= 0) && (source < sources.size()))
  186. alSourceStop(sources.at(source));
  187. else
  188. Log::get(LOG_ERROR) << "SoundAL: Can't stop non-existing source!" << Log::endl;
  189. }
  190. void SoundAL::stopAll() {
  191. if (!init)
  192. return;
  193. alSourceStopv(sources.size(), &sources[0]);
  194. alSourceStopv(listenerSources.size(), &listenerSources[0]);
  195. }
  196. void SoundAL::setEnabled(bool on) {
  197. enabled = on;
  198. }
  199. bool SoundAL::getEnabled() {
  200. return enabled;
  201. }
  202. void SoundAL::setVolume(float vol) {
  203. volume = vol;
  204. if (init)
  205. alListenerf(AL_GAIN, volume);
  206. }
  207. float SoundAL::getVolume() {
  208. return volume;
  209. }