Open Source Tomb Raider Engine
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

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. }