AudioOutputOpenSLES.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //
  2. // libtgvoip is free and unencumbered public domain software.
  3. // For more information, see http://unlicense.org or the UNLICENSE file
  4. // you should have received with this source code distribution.
  5. //
  6. #include <sys/time.h>
  7. #include <unistd.h>
  8. #include <assert.h>
  9. #include "AudioOutputOpenSLES.h"
  10. #include "../../logging.h"
  11. #include "../../VoIPController.h"
  12. #include "OpenSLEngineWrapper.h"
  13. #include "AudioInputAndroid.h"
  14. #define CHECK_SL_ERROR(res, msg) if(res!=SL_RESULT_SUCCESS){ LOGE(msg); failed=true; return; }
  15. #define BUFFER_SIZE 960 // 20 ms
  16. using namespace tgvoip;
  17. using namespace tgvoip::audio;
  18. unsigned int AudioOutputOpenSLES::nativeBufferSize;
  19. AudioOutputOpenSLES::AudioOutputOpenSLES(){
  20. SLresult result;
  21. slEngine=OpenSLEngineWrapper::CreateEngine();
  22. const SLInterfaceID pOutputMixIDs[] = {};
  23. const SLboolean pOutputMixRequired[] = {};
  24. result = (*slEngine)->CreateOutputMix(slEngine, &slOutputMixObj, 0, pOutputMixIDs, pOutputMixRequired);
  25. CHECK_SL_ERROR(result, "Error creating output mix");
  26. result = (*slOutputMixObj)->Realize(slOutputMixObj, SL_BOOLEAN_FALSE);
  27. CHECK_SL_ERROR(result, "Error realizing output mix");
  28. LOGI("Native buffer size is %u samples", nativeBufferSize);
  29. /*if(nativeBufferSize<BUFFER_SIZE && BUFFER_SIZE % nativeBufferSize!=0){
  30. LOGE("20ms is not divisible by native buffer size!!");
  31. nativeBufferSize=BUFFER_SIZE;
  32. }else if(nativeBufferSize>BUFFER_SIZE && nativeBufferSize%BUFFER_SIZE!=0){
  33. LOGE("native buffer size is not multiple of 20ms!!");
  34. nativeBufferSize+=nativeBufferSize%BUFFER_SIZE;
  35. }
  36. LOGI("Adjusted native buffer size is %u", nativeBufferSize);*/
  37. buffer=(int16_t*)calloc(BUFFER_SIZE, sizeof(int16_t));
  38. nativeBuffer=(int16_t*)calloc((size_t) nativeBufferSize, sizeof(int16_t));
  39. slPlayerObj=NULL;
  40. remainingDataSize=0;
  41. }
  42. AudioOutputOpenSLES::~AudioOutputOpenSLES(){
  43. if(!stopped)
  44. Stop();
  45. (*slBufferQueue)->Clear(slBufferQueue);
  46. LOGV("destroy slPlayerObj");
  47. (*slPlayerObj)->Destroy(slPlayerObj);
  48. LOGV("destroy slOutputMixObj");
  49. (*slOutputMixObj)->Destroy(slOutputMixObj);
  50. OpenSLEngineWrapper::DestroyEngine();
  51. free(buffer);
  52. free(nativeBuffer);
  53. }
  54. void AudioOutputOpenSLES::SetNativeBufferSize(unsigned int size){
  55. AudioOutputOpenSLES::nativeBufferSize=size;
  56. }
  57. void AudioOutputOpenSLES::BufferCallback(SLAndroidSimpleBufferQueueItf bq, void *context){
  58. ((AudioOutputOpenSLES*)context)->HandleSLCallback();
  59. }
  60. void AudioOutputOpenSLES::Configure(uint32_t sampleRate, uint32_t bitsPerSample, uint32_t channels){
  61. assert(slPlayerObj==NULL);
  62. SLDataLocator_AndroidSimpleBufferQueue locatorBufferQueue =
  63. {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 1};
  64. SLDataFormat_PCM formatPCM = {SL_DATAFORMAT_PCM, channels, sampleRate*1000,
  65. SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16,
  66. channels==2 ? (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT) : SL_SPEAKER_FRONT_CENTER, SL_BYTEORDER_LITTLEENDIAN};
  67. SLDataSource audioSrc = {&locatorBufferQueue, &formatPCM};
  68. SLDataLocator_OutputMix locatorOutMix = {SL_DATALOCATOR_OUTPUTMIX, slOutputMixObj};
  69. SLDataSink audioSnk = {&locatorOutMix, NULL};
  70. const SLInterfaceID id[2] = {SL_IID_BUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION};
  71. const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
  72. SLresult result = (*slEngine)->CreateAudioPlayer(slEngine, &slPlayerObj, &audioSrc, &audioSnk, 2, id, req);
  73. CHECK_SL_ERROR(result, "Error creating player");
  74. SLAndroidConfigurationItf playerConfig;
  75. result = (*slPlayerObj)->GetInterface(slPlayerObj, SL_IID_ANDROIDCONFIGURATION, &playerConfig);
  76. SLint32 streamType = SL_ANDROID_STREAM_VOICE;
  77. result = (*playerConfig)->SetConfiguration(playerConfig, SL_ANDROID_KEY_STREAM_TYPE, &streamType, sizeof(SLint32));
  78. result=(*slPlayerObj)->Realize(slPlayerObj, SL_BOOLEAN_FALSE);
  79. CHECK_SL_ERROR(result, "Error realizing player");
  80. result=(*slPlayerObj)->GetInterface(slPlayerObj, SL_IID_PLAY, &slPlayer);
  81. CHECK_SL_ERROR(result, "Error getting player interface");
  82. result=(*slPlayerObj)->GetInterface(slPlayerObj, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &slBufferQueue);
  83. CHECK_SL_ERROR(result, "Error getting buffer queue");
  84. result=(*slBufferQueue)->RegisterCallback(slBufferQueue, AudioOutputOpenSLES::BufferCallback, this);
  85. CHECK_SL_ERROR(result, "Error setting buffer queue callback");
  86. (*slBufferQueue)->Enqueue(slBufferQueue, nativeBuffer, nativeBufferSize*sizeof(int16_t));
  87. }
  88. bool AudioOutputOpenSLES::IsPhone(){
  89. return false;
  90. }
  91. void AudioOutputOpenSLES::EnableLoudspeaker(bool enabled){
  92. }
  93. void AudioOutputOpenSLES::Start(){
  94. stopped=false;
  95. SLresult result=(*slPlayer)->SetPlayState(slPlayer, SL_PLAYSTATE_PLAYING);
  96. CHECK_SL_ERROR(result, "Error starting player");
  97. }
  98. void AudioOutputOpenSLES::Stop(){
  99. stopped=true;
  100. LOGV("Stopping OpenSL output");
  101. SLresult result=(*slPlayer)->SetPlayState(slPlayer, SL_PLAYSTATE_PAUSED);
  102. CHECK_SL_ERROR(result, "Error starting player");
  103. }
  104. void AudioOutputOpenSLES::HandleSLCallback(){
  105. /*if(stopped){
  106. //LOGV("left HandleSLCallback early");
  107. return;
  108. }*/
  109. //LOGV("before InvokeCallback");
  110. if(!stopped){
  111. while(remainingDataSize<nativeBufferSize*2){
  112. assert(remainingDataSize+BUFFER_SIZE*2<10240);
  113. InvokeCallback(remainingData+remainingDataSize, BUFFER_SIZE*2);
  114. remainingDataSize+=BUFFER_SIZE*2;
  115. }
  116. memcpy(nativeBuffer, remainingData, nativeBufferSize*2);
  117. remainingDataSize-=nativeBufferSize*2;
  118. if(remainingDataSize>0)
  119. memmove(remainingData, remainingData+nativeBufferSize*2, remainingDataSize);
  120. //InvokeCallback((unsigned char *) nativeBuffer, nativeBufferSize*sizeof(int16_t));
  121. }else{
  122. memset(nativeBuffer, 0, nativeBufferSize*2);
  123. }
  124. (*slBufferQueue)->Enqueue(slBufferQueue, nativeBuffer, nativeBufferSize*sizeof(int16_t));
  125. //LOGV("left HandleSLCallback");
  126. }
  127. bool AudioOutputOpenSLES::IsPlaying(){
  128. if(slPlayer){
  129. uint32_t state;
  130. (*slPlayer)->GetPlayState(slPlayer, &state);
  131. return state==SL_PLAYSTATE_PLAYING;
  132. }
  133. return false;
  134. }
  135. float AudioOutputOpenSLES::GetLevel(){
  136. return 0; // we don't use this anyway
  137. }