🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

984 lines
33 KiB

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