opensl.cpp 31 KB

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