Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

SoundAL.cpp 7.2KB

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