ALRenderer.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. Copyright (c) 2013 Daniele Bartolini, Michele Rossi
  3. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  4. Permission is hereby granted, free of charge, to any person
  5. obtaining a copy of this software and associated documentation
  6. files (the "Software"), to deal in the Software without
  7. restriction, including without limitation the rights to use,
  8. copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the
  10. Software is furnished to do so, subject to the following
  11. conditions:
  12. The above copyright notice and this permission notice shall be
  13. included in all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #include "ALRenderer.h"
  24. #include "StringUtils.h"
  25. namespace crown
  26. {
  27. //-----------------------------------------------------------------------------
  28. static const char* al_error_to_string(ALenum error)
  29. {
  30. switch (error)
  31. {
  32. case AL_INVALID_ENUM: return "AL_INVALID_ENUM";
  33. case AL_INVALID_VALUE: return "AL_INVALID_VALUE";
  34. case AL_INVALID_OPERATION: return "AL_INVALID_OPERATION";
  35. case AL_OUT_OF_MEMORY: return "AL_OUT_OF_MEMORY";
  36. default: return "UNKNOWN_AL_ERROR";
  37. }
  38. }
  39. //-----------------------------------------------------------------------------
  40. #ifdef CROWN_DEBUG
  41. #define AL_CHECK(function)\
  42. function;\
  43. do { ALenum error; CE_ASSERT((error = alGetError()) == AL_NO_ERROR,\
  44. "OpenAL error: %s", al_error_to_string(error)); } while (0)
  45. #else
  46. #define AL_CHECK(function)\
  47. function;
  48. #endif
  49. //-----------------------------------------------------------------------------
  50. ALRenderer::ALRenderer() :
  51. m_buffers_id_table(m_allocator, MAX_BUFFERS),
  52. m_sources_id_table(m_allocator, MAX_SOURCES)
  53. {
  54. }
  55. //-----------------------------------------------------------------------------
  56. void ALRenderer::init()
  57. {
  58. m_device = alcOpenDevice(NULL);
  59. if (!m_device)
  60. {
  61. CE_ASSERT(false, "Cannot open audio device");
  62. }
  63. m_context = alcCreateContext(m_device, NULL);
  64. if (!m_context)
  65. {
  66. CE_ASSERT(false, "Cannot create context");
  67. }
  68. AL_CHECK(alcMakeContextCurrent(m_context));
  69. AL_CHECK(alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED));
  70. AL_CHECK(alDopplerFactor(1.0f));
  71. AL_CHECK(alDopplerVelocity(343.0f));
  72. // Default listener
  73. Vec3 pos(0.0f, 0.0f, 0.0f);
  74. Vec3 vel(0.0f, 0.0f, 0.0f);
  75. Vec3 at(0.0f, 0.0f, -1.0f);
  76. Vec3 up(0.0f, 1.0f, 0.0f);
  77. set_listener(pos, vel, at, up);
  78. }
  79. //-----------------------------------------------------------------------------
  80. void ALRenderer::shutdown()
  81. {
  82. AL_CHECK(alcDestroyContext(m_context));
  83. AL_CHECK(alcCloseDevice(m_device));
  84. }
  85. //-----------------------------------------------------------------------------
  86. void ALRenderer::set_listener(Vec3& position, Vec3& velocity, Vec3& orientation_up, Vec3& orientation_at)
  87. {
  88. AL_CHECK(alListener3f(AL_POSITION, position.x, position.y, position.z));
  89. AL_CHECK(alListener3f(AL_VELOCITY, velocity.x, velocity.y, velocity.z));
  90. ALfloat orientation[] = { orientation_up.x, orientation_up.y, orientation_up.z,
  91. orientation_at.x, orientation_at.y, orientation_at.z };
  92. AL_CHECK(alListenerfv(AL_ORIENTATION, orientation));
  93. }
  94. //-----------------------------------------------------------------------------
  95. SoundBufferId ALRenderer::create_buffer(const void* data, uint32_t size, uint32_t sample_rate, uint32_t channels, uint32_t bxs)
  96. {
  97. SoundBufferId id = m_buffers_id_table.create();
  98. SoundBuffer& al_buffer = m_buffers[id.index];
  99. // Generates AL buffer
  100. AL_CHECK(alGenBuffers(1, &al_buffer.id));
  101. bool stereo = (channels > 1);
  102. // Sets sound's format
  103. switch(bxs)
  104. {
  105. case 8:
  106. {
  107. if (stereo)
  108. {
  109. al_buffer.format = AL_FORMAT_STEREO8;
  110. }
  111. else
  112. {
  113. al_buffer.format = AL_FORMAT_MONO8;
  114. }
  115. break;
  116. }
  117. case 16:
  118. {
  119. if (stereo)
  120. {
  121. al_buffer.format = AL_FORMAT_STEREO16;
  122. }
  123. else
  124. {
  125. al_buffer.format = AL_FORMAT_MONO16;
  126. }
  127. break;
  128. }
  129. default:
  130. {
  131. CE_ASSERT(false, "Wrong number of bits per sample.");
  132. break;
  133. }
  134. }
  135. // Sets sound's size
  136. al_buffer.size = size;
  137. // Sets sound's frequency
  138. al_buffer.freq = sample_rate;
  139. // Fills AL buffer
  140. AL_CHECK(alBufferData(al_buffer.id, al_buffer.format, data, al_buffer.size, al_buffer.freq));
  141. }
  142. //-----------------------------------------------------------------------------
  143. void ALRenderer::destroy_buffer(SoundBufferId id)
  144. {
  145. CE_ASSERT(m_buffers_id_table.has(id), "SoundBuffer does not exist");
  146. SoundBuffer& al_buffer = m_buffers[id.index];
  147. AL_CHECK(alDeleteBuffers(1, &al_buffer.id));
  148. }
  149. //-----------------------------------------------------------------------------
  150. SoundSourceId ALRenderer::create_source(Vec3& position, Vec3& velocity, Vec3& direction, bool loop)
  151. {
  152. SoundSourceId id = m_sources_id_table.create();
  153. SoundSource& al_source = m_sources[id.index];
  154. // Creates AL source
  155. AL_CHECK(alGenSources(1, &al_source.id));
  156. AL_CHECK(alSourcef(al_source.id, AL_PITCH, 1.0f));
  157. AL_CHECK(alSourcef(al_source.id, AL_REFERENCE_DISTANCE, 0.1f));
  158. AL_CHECK(alSourcef(al_source.id, AL_MAX_DISTANCE, 1000.0f));
  159. AL_CHECK(alSource3f(al_source.id, AL_POSITION, position.x, position.y, position.z));
  160. AL_CHECK(alSource3f(al_source.id, AL_VELOCITY, velocity.x, velocity.y, velocity.z));
  161. AL_CHECK(alSource3f(al_source.id, AL_DIRECTION, direction.x, direction.y, direction.z));
  162. if (loop)
  163. {
  164. AL_CHECK(alSourcei(al_source.id, AL_LOOPING, AL_TRUE));
  165. }
  166. else
  167. {
  168. AL_CHECK(alSourcei(al_source.id, AL_LOOPING, AL_FALSE));
  169. }
  170. return id;
  171. }
  172. //-----------------------------------------------------------------------------
  173. void ALRenderer::play_source(SoundSourceId id)
  174. {
  175. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  176. SoundSource& al_source = m_sources[id.index];
  177. AL_CHECK(alSourcePlay(al_source.id));
  178. }
  179. //-----------------------------------------------------------------------------
  180. void ALRenderer::pause_source(SoundSourceId id)
  181. {
  182. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  183. SoundSource& al_source = m_sources[id.index];
  184. if (source_playing(id))
  185. {
  186. AL_CHECK(alSourcePause(al_source.id));
  187. }
  188. }
  189. //-----------------------------------------------------------------------------
  190. void ALRenderer::destroy_source(SoundSourceId id)
  191. {
  192. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  193. SoundSource& al_source = m_sources[id.index];
  194. alDeleteSources(1, &al_source.id);
  195. }
  196. //-----------------------------------------------------------------------------
  197. void ALRenderer::bind_buffer(SoundSourceId sid, SoundBufferId bid)
  198. {
  199. CE_ASSERT(m_sources_id_table.has(sid), "SoundSource does not exist");
  200. CE_ASSERT(m_buffers_id_table.has(bid), "SoundBuffer does not exist");
  201. SoundSource& al_source = m_sources[sid.index];
  202. SoundBuffer& al_buffer = m_buffers[bid.index];
  203. alSourcei(al_source.id, AL_BUFFER, al_buffer.id);
  204. }
  205. //-----------------------------------------------------------------------------
  206. void ALRenderer::set_source_position(SoundSourceId id, Vec3& pos)
  207. {
  208. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  209. SoundSource& al_source = m_sources[id.index];
  210. AL_CHECK(alSource3f(al_source.id, AL_POSITION, pos.x, pos.y, pos.z));
  211. }
  212. //-----------------------------------------------------------------------------
  213. void ALRenderer::set_source_velocity(SoundSourceId id, Vec3& vel)
  214. {
  215. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  216. SoundSource& al_source = m_sources[id.index];
  217. AL_CHECK(alSource3f(al_source.id, AL_VELOCITY, vel.x, vel.y, vel.z));
  218. }
  219. //-----------------------------------------------------------------------------
  220. void ALRenderer::set_source_direction(SoundSourceId id, Vec3& dir)
  221. {
  222. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  223. SoundSource& al_source = m_sources[id.index];
  224. AL_CHECK(alSource3f(al_source.id, AL_DIRECTION, dir.x, dir.y, dir.z));
  225. }
  226. //-----------------------------------------------------------------------------
  227. void ALRenderer::set_source_gain(SoundSourceId id, float gain)
  228. {
  229. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  230. SoundSource& al_source = m_sources[id.index];
  231. AL_CHECK(alSourcef(al_source.id, AL_GAIN, gain));
  232. }
  233. //-----------------------------------------------------------------------------
  234. void ALRenderer::set_source_rolloff(SoundSourceId id, float rolloff)
  235. {
  236. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  237. SoundSource& al_source = m_sources[id.index];
  238. AL_CHECK(alSourcef(al_source.id, AL_ROLLOFF_FACTOR, rolloff));
  239. }
  240. //-----------------------------------------------------------------------------
  241. bool ALRenderer::source_playing(SoundSourceId id)
  242. {
  243. CE_ASSERT(m_sources_id_table.has(id), "SoundSource does not exist");
  244. SoundSource& al_source = m_sources[id.index];
  245. ALint source_state;
  246. alGetSourcei(al_source.id, AL_SOURCE_STATE, &source_state);
  247. return source_state == AL_PLAYING;
  248. }
  249. } // namespace crown