opensl.cpp 33 KB

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