Open Source Tomb Raider Engine
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

SoundAL.cpp 6.2KB

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