audio_driver_alsa.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*************************************************************************/
  2. /* audio_driver_alsa.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* http://www.godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */
  9. /* */
  10. /* Permission is hereby granted, free of charge, to any person obtaining */
  11. /* a copy of this software and associated documentation files (the */
  12. /* "Software"), to deal in the Software without restriction, including */
  13. /* without limitation the rights to use, copy, modify, merge, publish, */
  14. /* distribute, sublicense, and/or sell copies of the Software, and to */
  15. /* permit persons to whom the Software is furnished to do so, subject to */
  16. /* the following conditions: */
  17. /* */
  18. /* The above copyright notice and this permission notice shall be */
  19. /* included in all copies or substantial portions of the Software. */
  20. /* */
  21. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  22. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  23. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  24. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  25. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  26. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  27. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  28. /*************************************************************************/
  29. #include "audio_driver_alsa.h"
  30. #ifdef ALSA_ENABLED
  31. #include <errno.h>
  32. #include "globals.h"
  33. Error AudioDriverALSA::init() {
  34. active=false;
  35. thread_exited=false;
  36. exit_thread=false;
  37. pcm_open = false;
  38. samples_in = NULL;
  39. samples_out = NULL;
  40. mix_rate = 44100;
  41. output_format = OUTPUT_STEREO;
  42. channels = 2;
  43. int status;
  44. snd_pcm_hw_params_t *hwparams;
  45. snd_pcm_sw_params_t *swparams;
  46. #define CHECK_FAIL(m_cond)\
  47. if (m_cond) {\
  48. fprintf(stderr,"ALSA ERR: %s\n",snd_strerror(status));\
  49. snd_pcm_close(pcm_handle);\
  50. ERR_FAIL_COND_V(m_cond,ERR_CANT_OPEN);\
  51. }
  52. //todo, add
  53. //6 chans - "plug:surround51"
  54. //4 chans - "plug:surround40";
  55. status = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
  56. ERR_FAIL_COND_V( status<0, ERR_CANT_OPEN );
  57. snd_pcm_hw_params_alloca(&hwparams);
  58. status = snd_pcm_hw_params_any(pcm_handle, hwparams);
  59. CHECK_FAIL( status<0 );
  60. status = snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
  61. CHECK_FAIL( status<0 );
  62. //not interested in anything else
  63. status = snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE);
  64. CHECK_FAIL( status<0 );
  65. //todo: support 4 and 6
  66. status = snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2);
  67. CHECK_FAIL( status<0 );
  68. status = snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &mix_rate, NULL);
  69. CHECK_FAIL( status<0 );
  70. int latency = GLOBAL_DEF("audio/output_latency",25);
  71. buffer_size = nearest_power_of_2( latency * mix_rate / 1000 );
  72. status = snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, &buffer_size, NULL);
  73. CHECK_FAIL( status<0 );
  74. unsigned int periods=2;
  75. status = snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, &periods, NULL);
  76. CHECK_FAIL( status<0 );
  77. status = snd_pcm_hw_params(pcm_handle,hwparams);
  78. CHECK_FAIL( status<0 );
  79. //snd_pcm_hw_params_free(&hwparams);
  80. snd_pcm_sw_params_alloca(&swparams);
  81. status = snd_pcm_sw_params_current(pcm_handle, swparams);
  82. CHECK_FAIL( status<0 );
  83. status = snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, buffer_size);
  84. CHECK_FAIL( status<0 );
  85. status = snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 1);
  86. CHECK_FAIL( status<0 );
  87. status = snd_pcm_sw_params(pcm_handle, swparams);
  88. CHECK_FAIL( status<0 );
  89. samples_in = memnew_arr(int32_t, buffer_size*channels);
  90. samples_out = memnew_arr(int16_t, buffer_size*channels);
  91. snd_pcm_nonblock(pcm_handle, 0);
  92. mutex=Mutex::create();
  93. thread = Thread::create(AudioDriverALSA::thread_func, this);
  94. return OK;
  95. };
  96. void AudioDriverALSA::thread_func(void* p_udata) {
  97. AudioDriverALSA* ad = (AudioDriverALSA*)p_udata;
  98. while (!ad->exit_thread) {
  99. if (!ad->active) {
  100. for (unsigned int i=0; i < ad->buffer_size*ad->channels; i++) {
  101. ad->samples_out[i] = 0;
  102. };
  103. } else {
  104. ad->lock();
  105. ad->audio_server_process(ad->buffer_size, ad->samples_in);
  106. ad->unlock();
  107. for(unsigned int i=0;i<ad->buffer_size*ad->channels;i++) {
  108. ad->samples_out[i]=ad->samples_in[i]>>16;
  109. }
  110. };
  111. int todo = ad->buffer_size; // * ad->channels * 2;
  112. int total = 0;
  113. while (todo) {
  114. if (ad->exit_thread)
  115. break;
  116. uint8_t* src = (uint8_t*)ad->samples_out;
  117. int wrote = snd_pcm_writei(ad->pcm_handle, (void*)(src + (total*ad->channels)), todo);
  118. if (wrote < 0) {
  119. if (ad->exit_thread)
  120. break;
  121. if ( wrote == -EAGAIN ) {
  122. usleep(1000); //can't write yet (though this is blocking..)
  123. continue;
  124. }
  125. wrote = snd_pcm_recover(ad->pcm_handle, wrote, 0);
  126. if ( wrote < 0 ) {
  127. //absolute fail
  128. fprintf(stderr, "ALSA failed and can't recover: %s\n", snd_strerror(wrote));
  129. ad->active=false;
  130. ad->exit_thread=true;
  131. break;
  132. }
  133. continue;
  134. };
  135. total += wrote;
  136. todo -= wrote;
  137. };
  138. };
  139. ad->thread_exited=true;
  140. };
  141. void AudioDriverALSA::start() {
  142. active = true;
  143. };
  144. int AudioDriverALSA::get_mix_rate() const {
  145. return mix_rate;
  146. };
  147. AudioDriverSW::OutputFormat AudioDriverALSA::get_output_format() const {
  148. return output_format;
  149. };
  150. void AudioDriverALSA::lock() {
  151. if (!thread || !mutex)
  152. return;
  153. mutex->lock();
  154. };
  155. void AudioDriverALSA::unlock() {
  156. if (!thread || !mutex)
  157. return;
  158. mutex->unlock();
  159. };
  160. void AudioDriverALSA::finish() {
  161. if (!thread)
  162. return;
  163. exit_thread = true;
  164. Thread::wait_to_finish(thread);
  165. if (pcm_open)
  166. snd_pcm_close(pcm_handle);
  167. if (samples_in) {
  168. memdelete_arr(samples_in);
  169. memdelete_arr(samples_out);
  170. };
  171. memdelete(thread);
  172. if (mutex)
  173. memdelete(mutex);
  174. thread = NULL;
  175. };
  176. AudioDriverALSA::AudioDriverALSA() {
  177. mutex = NULL;
  178. thread=NULL;
  179. pcm_handle=NULL;
  180. };
  181. AudioDriverALSA::~AudioDriverALSA() {
  182. };
  183. #endif