opensl.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964
  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* This is an OpenAL backend for Android using the native audio APIs based on
  17. * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app
  18. * bundled with NDK.
  19. */
  20. #include "config.h"
  21. #include "backends/opensl.h"
  22. #include <stdlib.h>
  23. #include <jni.h>
  24. #include <new>
  25. #include <array>
  26. #include <cstring>
  27. #include <thread>
  28. #include <functional>
  29. #include "alcmain.h"
  30. #include "alexcpt.h"
  31. #include "alu.h"
  32. #include "compat.h"
  33. #include "endiantest.h"
  34. #include "ringbuffer.h"
  35. #include "threads.h"
  36. #include <SLES/OpenSLES.h>
  37. #include <SLES/OpenSLES_Android.h>
  38. #include <SLES/OpenSLES_AndroidConfiguration.h>
  39. namespace {
  40. /* Helper macros */
  41. #define EXTRACT_VCALL_ARGS(...) __VA_ARGS__))
  42. #define VCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
  43. #define VCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
  44. constexpr ALCchar opensl_device[] = "OpenSL";
  45. SLuint32 GetChannelMask(DevFmtChannels chans)
  46. {
  47. switch(chans)
  48. {
  49. case DevFmtMono: return SL_SPEAKER_FRONT_CENTER;
  50. case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
  51. case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
  52. SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT;
  53. case DevFmtX51: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
  54. SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_SIDE_LEFT |
  55. SL_SPEAKER_SIDE_RIGHT;
  56. case DevFmtX51Rear: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
  57. SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_LEFT |
  58. SL_SPEAKER_BACK_RIGHT;
  59. case DevFmtX61: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
  60. SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_CENTER |
  61. SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT;
  62. case DevFmtX71: return SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT |
  63. SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY | SL_SPEAKER_BACK_LEFT |
  64. SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT;
  65. case DevFmtAmbi3D:
  66. break;
  67. }
  68. return 0;
  69. }
  70. #ifdef SL_ANDROID_DATAFORMAT_PCM_EX
  71. SLuint32 GetTypeRepresentation(DevFmtType type)
  72. {
  73. switch(type)
  74. {
  75. case DevFmtUByte:
  76. case DevFmtUShort:
  77. case DevFmtUInt:
  78. return SL_ANDROID_PCM_REPRESENTATION_UNSIGNED_INT;
  79. case DevFmtByte:
  80. case DevFmtShort:
  81. case DevFmtInt:
  82. return SL_ANDROID_PCM_REPRESENTATION_SIGNED_INT;
  83. case DevFmtFloat:
  84. return SL_ANDROID_PCM_REPRESENTATION_FLOAT;
  85. }
  86. return 0;
  87. }
  88. #endif
  89. const char *res_str(SLresult result)
  90. {
  91. switch(result)
  92. {
  93. case SL_RESULT_SUCCESS: return "Success";
  94. case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";
  95. case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid";
  96. case SL_RESULT_MEMORY_FAILURE: return "Memory failure";
  97. case SL_RESULT_RESOURCE_ERROR: return "Resource error";
  98. case SL_RESULT_RESOURCE_LOST: return "Resource lost";
  99. case SL_RESULT_IO_ERROR: return "I/O error";
  100. case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient";
  101. case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted";
  102. case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported";
  103. case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found";
  104. case SL_RESULT_PERMISSION_DENIED: return "Permission denied";
  105. case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported";
  106. case SL_RESULT_INTERNAL_ERROR: return "Internal error";
  107. case SL_RESULT_UNKNOWN_ERROR: return "Unknown error";
  108. case SL_RESULT_OPERATION_ABORTED: return "Operation aborted";
  109. case SL_RESULT_CONTROL_LOST: return "Control lost";
  110. #ifdef SL_RESULT_READONLY
  111. case SL_RESULT_READONLY: return "ReadOnly";
  112. #endif
  113. #ifdef SL_RESULT_ENGINEOPTION_UNSUPPORTED
  114. case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported";
  115. #endif
  116. #ifdef SL_RESULT_SOURCE_SINK_INCOMPATIBLE
  117. case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible";
  118. #endif
  119. }
  120. return "Unknown error code";
  121. }
  122. #define PRINTERR(x, s) do { \
  123. if UNLIKELY((x) != SL_RESULT_SUCCESS) \
  124. ERR("%s: %s\n", (s), res_str((x))); \
  125. } while(0)
  126. struct OpenSLPlayback final : public BackendBase {
  127. OpenSLPlayback(ALCdevice *device) noexcept : BackendBase{device} { }
  128. ~OpenSLPlayback() override;
  129. void process(SLAndroidSimpleBufferQueueItf bq) noexcept;
  130. static void processC(SLAndroidSimpleBufferQueueItf bq, void *context) noexcept
  131. { static_cast<OpenSLPlayback*>(context)->process(bq); }
  132. int mixerProc();
  133. void open(const ALCchar *name) override;
  134. bool reset() override;
  135. bool start() override;
  136. void stop() override;
  137. ClockLatency getClockLatency() override;
  138. /* engine interfaces */
  139. SLObjectItf mEngineObj{nullptr};
  140. SLEngineItf mEngine{nullptr};
  141. /* output mix interfaces */
  142. SLObjectItf mOutputMix{nullptr};
  143. /* buffer queue player interfaces */
  144. SLObjectItf mBufferQueueObj{nullptr};
  145. RingBufferPtr mRing{nullptr};
  146. al::semaphore mSem;
  147. ALuint mFrameSize{0};
  148. std::atomic<bool> mKillNow{true};
  149. std::thread mThread;
  150. DEF_NEWDEL(OpenSLPlayback)
  151. };
  152. OpenSLPlayback::~OpenSLPlayback()
  153. {
  154. if(mBufferQueueObj)
  155. VCALL0(mBufferQueueObj,Destroy)();
  156. mBufferQueueObj = nullptr;
  157. if(mOutputMix)
  158. VCALL0(mOutputMix,Destroy)();
  159. mOutputMix = nullptr;
  160. if(mEngineObj)
  161. VCALL0(mEngineObj,Destroy)();
  162. mEngineObj = nullptr;
  163. mEngine = nullptr;
  164. }
  165. /* this callback handler is called every time a buffer finishes playing */
  166. void OpenSLPlayback::process(SLAndroidSimpleBufferQueueItf) noexcept
  167. {
  168. /* A note on the ringbuffer usage: The buffer queue seems to hold on to the
  169. * pointer passed to the Enqueue method, rather than copying the audio.
  170. * Consequently, the ringbuffer contains the audio that is currently queued
  171. * and waiting to play. This process() callback is called when a buffer is
  172. * finished, so we simply move the read pointer up to indicate the space is
  173. * available for writing again, and wake up the mixer thread to mix and
  174. * queue more audio.
  175. */
  176. mRing->readAdvance(1);
  177. mSem.post();
  178. }
  179. int OpenSLPlayback::mixerProc()
  180. {
  181. SetRTPriority();
  182. althrd_setname(MIXER_THREAD_NAME);
  183. SLPlayItf player;
  184. SLAndroidSimpleBufferQueueItf bufferQueue;
  185. SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  186. &bufferQueue)};
  187. PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
  188. if(SL_RESULT_SUCCESS == result)
  189. {
  190. result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
  191. PRINTERR(result, "bufferQueue->GetInterface SL_IID_PLAY");
  192. }
  193. std::unique_lock<OpenSLPlayback> dlock{*this};
  194. if(SL_RESULT_SUCCESS != result)
  195. aluHandleDisconnect(mDevice, "Failed to get playback buffer: 0x%08x", result);
  196. while(SL_RESULT_SUCCESS == result && !mKillNow.load(std::memory_order_acquire) &&
  197. mDevice->Connected.load(std::memory_order_acquire))
  198. {
  199. if(mRing->writeSpace() == 0)
  200. {
  201. SLuint32 state{0};
  202. result = VCALL(player,GetPlayState)(&state);
  203. PRINTERR(result, "player->GetPlayState");
  204. if(SL_RESULT_SUCCESS == result && state != SL_PLAYSTATE_PLAYING)
  205. {
  206. result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING);
  207. PRINTERR(result, "player->SetPlayState");
  208. }
  209. if(SL_RESULT_SUCCESS != result)
  210. {
  211. aluHandleDisconnect(mDevice, "Failed to start platback: 0x%08x", result);
  212. break;
  213. }
  214. if(mRing->writeSpace() == 0)
  215. {
  216. dlock.unlock();
  217. mSem.wait();
  218. dlock.lock();
  219. continue;
  220. }
  221. }
  222. auto data = mRing->getWriteVector();
  223. aluMixData(mDevice, data.first.buf,
  224. static_cast<ALuint>(data.first.len*mDevice->UpdateSize));
  225. if(data.second.len > 0)
  226. aluMixData(mDevice, data.second.buf,
  227. static_cast<ALuint>(data.second.len*mDevice->UpdateSize));
  228. size_t todo{data.first.len + data.second.len};
  229. mRing->writeAdvance(todo);
  230. for(size_t i{0};i < todo;i++)
  231. {
  232. if(!data.first.len)
  233. {
  234. data.first = data.second;
  235. data.second.buf = nullptr;
  236. data.second.len = 0;
  237. }
  238. result = VCALL(bufferQueue,Enqueue)(data.first.buf, mDevice->UpdateSize*mFrameSize);
  239. PRINTERR(result, "bufferQueue->Enqueue");
  240. if(SL_RESULT_SUCCESS != result)
  241. {
  242. aluHandleDisconnect(mDevice, "Failed to queue audio: 0x%08x", result);
  243. break;
  244. }
  245. data.first.len--;
  246. data.first.buf += mDevice->UpdateSize*mFrameSize;
  247. }
  248. }
  249. return 0;
  250. }
  251. void OpenSLPlayback::open(const ALCchar *name)
  252. {
  253. if(!name)
  254. name = opensl_device;
  255. else if(strcmp(name, opensl_device) != 0)
  256. throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name};
  257. // create engine
  258. SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)};
  259. PRINTERR(result, "slCreateEngine");
  260. if(SL_RESULT_SUCCESS == result)
  261. {
  262. result = VCALL(mEngineObj,Realize)(SL_BOOLEAN_FALSE);
  263. PRINTERR(result, "engine->Realize");
  264. }
  265. if(SL_RESULT_SUCCESS == result)
  266. {
  267. result = VCALL(mEngineObj,GetInterface)(SL_IID_ENGINE, &mEngine);
  268. PRINTERR(result, "engine->GetInterface");
  269. }
  270. if(SL_RESULT_SUCCESS == result)
  271. {
  272. result = VCALL(mEngine,CreateOutputMix)(&mOutputMix, 0, nullptr, nullptr);
  273. PRINTERR(result, "engine->CreateOutputMix");
  274. }
  275. if(SL_RESULT_SUCCESS == result)
  276. {
  277. result = VCALL(mOutputMix,Realize)(SL_BOOLEAN_FALSE);
  278. PRINTERR(result, "outputMix->Realize");
  279. }
  280. if(SL_RESULT_SUCCESS != result)
  281. {
  282. if(mOutputMix)
  283. VCALL0(mOutputMix,Destroy)();
  284. mOutputMix = nullptr;
  285. if(mEngineObj)
  286. VCALL0(mEngineObj,Destroy)();
  287. mEngineObj = nullptr;
  288. mEngine = nullptr;
  289. throw al::backend_exception{ALC_INVALID_VALUE,
  290. "Failed to initialize OpenSL device: 0x%08x", result};
  291. }
  292. mDevice->DeviceName = name;
  293. }
  294. bool OpenSLPlayback::reset()
  295. {
  296. SLresult result;
  297. if(mBufferQueueObj)
  298. VCALL0(mBufferQueueObj,Destroy)();
  299. mBufferQueueObj = nullptr;
  300. mRing = nullptr;
  301. #if 0
  302. if(!mDevice->Flags.get<FrequencyRequest>())
  303. {
  304. /* FIXME: Disabled until I figure out how to get the Context needed for
  305. * the getSystemService call.
  306. */
  307. JNIEnv *env = Android_GetJNIEnv();
  308. jobject jctx = Android_GetContext();
  309. /* Get necessary stuff for using java.lang.Integer,
  310. * android.content.Context, and android.media.AudioManager.
  311. */
  312. jclass int_cls = JCALL(env,FindClass)("java/lang/Integer");
  313. jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls,
  314. "parseInt", "(Ljava/lang/String;)I"
  315. );
  316. TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint);
  317. jclass ctx_cls = JCALL(env,FindClass)("android/content/Context");
  318. jfieldID ctx_audsvc = JCALL(env,GetStaticFieldID)(ctx_cls,
  319. "AUDIO_SERVICE", "Ljava/lang/String;"
  320. );
  321. jmethodID ctx_getSysSvc = JCALL(env,GetMethodID)(ctx_cls,
  322. "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"
  323. );
  324. TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n",
  325. ctx_cls, ctx_audsvc, ctx_getSysSvc);
  326. jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager");
  327. jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls,
  328. "PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;"
  329. );
  330. jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls,
  331. "getProperty", "(Ljava/lang/String;)Ljava/lang/String;"
  332. );
  333. TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n",
  334. audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty);
  335. const char *strchars;
  336. jstring strobj;
  337. /* Now make the calls. */
  338. //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
  339. strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc);
  340. jobject audMgr = JCALL(env,CallObjectMethod)(jctx, ctx_getSysSvc, strobj);
  341. strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr);
  342. TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr);
  343. JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
  344. //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
  345. strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate);
  346. jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj);
  347. strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr);
  348. TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr);
  349. JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
  350. //int sampleRate = Integer.parseInt(srateStr);
  351. sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr);
  352. strchars = JCALL(env,GetStringUTFChars)(srateStr, nullptr);
  353. TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars);
  354. JCALL(env,ReleaseStringUTFChars)(srateStr, strchars);
  355. if(!sampleRate) sampleRate = device->Frequency;
  356. else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE);
  357. }
  358. #endif
  359. mDevice->FmtChans = DevFmtStereo;
  360. mDevice->FmtType = DevFmtShort;
  361. SetDefaultWFXChannelOrder(mDevice);
  362. mFrameSize = mDevice->frameSizeFromFmt();
  363. const std::array<SLInterfaceID,2> ids{{ SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }};
  364. const std::array<SLboolean,2> reqs{{ SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE }};
  365. SLDataLocator_OutputMix loc_outmix{};
  366. loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
  367. loc_outmix.outputMix = mOutputMix;
  368. SLDataSink audioSnk{};
  369. audioSnk.pLocator = &loc_outmix;
  370. audioSnk.pFormat = nullptr;
  371. SLDataLocator_AndroidSimpleBufferQueue loc_bufq{};
  372. loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
  373. loc_bufq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize;
  374. SLDataSource audioSrc{};
  375. #ifdef SL_ANDROID_DATAFORMAT_PCM_EX
  376. SLAndroidDataFormat_PCM_EX format_pcm_ex{};
  377. format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
  378. format_pcm_ex.numChannels = mDevice->channelsFromFmt();
  379. format_pcm_ex.sampleRate = mDevice->Frequency * 1000;
  380. format_pcm_ex.bitsPerSample = mDevice->bytesFromFmt() * 8;
  381. format_pcm_ex.containerSize = format_pcm_ex.bitsPerSample;
  382. format_pcm_ex.channelMask = GetChannelMask(mDevice->FmtChans);
  383. format_pcm_ex.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN;
  384. format_pcm_ex.representation = GetTypeRepresentation(mDevice->FmtType);
  385. audioSrc.pLocator = &loc_bufq;
  386. audioSrc.pFormat = &format_pcm_ex;
  387. result = VCALL(mEngine,CreateAudioPlayer)(&mBufferQueueObj, &audioSrc, &audioSnk, ids.size(),
  388. ids.data(), reqs.data());
  389. if(SL_RESULT_SUCCESS != result)
  390. #endif
  391. {
  392. /* Alter sample type according to what SLDataFormat_PCM can support. */
  393. switch(mDevice->FmtType)
  394. {
  395. case DevFmtByte: mDevice->FmtType = DevFmtUByte; break;
  396. case DevFmtUInt: mDevice->FmtType = DevFmtInt; break;
  397. case DevFmtFloat:
  398. case DevFmtUShort: mDevice->FmtType = DevFmtShort; break;
  399. case DevFmtUByte:
  400. case DevFmtShort:
  401. case DevFmtInt:
  402. break;
  403. }
  404. SLDataFormat_PCM format_pcm{};
  405. format_pcm.formatType = SL_DATAFORMAT_PCM;
  406. format_pcm.numChannels = mDevice->channelsFromFmt();
  407. format_pcm.samplesPerSec = mDevice->Frequency * 1000;
  408. format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8;
  409. format_pcm.containerSize = format_pcm.bitsPerSample;
  410. format_pcm.channelMask = GetChannelMask(mDevice->FmtChans);
  411. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  412. SL_BYTEORDER_BIGENDIAN;
  413. audioSrc.pLocator = &loc_bufq;
  414. audioSrc.pFormat = &format_pcm;
  415. result = VCALL(mEngine,CreateAudioPlayer)(&mBufferQueueObj, &audioSrc, &audioSnk, ids.size(),
  416. ids.data(), reqs.data());
  417. PRINTERR(result, "engine->CreateAudioPlayer");
  418. }
  419. if(SL_RESULT_SUCCESS == result)
  420. {
  421. /* Set the stream type to "media" (games, music, etc), if possible. */
  422. SLAndroidConfigurationItf config;
  423. result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
  424. PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDCONFIGURATION");
  425. if(SL_RESULT_SUCCESS == result)
  426. {
  427. SLint32 streamType = SL_ANDROID_STREAM_MEDIA;
  428. result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_STREAM_TYPE, &streamType,
  429. sizeof(streamType));
  430. PRINTERR(result, "config->SetConfiguration");
  431. }
  432. /* Clear any error since this was optional. */
  433. result = SL_RESULT_SUCCESS;
  434. }
  435. if(SL_RESULT_SUCCESS == result)
  436. {
  437. result = VCALL(mBufferQueueObj,Realize)(SL_BOOLEAN_FALSE);
  438. PRINTERR(result, "bufferQueue->Realize");
  439. }
  440. if(SL_RESULT_SUCCESS == result)
  441. {
  442. const ALuint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
  443. mRing = CreateRingBuffer(num_updates, mFrameSize*mDevice->UpdateSize, true);
  444. }
  445. if(SL_RESULT_SUCCESS != result)
  446. {
  447. if(mBufferQueueObj)
  448. VCALL0(mBufferQueueObj,Destroy)();
  449. mBufferQueueObj = nullptr;
  450. return false;
  451. }
  452. return true;
  453. }
  454. bool OpenSLPlayback::start()
  455. {
  456. mRing->reset();
  457. SLAndroidSimpleBufferQueueItf bufferQueue;
  458. SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  459. &bufferQueue)};
  460. PRINTERR(result, "bufferQueue->GetInterface");
  461. if(SL_RESULT_SUCCESS != result)
  462. return false;
  463. result = VCALL(bufferQueue,RegisterCallback)(&OpenSLPlayback::processC, this);
  464. PRINTERR(result, "bufferQueue->RegisterCallback");
  465. if(SL_RESULT_SUCCESS != result) return false;
  466. try {
  467. mKillNow.store(false, std::memory_order_release);
  468. mThread = std::thread(std::mem_fn(&OpenSLPlayback::mixerProc), this);
  469. return true;
  470. }
  471. catch(std::exception& e) {
  472. ERR("Could not create playback thread: %s\n", e.what());
  473. }
  474. catch(...) {
  475. }
  476. return false;
  477. }
  478. void OpenSLPlayback::stop()
  479. {
  480. if(mKillNow.exchange(true, std::memory_order_acq_rel) || !mThread.joinable())
  481. return;
  482. mSem.post();
  483. mThread.join();
  484. SLPlayItf player;
  485. SLresult result{VCALL(mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player)};
  486. PRINTERR(result, "bufferQueue->GetInterface");
  487. if(SL_RESULT_SUCCESS == result)
  488. {
  489. result = VCALL(player,SetPlayState)(SL_PLAYSTATE_STOPPED);
  490. PRINTERR(result, "player->SetPlayState");
  491. }
  492. SLAndroidSimpleBufferQueueItf bufferQueue;
  493. result = VCALL(mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue);
  494. PRINTERR(result, "bufferQueue->GetInterface");
  495. if(SL_RESULT_SUCCESS == result)
  496. {
  497. result = VCALL0(bufferQueue,Clear)();
  498. PRINTERR(result, "bufferQueue->Clear");
  499. }
  500. if(SL_RESULT_SUCCESS == result)
  501. {
  502. result = VCALL(bufferQueue,RegisterCallback)(nullptr, nullptr);
  503. PRINTERR(result, "bufferQueue->RegisterCallback");
  504. }
  505. if(SL_RESULT_SUCCESS == result)
  506. {
  507. SLAndroidSimpleBufferQueueState state;
  508. do {
  509. std::this_thread::yield();
  510. result = VCALL(bufferQueue,GetState)(&state);
  511. } while(SL_RESULT_SUCCESS == result && state.count > 0);
  512. PRINTERR(result, "bufferQueue->GetState");
  513. }
  514. }
  515. ClockLatency OpenSLPlayback::getClockLatency()
  516. {
  517. ClockLatency ret;
  518. std::lock_guard<OpenSLPlayback> _{*this};
  519. ret.ClockTime = GetDeviceClockTime(mDevice);
  520. ret.Latency = std::chrono::seconds{mRing->readSpace() * mDevice->UpdateSize};
  521. ret.Latency /= mDevice->Frequency;
  522. return ret;
  523. }
  524. struct OpenSLCapture final : public BackendBase {
  525. OpenSLCapture(ALCdevice *device) noexcept : BackendBase{device} { }
  526. ~OpenSLCapture() override;
  527. void process(SLAndroidSimpleBufferQueueItf bq) noexcept;
  528. static void processC(SLAndroidSimpleBufferQueueItf bq, void *context) noexcept
  529. { static_cast<OpenSLCapture*>(context)->process(bq); }
  530. void open(const ALCchar *name) override;
  531. bool start() override;
  532. void stop() override;
  533. ALCenum captureSamples(al::byte *buffer, ALCuint samples) override;
  534. ALCuint availableSamples() override;
  535. /* engine interfaces */
  536. SLObjectItf mEngineObj{nullptr};
  537. SLEngineItf mEngine;
  538. /* recording interfaces */
  539. SLObjectItf mRecordObj{nullptr};
  540. RingBufferPtr mRing{nullptr};
  541. ALCuint mSplOffset{0u};
  542. ALuint mFrameSize{0};
  543. DEF_NEWDEL(OpenSLCapture)
  544. };
  545. OpenSLCapture::~OpenSLCapture()
  546. {
  547. if(mRecordObj)
  548. VCALL0(mRecordObj,Destroy)();
  549. mRecordObj = nullptr;
  550. if(mEngineObj)
  551. VCALL0(mEngineObj,Destroy)();
  552. mEngineObj = nullptr;
  553. mEngine = nullptr;
  554. }
  555. void OpenSLCapture::process(SLAndroidSimpleBufferQueueItf) noexcept
  556. {
  557. /* A new chunk has been written into the ring buffer, advance it. */
  558. mRing->writeAdvance(1);
  559. }
  560. void OpenSLCapture::open(const ALCchar* name)
  561. {
  562. if(!name)
  563. name = opensl_device;
  564. else if(strcmp(name, opensl_device) != 0)
  565. throw al::backend_exception{ALC_INVALID_VALUE, "Device name \"%s\" not found", name};
  566. SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)};
  567. PRINTERR(result, "slCreateEngine");
  568. if(SL_RESULT_SUCCESS == result)
  569. {
  570. result = VCALL(mEngineObj,Realize)(SL_BOOLEAN_FALSE);
  571. PRINTERR(result, "engine->Realize");
  572. }
  573. if(SL_RESULT_SUCCESS == result)
  574. {
  575. result = VCALL(mEngineObj,GetInterface)(SL_IID_ENGINE, &mEngine);
  576. PRINTERR(result, "engine->GetInterface");
  577. }
  578. if(SL_RESULT_SUCCESS == result)
  579. {
  580. mFrameSize = mDevice->frameSizeFromFmt();
  581. /* Ensure the total length is at least 100ms */
  582. ALuint length{maxu(mDevice->BufferSize, mDevice->Frequency/10)};
  583. /* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */
  584. ALuint update_len{clampu(mDevice->BufferSize/3, mDevice->Frequency/100,
  585. mDevice->Frequency/100*5)};
  586. ALuint num_updates{(length+update_len-1) / update_len};
  587. mRing = CreateRingBuffer(num_updates, update_len*mFrameSize, false);
  588. mDevice->UpdateSize = update_len;
  589. mDevice->BufferSize = static_cast<ALuint>(mRing->writeSpace() * update_len);
  590. }
  591. if(SL_RESULT_SUCCESS == result)
  592. {
  593. const std::array<SLInterfaceID,2> ids{{ SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }};
  594. const std::array<SLboolean,2> reqs{{ SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE }};
  595. SLDataLocator_IODevice loc_dev{};
  596. loc_dev.locatorType = SL_DATALOCATOR_IODEVICE;
  597. loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT;
  598. loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
  599. loc_dev.device = nullptr;
  600. SLDataSource audioSrc{};
  601. audioSrc.pLocator = &loc_dev;
  602. audioSrc.pFormat = nullptr;
  603. SLDataLocator_AndroidSimpleBufferQueue loc_bq{};
  604. loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
  605. loc_bq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize;
  606. SLDataSink audioSnk{};
  607. #ifdef SL_ANDROID_DATAFORMAT_PCM_EX
  608. SLAndroidDataFormat_PCM_EX format_pcm_ex{};
  609. format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
  610. format_pcm_ex.numChannels = mDevice->channelsFromFmt();
  611. format_pcm_ex.sampleRate = mDevice->Frequency * 1000;
  612. format_pcm_ex.bitsPerSample = mDevice->bytesFromFmt() * 8;
  613. format_pcm_ex.containerSize = format_pcm_ex.bitsPerSample;
  614. format_pcm_ex.channelMask = GetChannelMask(mDevice->FmtChans);
  615. format_pcm_ex.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  616. SL_BYTEORDER_BIGENDIAN;
  617. format_pcm_ex.representation = GetTypeRepresentation(mDevice->FmtType);
  618. audioSnk.pLocator = &loc_bq;
  619. audioSnk.pFormat = &format_pcm_ex;
  620. result = VCALL(mEngine,CreateAudioRecorder)(&mRecordObj, &audioSrc, &audioSnk,
  621. ids.size(), ids.data(), reqs.data());
  622. if(SL_RESULT_SUCCESS != result)
  623. #endif
  624. {
  625. /* Fallback to SLDataFormat_PCM only if it supports the desired
  626. * sample type.
  627. */
  628. if(mDevice->FmtType == DevFmtUByte || mDevice->FmtType == DevFmtShort
  629. || mDevice->FmtType == DevFmtInt)
  630. {
  631. SLDataFormat_PCM format_pcm{};
  632. format_pcm.formatType = SL_DATAFORMAT_PCM;
  633. format_pcm.numChannels = mDevice->channelsFromFmt();
  634. format_pcm.samplesPerSec = mDevice->Frequency * 1000;
  635. format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8;
  636. format_pcm.containerSize = format_pcm.bitsPerSample;
  637. format_pcm.channelMask = GetChannelMask(mDevice->FmtChans);
  638. format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
  639. SL_BYTEORDER_BIGENDIAN;
  640. audioSnk.pLocator = &loc_bq;
  641. audioSnk.pFormat = &format_pcm;
  642. result = VCALL(mEngine,CreateAudioRecorder)(&mRecordObj, &audioSrc, &audioSnk,
  643. ids.size(), ids.data(), reqs.data());
  644. }
  645. PRINTERR(result, "engine->CreateAudioRecorder");
  646. }
  647. }
  648. if(SL_RESULT_SUCCESS == result)
  649. {
  650. /* Set the record preset to "generic", if possible. */
  651. SLAndroidConfigurationItf config;
  652. result = VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
  653. PRINTERR(result, "recordObj->GetInterface SL_IID_ANDROIDCONFIGURATION");
  654. if(SL_RESULT_SUCCESS == result)
  655. {
  656. SLuint32 preset = SL_ANDROID_RECORDING_PRESET_GENERIC;
  657. result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_RECORDING_PRESET, &preset,
  658. sizeof(preset));
  659. PRINTERR(result, "config->SetConfiguration");
  660. }
  661. /* Clear any error since this was optional. */
  662. result = SL_RESULT_SUCCESS;
  663. }
  664. if(SL_RESULT_SUCCESS == result)
  665. {
  666. result = VCALL(mRecordObj,Realize)(SL_BOOLEAN_FALSE);
  667. PRINTERR(result, "recordObj->Realize");
  668. }
  669. SLAndroidSimpleBufferQueueItf bufferQueue;
  670. if(SL_RESULT_SUCCESS == result)
  671. {
  672. result = VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue);
  673. PRINTERR(result, "recordObj->GetInterface");
  674. }
  675. if(SL_RESULT_SUCCESS == result)
  676. {
  677. result = VCALL(bufferQueue,RegisterCallback)(&OpenSLCapture::processC, this);
  678. PRINTERR(result, "bufferQueue->RegisterCallback");
  679. }
  680. if(SL_RESULT_SUCCESS == result)
  681. {
  682. const ALuint chunk_size{mDevice->UpdateSize * mFrameSize};
  683. auto data = mRing->getWriteVector();
  684. for(size_t i{0u};i < data.first.len && SL_RESULT_SUCCESS == result;i++)
  685. {
  686. result = VCALL(bufferQueue,Enqueue)(data.first.buf + chunk_size*i, chunk_size);
  687. PRINTERR(result, "bufferQueue->Enqueue");
  688. }
  689. for(size_t i{0u};i < data.second.len && SL_RESULT_SUCCESS == result;i++)
  690. {
  691. result = VCALL(bufferQueue,Enqueue)(data.second.buf + chunk_size*i, chunk_size);
  692. PRINTERR(result, "bufferQueue->Enqueue");
  693. }
  694. }
  695. if(SL_RESULT_SUCCESS != result)
  696. {
  697. if(mRecordObj)
  698. VCALL0(mRecordObj,Destroy)();
  699. mRecordObj = nullptr;
  700. if(mEngineObj)
  701. VCALL0(mEngineObj,Destroy)();
  702. mEngineObj = nullptr;
  703. mEngine = nullptr;
  704. throw al::backend_exception{ALC_INVALID_VALUE,
  705. "Failed to initialize OpenSL device: 0x%08x", result};
  706. }
  707. mDevice->DeviceName = name;
  708. }
  709. bool OpenSLCapture::start()
  710. {
  711. SLRecordItf record;
  712. SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_RECORD, &record)};
  713. PRINTERR(result, "recordObj->GetInterface");
  714. if(SL_RESULT_SUCCESS == result)
  715. {
  716. result = VCALL(record,SetRecordState)(SL_RECORDSTATE_RECORDING);
  717. PRINTERR(result, "record->SetRecordState");
  718. }
  719. if(SL_RESULT_SUCCESS != result)
  720. {
  721. aluHandleDisconnect(mDevice, "Failed to start capture: 0x%08x", result);
  722. return false;
  723. }
  724. return true;
  725. }
  726. void OpenSLCapture::stop()
  727. {
  728. SLRecordItf record;
  729. SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_RECORD, &record)};
  730. PRINTERR(result, "recordObj->GetInterface");
  731. if(SL_RESULT_SUCCESS == result)
  732. {
  733. result = VCALL(record,SetRecordState)(SL_RECORDSTATE_PAUSED);
  734. PRINTERR(result, "record->SetRecordState");
  735. }
  736. }
  737. ALCenum OpenSLCapture::captureSamples(al::byte *buffer, ALCuint samples)
  738. {
  739. SLAndroidSimpleBufferQueueItf bufferQueue{};
  740. if LIKELY(mDevice->Connected.load(std::memory_order_acquire))
  741. {
  742. const SLresult result{VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
  743. &bufferQueue)};
  744. PRINTERR(result, "recordObj->GetInterface");
  745. if UNLIKELY(SL_RESULT_SUCCESS != result)
  746. {
  747. aluHandleDisconnect(mDevice, "Failed to get capture buffer queue: 0x%08x", result);
  748. bufferQueue = nullptr;
  749. }
  750. }
  751. const ALuint update_size{mDevice->UpdateSize};
  752. const ALuint chunk_size{update_size * mFrameSize};
  753. /* Read the desired samples from the ring buffer then advance its read
  754. * pointer.
  755. */
  756. auto data = mRing->getReadVector();
  757. for(ALCuint i{0};i < samples;)
  758. {
  759. const ALCuint rem{minu(samples - i, update_size - mSplOffset)};
  760. std::copy_n(data.first.buf + mSplOffset*mFrameSize, rem*mFrameSize, buffer + i*mFrameSize);
  761. mSplOffset += rem;
  762. if(mSplOffset == update_size)
  763. {
  764. /* Finished a chunk, reset the offset and advance the read pointer. */
  765. mSplOffset = 0;
  766. mRing->readAdvance(1);
  767. if LIKELY(bufferQueue)
  768. {
  769. const SLresult result{VCALL(bufferQueue,Enqueue)(data.first.buf, chunk_size)};
  770. PRINTERR(result, "bufferQueue->Enqueue");
  771. if UNLIKELY(SL_RESULT_SUCCESS != result)
  772. {
  773. aluHandleDisconnect(mDevice, "Failed to update capture buffer: 0x%08x",
  774. result);
  775. bufferQueue = nullptr;
  776. }
  777. }
  778. data.first.len--;
  779. if(!data.first.len)
  780. data.first = data.second;
  781. else
  782. data.first.buf += chunk_size;
  783. }
  784. i += rem;
  785. }
  786. return ALC_NO_ERROR;
  787. }
  788. ALCuint OpenSLCapture::availableSamples()
  789. { return static_cast<ALuint>(mRing->readSpace()*mDevice->UpdateSize - mSplOffset); }
  790. } // namespace
  791. bool OSLBackendFactory::init() { return true; }
  792. bool OSLBackendFactory::querySupport(BackendType type)
  793. { return (type == BackendType::Playback || type == BackendType::Capture); }
  794. void OSLBackendFactory::probe(DevProbe type, std::string *outnames)
  795. {
  796. switch(type)
  797. {
  798. case DevProbe::Playback:
  799. case DevProbe::Capture:
  800. /* Includes null char. */
  801. outnames->append(opensl_device, sizeof(opensl_device));
  802. break;
  803. }
  804. }
  805. BackendPtr OSLBackendFactory::createBackend(ALCdevice *device, BackendType type)
  806. {
  807. if(type == BackendType::Playback)
  808. return BackendPtr{new OpenSLPlayback{device}};
  809. if(type == BackendType::Capture)
  810. return BackendPtr{new OpenSLCapture{device}};
  811. return nullptr;
  812. }
  813. BackendFactory &OSLBackendFactory::getFactory()
  814. {
  815. static OSLBackendFactory factory{};
  816. return factory;
  817. }