The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

1081 lines
45KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2016 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of the ISC license
  6. http://www.isc.org/downloads/software-support-policy/isc-license/
  7. Permission to use, copy, modify, and/or distribute this software for any
  8. purpose with or without fee is hereby granted, provided that the above
  9. copyright notice and this permission notice appear in all copies.
  10. THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
  11. TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  12. FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
  13. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  14. USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  16. OF THIS SOFTWARE.
  17. -----------------------------------------------------------------------------
  18. To release a closed-source product which uses other parts of JUCE not
  19. licensed under the ISC terms, commercial licenses are available: visit
  20. www.juce.com for more information.
  21. ==============================================================================
  22. */
  23. //==============================================================================
  24. #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
  25. STATICFIELD (SDK_INT, "SDK_INT", "I") \
  26. DECLARE_JNI_CLASS (AndroidBuildVersion, "android/os/Build$VERSION");
  27. #undef JNI_CLASS_MEMBERS
  28. //==============================================================================
  29. #ifndef SL_ANDROID_DATAFORMAT_PCM_EX
  30. #define SL_ANDROID_DATAFORMAT_PCM_EX ((SLuint32) 0x00000004)
  31. #endif
  32. #ifndef SL_ANDROID_PCM_REPRESENTATION_FLOAT
  33. #define SL_ANDROID_PCM_REPRESENTATION_FLOAT ((SLuint32) 0x00000003)
  34. #endif
  35. #ifndef SL_ANDROID_RECORDING_PRESET_UNPROCESSED
  36. #define SL_ANDROID_RECORDING_PRESET_UNPROCESSED ((SLuint32) 0x00000005)
  37. #endif
  38. //==============================================================================
  39. struct PCMDataFormatEx : SLDataFormat_PCM
  40. {
  41. SLuint32 representation;
  42. };
  43. //==============================================================================
  44. template <typename T> struct IntfIID;
  45. template <> struct IntfIID<SLObjectItf_> { static SLInterfaceID_ iid; };
  46. template <> struct IntfIID<SLEngineItf_> { static SLInterfaceID_ iid; };
  47. template <> struct IntfIID<SLOutputMixItf_> { static SLInterfaceID_ iid; };
  48. template <> struct IntfIID<SLPlayItf_> { static SLInterfaceID_ iid; };
  49. template <> struct IntfIID<SLRecordItf_> { static SLInterfaceID_ iid; };
  50. template <> struct IntfIID<SLAndroidSimpleBufferQueueItf_> { static SLInterfaceID_ iid; };
  51. template <> struct IntfIID<SLAndroidConfigurationItf_> { static SLInterfaceID_ iid; };
  52. SLInterfaceID_ IntfIID<SLObjectItf_>::iid = { 0x79216360, 0xddd7, 0x11db, 0xac16, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
  53. SLInterfaceID_ IntfIID<SLEngineItf_>::iid = { 0x8d97c260, 0xddd4, 0x11db, 0x958f, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
  54. SLInterfaceID_ IntfIID<SLOutputMixItf_>::iid = { 0x97750f60, 0xddd7, 0x11db, 0x92b1, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
  55. SLInterfaceID_ IntfIID<SLPlayItf_>::iid = { 0xef0bd9c0, 0xddd7, 0x11db, 0xbf49, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
  56. SLInterfaceID_ IntfIID<SLRecordItf_>::iid = { 0xc5657aa0, 0xdddb, 0x11db, 0x82f7, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
  57. SLInterfaceID_ IntfIID<SLAndroidSimpleBufferQueueItf_>::iid = { 0x198e4940, 0xc5d7, 0x11df, 0xa2a6, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
  58. SLInterfaceID_ IntfIID<SLAndroidConfigurationItf_>::iid = { 0x89f6a7e0, 0xbeac, 0x11df, 0x8b5c, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} };
  59. //==============================================================================
  60. // Some life-time and type management of OpenSL objects
  61. class SlObjectRef
  62. {
  63. public:
  64. //==============================================================================
  65. SlObjectRef () noexcept {}
  66. SlObjectRef (const SlObjectRef& obj) noexcept : cb (obj.cb) {}
  67. SlObjectRef (SlObjectRef&& obj) noexcept : cb (static_cast<ReferenceCountedObjectPtr<ControlBlock>&&> (obj.cb)) { obj.cb = nullptr; }
  68. explicit SlObjectRef (SLObjectItf o) : cb (new ControlBlock (o)) {}
  69. //==============================================================================
  70. SlObjectRef& operator=(const SlObjectRef& r) noexcept { cb = r.cb; return *this; }
  71. SlObjectRef& operator=(SlObjectRef&& r) noexcept { cb = static_cast<ReferenceCountedObjectPtr<ControlBlock>&&> (r.cb); r.cb = nullptr; return *this; }
  72. SlObjectRef& operator=(std::nullptr_t) noexcept { cb = nullptr; return *this; }
  73. //==============================================================================
  74. const SLObjectItf_* const operator*() noexcept { return *cb->ptr.get(); }
  75. SLObjectItf operator->() noexcept { return (cb == nullptr ? nullptr : cb->ptr.get()); }
  76. operator SLObjectItf() noexcept { return (cb == nullptr ? nullptr : cb->ptr.get()); }
  77. //==============================================================================
  78. bool operator== (nullptr_t) const noexcept { return (cb == nullptr || cb->ptr == nullptr); }
  79. bool operator!= (nullptr_t) const noexcept { return (cb != nullptr && cb->ptr != nullptr); }
  80. private:
  81. //==============================================================================
  82. struct ControlBlock : ReferenceCountedObject { ScopedPointer<const SLObjectItf_* const> ptr; ControlBlock() {} ControlBlock (SLObjectItf o) : ptr (o) {} };
  83. ReferenceCountedObjectPtr<ControlBlock> cb;
  84. };
  85. template <typename T>
  86. class SlRef : public SlObjectRef
  87. {
  88. public:
  89. //==============================================================================
  90. SlRef () noexcept : type (nullptr) {}
  91. SlRef (SlRef& r) noexcept : SlObjectRef (r), type (r.type) {}
  92. SlRef (SlRef&& r) noexcept : SlObjectRef (static_cast<SlRef&&> (r)), type (r.type) { r.type = nullptr; }
  93. //==============================================================================
  94. SlRef& operator= (const SlRef& r) noexcept { SlObjectRef::operator= (r); type = r.type; return *this; }
  95. SlRef& operator= (SlRef&& r) noexcept { SlObjectRef::operator= (static_cast<SlObjectRef&&> (r)); type = r.type; r.type = nullptr; return *this; }
  96. SlRef& operator= (std::nullptr_t) noexcept { SlObjectRef::operator= (nullptr); type = nullptr; return *this; }
  97. //==============================================================================
  98. T* const operator*() noexcept { return *type; }
  99. T* const * operator->() noexcept { return type; }
  100. operator T* const *() noexcept { return type; }
  101. //==============================================================================
  102. static SlRef cast (SlObjectRef& base) { return SlRef (base); }
  103. static SlRef cast (SlObjectRef&& base) { return SlRef (static_cast<SlObjectRef&&> (base)); }
  104. private:
  105. //==============================================================================
  106. SlRef (SlObjectRef& base) : SlObjectRef (base)
  107. {
  108. SLObjectItf obj = SlObjectRef::operator->();
  109. SLresult err = (*obj)->GetInterface (obj, &IntfIID<T>::iid, &type);
  110. if (type == nullptr || err != SL_RESULT_SUCCESS)
  111. *this = nullptr;
  112. }
  113. SlRef (SlObjectRef&& base) : SlObjectRef (static_cast<SlObjectRef&&> (base))
  114. {
  115. SLObjectItf obj = SlObjectRef::operator->();
  116. SLresult err = (*obj)->GetInterface (obj, &IntfIID<T>::iid, &type);
  117. base = nullptr;
  118. if (type == nullptr || err != SL_RESULT_SUCCESS)
  119. *this = nullptr;
  120. }
  121. T* const * type;
  122. };
  123. template <>
  124. struct ContainerDeletePolicy<const SLObjectItf_* const>
  125. {
  126. static void destroy (SLObjectItf object)
  127. {
  128. if (object != nullptr)
  129. (*object)->Destroy (object);
  130. }
  131. };
  132. //==============================================================================
  133. template <typename T> struct BufferHelpers {};
  134. template <>
  135. struct BufferHelpers<int16>
  136. {
  137. static void initPCMDataFormat (PCMDataFormatEx& dataFormat, int numChannels, double sampleRate)
  138. {
  139. dataFormat.formatType = SL_DATAFORMAT_PCM;
  140. dataFormat.numChannels = (SLuint32) numChannels;
  141. dataFormat.samplesPerSec = (SLuint32) (sampleRate * 1000);
  142. dataFormat.bitsPerSample = SL_PCMSAMPLEFORMAT_FIXED_16;
  143. dataFormat.containerSize = SL_PCMSAMPLEFORMAT_FIXED_16;
  144. dataFormat.channelMask = (numChannels == 1) ? SL_SPEAKER_FRONT_CENTER :
  145. (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
  146. dataFormat.endianness = SL_BYTEORDER_LITTLEENDIAN;
  147. dataFormat.representation = 0;
  148. }
  149. static void prepareCallbackBuffer (AudioSampleBuffer&, int16*) {}
  150. static void convertFromOpenSL (const int16* srcInterleaved, AudioSampleBuffer& audioBuffer)
  151. {
  152. for (int i = 0; i < audioBuffer.getNumChannels(); ++i)
  153. {
  154. typedef AudioData::Pointer<AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DstSampleType;
  155. typedef AudioData::Pointer<AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const> SrcSampleType;
  156. DstSampleType dstData (audioBuffer.getWritePointer (i));
  157. SrcSampleType srcData (srcInterleaved + i, audioBuffer.getNumChannels());
  158. dstData.convertSamples (srcData, audioBuffer.getNumSamples());
  159. }
  160. }
  161. static void convertToOpenSL (const AudioSampleBuffer& audioBuffer, int16* dstInterleaved)
  162. {
  163. for (int i = 0; i < audioBuffer.getNumChannels(); ++i)
  164. {
  165. typedef AudioData::Pointer<AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> DstSampleType;
  166. typedef AudioData::Pointer<AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SrcSampleType;
  167. DstSampleType dstData (dstInterleaved + i, audioBuffer.getNumChannels());
  168. SrcSampleType srcData (audioBuffer.getReadPointer (i));
  169. dstData.convertSamples (srcData, audioBuffer.getNumSamples());
  170. }
  171. }
  172. };
  173. template <>
  174. struct BufferHelpers<float>
  175. {
  176. static void initPCMDataFormat (PCMDataFormatEx& dataFormat, int numChannels, double sampleRate)
  177. {
  178. dataFormat.formatType = SL_ANDROID_DATAFORMAT_PCM_EX;
  179. dataFormat.numChannels = (SLuint32) numChannels;
  180. dataFormat.samplesPerSec = (SLuint32) (sampleRate * 1000);
  181. dataFormat.bitsPerSample = 32;
  182. dataFormat.containerSize = 32;
  183. dataFormat.channelMask = (numChannels == 1) ? SL_SPEAKER_FRONT_CENTER :
  184. (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT);
  185. dataFormat.endianness = SL_BYTEORDER_LITTLEENDIAN;
  186. dataFormat.representation = SL_ANDROID_PCM_REPRESENTATION_FLOAT;
  187. }
  188. static void prepareCallbackBuffer (AudioSampleBuffer& audioBuffer, float* native)
  189. {
  190. if (audioBuffer.getNumChannels() == 1)
  191. audioBuffer.setDataToReferTo (&native, 1, audioBuffer.getNumSamples());
  192. }
  193. static void convertFromOpenSL (const float* srcInterleaved, AudioSampleBuffer& audioBuffer)
  194. {
  195. if (audioBuffer.getNumChannels() == 1)
  196. {
  197. jassert (srcInterleaved == audioBuffer.getWritePointer (0));
  198. return;
  199. }
  200. for (int i = 0; i < audioBuffer.getNumChannels(); ++i)
  201. {
  202. typedef AudioData::Pointer<AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DstSampleType;
  203. typedef AudioData::Pointer<AudioData::Float32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const> SrcSampleType;
  204. DstSampleType dstData (audioBuffer.getWritePointer (i));
  205. SrcSampleType srcData (srcInterleaved + i, audioBuffer.getNumChannels());
  206. dstData.convertSamples (srcData, audioBuffer.getNumSamples());
  207. }
  208. }
  209. static void convertToOpenSL (const AudioSampleBuffer& audioBuffer, float* dstInterleaved)
  210. {
  211. if (audioBuffer.getNumChannels() == 1)
  212. {
  213. jassert (dstInterleaved == audioBuffer.getReadPointer (0));
  214. return;
  215. }
  216. for (int i = 0; i < audioBuffer.getNumChannels(); ++i)
  217. {
  218. typedef AudioData::Pointer<AudioData::Float32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> DstSampleType;
  219. typedef AudioData::Pointer<AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SrcSampleType;
  220. DstSampleType dstData (dstInterleaved + i, audioBuffer.getNumChannels());
  221. SrcSampleType srcData (audioBuffer.getReadPointer (i));
  222. dstData.convertSamples (srcData, audioBuffer.getNumSamples());
  223. }
  224. }
  225. };
  226. //==============================================================================
  227. class OpenSLAudioIODevice : public AudioIODevice
  228. {
  229. public:
  230. //==============================================================================
  231. template <typename T>
  232. class OpenSLSessionT;
  233. //==============================================================================
  234. // CRTP
  235. template <typename T, class Child, typename RunnerObjectType>
  236. struct OpenSLQueueRunner
  237. {
  238. OpenSLQueueRunner (OpenSLSessionT<T>& sessionToUse, int numChannelsToUse)
  239. : owner (sessionToUse),
  240. numChannels (numChannelsToUse),
  241. nativeBuffer (static_cast<size_t> (numChannels * owner.bufferSize * owner.numBuffers)),
  242. scratchBuffer (numChannelsToUse, owner.bufferSize),
  243. sampleBuffer (scratchBuffer.getArrayOfWritePointers(), numChannelsToUse, owner.bufferSize),
  244. nextBlock (0), numBlocksOut (0)
  245. {}
  246. bool init()
  247. {
  248. runner = crtp().createPlayerOrRecorder();
  249. if (runner == nullptr)
  250. return false;
  251. queue = SlRef<SLAndroidSimpleBufferQueueItf_>::cast (runner);
  252. if (queue == nullptr)
  253. return false;
  254. return ((*queue)->RegisterCallback (queue, staticFinished, this) == SL_RESULT_SUCCESS);
  255. }
  256. void clear()
  257. {
  258. nextBlock.set (0);
  259. numBlocksOut.set (0);
  260. zeromem (nativeBuffer.getData(), static_cast<size_t> (owner.bufferSize * numChannels * owner.numBuffers) * sizeof (T));
  261. scratchBuffer.clear();
  262. (*queue)->Clear (queue);
  263. }
  264. void enqueueBuffer ()
  265. {
  266. (*queue)->Enqueue (queue, getCurrentBuffer(), getBufferSizeInSamples() * sizeof (T));
  267. ++numBlocksOut;
  268. }
  269. bool isBufferAvailable() const { return (numBlocksOut.get() < owner.numBuffers); }
  270. T* getNextBuffer() { nextBlock.set((nextBlock.get() + 1) % owner.numBuffers); return getCurrentBuffer(); }
  271. T* getCurrentBuffer() { return nativeBuffer.getData() + (static_cast<size_t> (nextBlock.get()) * getBufferSizeInSamples()); }
  272. size_t getBufferSizeInSamples() const { return static_cast<size_t> (owner.bufferSize * numChannels); }
  273. void finished (SLAndroidSimpleBufferQueueItf)
  274. {
  275. --numBlocksOut;
  276. owner.doSomeWorkOnAudioThread();
  277. }
  278. static void staticFinished (SLAndroidSimpleBufferQueueItf caller, void *pContext)
  279. {
  280. reinterpret_cast<OpenSLQueueRunner*> (pContext)->finished (caller);
  281. }
  282. // get the "this" pointer for CRTP
  283. Child& crtp() { return * ((Child*) this); }
  284. const Child& crtp() const { return * ((Child*) this); }
  285. OpenSLSessionT<T>& owner;
  286. SlRef<RunnerObjectType> runner;
  287. SlRef<SLAndroidSimpleBufferQueueItf_> queue;
  288. int numChannels;
  289. HeapBlock<T> nativeBuffer;
  290. AudioSampleBuffer scratchBuffer, sampleBuffer;
  291. Atomic<int> nextBlock, numBlocksOut;
  292. };
  293. //==============================================================================
  294. template <typename T>
  295. struct OpenSLQueueRunnerPlayer : OpenSLQueueRunner<T, OpenSLQueueRunnerPlayer<T>, SLPlayItf_>
  296. {
  297. typedef OpenSLQueueRunner<T, OpenSLQueueRunnerPlayer<T>, SLPlayItf_> Base;
  298. enum { isPlayer = 1 };
  299. OpenSLQueueRunnerPlayer (OpenSLSessionT<T>& sessionToUse, int numChannelsToUse)
  300. : Base (sessionToUse, numChannelsToUse)
  301. {}
  302. SlRef<SLPlayItf_> createPlayerOrRecorder()
  303. {
  304. SLDataLocator_AndroidSimpleBufferQueue queueLocator = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, static_cast<SLuint32> (Base::owner.numBuffers)};
  305. SLDataLocator_OutputMix outputMix = {SL_DATALOCATOR_OUTPUTMIX, Base::owner.outputMix};
  306. PCMDataFormatEx dataFormat;
  307. BufferHelpers<T>::initPCMDataFormat (dataFormat, Base::numChannels, Base::owner.sampleRate);
  308. SLDataSource source = {&queueLocator, &dataFormat};
  309. SLDataSink sink = {&outputMix, nullptr};
  310. SLInterfaceID queueInterfaces[] = { &IntfIID<SLAndroidSimpleBufferQueueItf_>::iid };
  311. SLboolean trueFlag = SL_BOOLEAN_TRUE;
  312. SLObjectItf obj = nullptr;
  313. SLresult status = (*Base::owner.engine)->CreateAudioPlayer (Base::owner.engine, &obj, &source, &sink, 1, queueInterfaces, &trueFlag);
  314. if (status != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
  315. {
  316. if (obj != nullptr)
  317. (*obj)->Destroy (obj);
  318. return SlRef<SLPlayItf_>();
  319. }
  320. return SlRef<SLPlayItf_>::cast (SlObjectRef (obj));
  321. }
  322. void setState (bool running) { (*Base::runner)->SetPlayState (Base::runner, running ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED); }
  323. };
  324. template <typename T>
  325. struct OpenSLQueueRunnerRecorder : OpenSLQueueRunner<T, OpenSLQueueRunnerRecorder<T>, SLRecordItf_>
  326. {
  327. typedef OpenSLQueueRunner<T, OpenSLQueueRunnerRecorder<T>, SLRecordItf_> Base;
  328. enum { isPlayer = 0 };
  329. OpenSLQueueRunnerRecorder (OpenSLSessionT<T>& sessionToUse, int numChannelsToUse)
  330. : Base (sessionToUse, numChannelsToUse)
  331. {}
  332. SlRef<SLRecordItf_> createPlayerOrRecorder()
  333. {
  334. SLDataLocator_IODevice ioDeviceLocator = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, nullptr};
  335. SLDataLocator_AndroidSimpleBufferQueue queueLocator = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, static_cast<SLuint32> (Base::owner.numBuffers)};
  336. PCMDataFormatEx dataFormat;
  337. BufferHelpers<T>::initPCMDataFormat (dataFormat, Base::numChannels, Base::owner.sampleRate);
  338. SLDataSource source = {&ioDeviceLocator, nullptr};
  339. SLDataSink sink = {&queueLocator, &dataFormat};
  340. SLInterfaceID queueInterfaces[] = { &IntfIID<SLAndroidSimpleBufferQueueItf_>::iid, &IntfIID<SLAndroidConfigurationItf_>::iid };
  341. SLboolean interfaceRequired[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE};
  342. SLObjectItf obj = nullptr;
  343. SLresult status = (*Base::owner.engine)->CreateAudioRecorder (Base::owner.engine, &obj, &source, &sink, 2, queueInterfaces, interfaceRequired);
  344. if (status != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
  345. {
  346. if (obj != nullptr)
  347. (*obj)->Destroy (obj);
  348. return SlRef<SLRecordItf_>();
  349. }
  350. SlRef<SLRecordItf_> recorder = SlRef<SLRecordItf_>::cast (SlObjectRef (obj));
  351. // may return nullptr on some platforms - that's ok
  352. config = SlRef<SLAndroidConfigurationItf_>::cast (recorder);
  353. return recorder;
  354. }
  355. bool setAudioPreprocessingEnabled (bool shouldEnable)
  356. {
  357. if (config != nullptr)
  358. {
  359. const bool supportsUnprocessed = (getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT) >= 25);
  360. const SLuint32 recordingPresetValue
  361. = (shouldEnable ? SL_ANDROID_RECORDING_PRESET_GENERIC
  362. : (supportsUnprocessed ? SL_ANDROID_RECORDING_PRESET_UNPROCESSED
  363. : SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION));
  364. SLresult status = (*config)->SetConfiguration (config, SL_ANDROID_KEY_RECORDING_PRESET,
  365. &recordingPresetValue, sizeof (recordingPresetValue));
  366. return (status == SL_RESULT_SUCCESS);
  367. }
  368. return false;
  369. }
  370. void setState (bool running) { (*Base::runner)->SetRecordState (Base::runner, running ? SL_RECORDSTATE_RECORDING : SL_RECORDSTATE_STOPPED); }
  371. SlRef<SLAndroidConfigurationItf_> config;
  372. };
  373. //==============================================================================
  374. class OpenSLSession
  375. {
  376. public:
  377. OpenSLSession (DynamicLibrary& slLibraryToUse,
  378. int numInputChannels, int numOutputChannels,
  379. double samleRateToUse, int bufferSizeToUse,
  380. int numBuffersToUse)
  381. : inputChannels (numInputChannels), outputChannels (numOutputChannels),
  382. sampleRate (samleRateToUse), bufferSize (bufferSizeToUse), numBuffers (numBuffersToUse),
  383. running (false), audioProcessingEnabled (true), callback (nullptr)
  384. {
  385. jassert (numInputChannels > 0 || numOutputChannels > 0);
  386. if (CreateEngineFunc createEngine = (CreateEngineFunc) slLibraryToUse.getFunction ("slCreateEngine"))
  387. {
  388. SLObjectItf obj = nullptr;
  389. SLresult err = createEngine (&obj, 0, nullptr, 0, nullptr, nullptr);
  390. if (err != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
  391. {
  392. if (obj != nullptr)
  393. (*obj)->Destroy (obj);
  394. return;
  395. }
  396. engine = SlRef<SLEngineItf_>::cast (SlObjectRef (obj));
  397. }
  398. if (outputChannels > 0)
  399. {
  400. SLObjectItf obj = nullptr;
  401. SLresult err = (*engine)->CreateOutputMix (engine, &obj, 0, nullptr, nullptr);
  402. if (err != SL_RESULT_SUCCESS || obj == nullptr || (*obj)->Realize (obj, 0) != SL_RESULT_SUCCESS)
  403. {
  404. if (obj != nullptr)
  405. (*obj)->Destroy (obj);
  406. return;
  407. }
  408. outputMix = SlRef<SLOutputMixItf_>::cast (SlObjectRef (obj));
  409. }
  410. }
  411. virtual ~OpenSLSession() {}
  412. virtual bool openedOK() const { return (engine != nullptr && (outputChannels == 0 || (outputMix != nullptr))); }
  413. virtual void start() { stop(); jassert (callback.get() != nullptr); running = true; }
  414. virtual void stop() { running = false; }
  415. virtual bool setAudioPreprocessingEnabled (bool shouldEnable) = 0;
  416. void setCallback (AudioIODeviceCallback* callbackToUse)
  417. {
  418. if (! running)
  419. {
  420. callback.set (callbackToUse);
  421. return;
  422. }
  423. // don't set callback to null! stop the playback instead!
  424. jassert (callbackToUse != nullptr);
  425. // spin-lock until we can set the callback
  426. while (true)
  427. {
  428. AudioIODeviceCallback* old = callback.get();
  429. if (old == callbackToUse)
  430. break;
  431. if (callback.compareAndSetValue (callbackToUse, old) == old)
  432. break;
  433. Thread::sleep (1);
  434. }
  435. }
  436. void process (const float** inputChannelData, float** outputChannelData)
  437. {
  438. if (AudioIODeviceCallback* cb = callback.exchange(nullptr))
  439. {
  440. cb->audioDeviceIOCallback (inputChannelData, inputChannels, outputChannelData, outputChannels, bufferSize);
  441. callback.set (cb);
  442. }
  443. else
  444. {
  445. for (int i = 0; i < outputChannels; ++i)
  446. zeromem (outputChannelData[i], sizeof(float) * static_cast<size_t> (bufferSize));
  447. }
  448. }
  449. static OpenSLSession* create (DynamicLibrary& slLibrary,
  450. int numInputChannels, int numOutputChannels,
  451. double samleRateToUse, int bufferSizeToUse,
  452. int numBuffersToUse,
  453. bool floatingPointSupport);
  454. //==============================================================================
  455. typedef SLresult (*CreateEngineFunc)(SLObjectItf*,SLuint32,const SLEngineOption*,SLuint32,const SLInterfaceID*,const SLboolean*);
  456. //==============================================================================
  457. int inputChannels, outputChannels;
  458. double sampleRate;
  459. int bufferSize, numBuffers;
  460. bool running, audioProcessingEnabled;
  461. SlRef<SLEngineItf_> engine;
  462. SlRef<SLOutputMixItf_> outputMix;
  463. Atomic<AudioIODeviceCallback*> callback;
  464. };
  465. template <typename T>
  466. class OpenSLSessionT : public OpenSLSession
  467. {
  468. public:
  469. OpenSLSessionT (DynamicLibrary& slLibraryToUse,
  470. int numInputChannels, int numOutputChannels,
  471. double samleRateToUse, int bufferSizeToUse,
  472. int numBuffersToUse)
  473. : OpenSLSession (slLibraryToUse, numInputChannels, numOutputChannels, samleRateToUse, bufferSizeToUse, numBuffersToUse)
  474. {
  475. jassert (numInputChannels > 0 || numOutputChannels > 0);
  476. if (OpenSLSession::openedOK())
  477. {
  478. if (inputChannels > 0)
  479. {
  480. recorder = new OpenSLQueueRunnerRecorder<T>(*this, inputChannels);
  481. if (! recorder->init())
  482. {
  483. recorder = nullptr;
  484. return;
  485. }
  486. }
  487. if (outputChannels > 0)
  488. {
  489. player = new OpenSLQueueRunnerPlayer<T>(*this, outputChannels);
  490. if (! player->init())
  491. {
  492. player = nullptr;
  493. return;
  494. }
  495. }
  496. }
  497. }
  498. bool openedOK() const override
  499. {
  500. return (OpenSLSession::openedOK() && (inputChannels == 0 || recorder != nullptr)
  501. && (outputChannels == 0 || player != nullptr));
  502. }
  503. void start() override
  504. {
  505. OpenSLSession::start();
  506. guard.set (0);
  507. if (inputChannels > 0)
  508. recorder->clear();
  509. if (outputChannels > 0)
  510. player->clear();
  511. // first enqueue all buffers
  512. for (int i = 0; i < numBuffers; ++i)
  513. doSomeWorkOnAudioThread();
  514. if (inputChannels > 0)
  515. recorder->setState (true);
  516. if (outputChannels > 0)
  517. player->setState (true);
  518. }
  519. void stop() override
  520. {
  521. OpenSLSession::stop();
  522. if (inputChannels > 0)
  523. recorder->setState (false);
  524. if (outputChannels > 0)
  525. player->setState (false);
  526. }
  527. bool setAudioPreprocessingEnabled (bool shouldEnable) override
  528. {
  529. if (shouldEnable != audioProcessingEnabled)
  530. {
  531. audioProcessingEnabled = shouldEnable;
  532. if (recorder != nullptr)
  533. return recorder->setAudioPreprocessingEnabled (audioProcessingEnabled);
  534. }
  535. return true;
  536. }
  537. void doSomeWorkOnAudioThread()
  538. {
  539. // only the player or the recorder should enter this section at any time
  540. if (guard.compareAndSetBool (1, 0))
  541. {
  542. // are there enough buffers avaialable to process some audio
  543. if ((inputChannels == 0 || recorder->isBufferAvailable()) && (outputChannels == 0 || player->isBufferAvailable()))
  544. {
  545. T* recorderBuffer = (inputChannels > 0 ? recorder->getNextBuffer() : nullptr);
  546. T* playerBuffer = (outputChannels > 0 ? player->getNextBuffer() : nullptr);
  547. const float** inputChannelData = nullptr;
  548. float** outputChannelData = nullptr;
  549. if (recorderBuffer != nullptr)
  550. {
  551. BufferHelpers<T>::prepareCallbackBuffer (recorder->sampleBuffer, recorderBuffer);
  552. BufferHelpers<T>::convertFromOpenSL (recorderBuffer, recorder->sampleBuffer);
  553. inputChannelData = recorder->sampleBuffer.getArrayOfReadPointers();
  554. }
  555. if (playerBuffer != nullptr)
  556. {
  557. BufferHelpers<T>::prepareCallbackBuffer (player->sampleBuffer, playerBuffer);
  558. outputChannelData = player->sampleBuffer.getArrayOfWritePointers();
  559. }
  560. process (inputChannelData, outputChannelData);
  561. if (recorderBuffer != nullptr)
  562. recorder->enqueueBuffer();
  563. if (playerBuffer != nullptr)
  564. {
  565. BufferHelpers<T>::convertToOpenSL (player->sampleBuffer, playerBuffer);
  566. player->enqueueBuffer();
  567. }
  568. }
  569. guard.set (0);
  570. }
  571. }
  572. //==============================================================================
  573. ScopedPointer<OpenSLQueueRunnerPlayer<T> > player;
  574. ScopedPointer<OpenSLQueueRunnerRecorder<T> > recorder;
  575. Atomic<int> guard;
  576. };
  577. //==============================================================================
  578. OpenSLAudioIODevice (const String& deviceName)
  579. : AudioIODevice (deviceName, openSLTypeName),
  580. audioProcessingEnabled (true),
  581. callback (nullptr)
  582. {
  583. // OpenSL has piss-poor support for determining latency, so the only way I can find to
  584. // get a number for this is by asking the AudioTrack/AudioRecord classes..
  585. AndroidAudioIODevice javaDevice (deviceName);
  586. // this is a total guess about how to calculate the latency, but seems to vaguely agree
  587. // with the devices I've tested.. YMMV
  588. inputLatency = (javaDevice.minBufferSizeIn * 2) / 3;
  589. outputLatency = (javaDevice.minBufferSizeOut * 2) / 3;
  590. const int64 longestLatency = jmax (inputLatency, outputLatency);
  591. const int64 totalLatency = inputLatency + outputLatency;
  592. inputLatency = (int) ((longestLatency * inputLatency) / totalLatency) & ~15;
  593. outputLatency = (int) ((longestLatency * outputLatency) / totalLatency) & ~15;
  594. supportsFloatingPoint = getSupportsFloatingPoint();
  595. bool success = slLibrary.open ("libOpenSLES.so");
  596. // You can only create this class if you are sure that your hardware supports OpenSL
  597. jassert (success);
  598. ignoreUnused (success);
  599. }
  600. ~OpenSLAudioIODevice()
  601. {
  602. close();
  603. }
  604. bool openedOk() const { return session != nullptr; }
  605. StringArray getOutputChannelNames() override
  606. {
  607. StringArray s;
  608. s.add ("Left");
  609. s.add ("Right");
  610. return s;
  611. }
  612. StringArray getInputChannelNames() override
  613. {
  614. StringArray s;
  615. s.add ("Audio Input");
  616. return s;
  617. }
  618. Array<double> getAvailableSampleRates() override
  619. {
  620. //see https://developer.android.com/ndk/guides/audio/opensl-for-android.html
  621. static const double rates[] = { 8000.0, 11025.0, 12000.0, 16000.0,
  622. 22050.0, 24000.0, 32000.0, 44100.0, 48000.0 };
  623. Array<double> retval (rates, numElementsInArray (rates));
  624. // make sure the native sample rate is pafrt of the list
  625. double native = getNativeSampleRate();
  626. if (native != 0.0 && ! retval.contains (native))
  627. retval.add (native);
  628. return retval;
  629. }
  630. Array<int> getAvailableBufferSizes() override
  631. {
  632. // we need to offer the lowest possible buffer size which
  633. // is the native buffer size
  634. const int defaultNumMultiples = 8;
  635. const int nativeBufferSize = getNativeBufferSize();
  636. Array<int> retval;
  637. for (int i = 1; i < defaultNumMultiples; ++i)
  638. retval.add (i * nativeBufferSize);
  639. return retval;
  640. }
  641. String open (const BigInteger& inputChannels,
  642. const BigInteger& outputChannels,
  643. double requestedSampleRate,
  644. int bufferSize) override
  645. {
  646. close();
  647. lastError.clear();
  648. sampleRate = (int) requestedSampleRate;
  649. int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
  650. activeOutputChans = outputChannels;
  651. activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false);
  652. int numOutputChannels = activeOutputChans.countNumberOfSetBits();
  653. activeInputChans = inputChannels;
  654. activeInputChans.setRange (1, activeInputChans.getHighestBit(), false);
  655. int numInputChannels = activeInputChans.countNumberOfSetBits();
  656. actualBufferSize = preferredBufferSize;
  657. const int audioBuffersToEnqueue = hasLowLatencyAudioPath() ? buffersToEnqueueForLowLatency
  658. : buffersToEnqueueSlowAudio;
  659. DBG ("OpenSL: numInputChannels = " << numInputChannels
  660. << ", numOutputChannels = " << numOutputChannels
  661. << ", nativeBufferSize = " << getNativeBufferSize()
  662. << ", nativeSampleRate = " << getNativeSampleRate()
  663. << ", actualBufferSize = " << actualBufferSize
  664. << ", audioBuffersToEnqueue = " << audioBuffersToEnqueue
  665. << ", sampleRate = " << sampleRate
  666. << ", supportsFloatingPoint = " << (supportsFloatingPoint ? "true" : "false"));
  667. if (numInputChannels > 0 && (! RuntimePermissions::isGranted (RuntimePermissions::recordAudio)))
  668. {
  669. // If you hit this assert, you probably forgot to get RuntimePermissions::recordAudio
  670. // before trying to open an audio input device. This is not going to work!
  671. jassertfalse;
  672. lastError = "Error opening OpenSL input device: the app was not granted android.permission.RECORD_AUDIO";
  673. }
  674. session = OpenSLSession::create (slLibrary, numInputChannels, numOutputChannels,
  675. sampleRate, actualBufferSize, audioBuffersToEnqueue,
  676. supportsFloatingPoint);
  677. if (session == nullptr)
  678. lastError = "Unknown error initializing opensl session";
  679. session->setAudioPreprocessingEnabled (audioProcessingEnabled);
  680. deviceOpen = (session != nullptr);
  681. return lastError;
  682. }
  683. void close() override
  684. {
  685. stop();
  686. session = nullptr;
  687. callback = nullptr;
  688. }
  689. int getOutputLatencyInSamples() override { return outputLatency; }
  690. int getInputLatencyInSamples() override { return inputLatency; }
  691. bool isOpen() override { return deviceOpen; }
  692. int getCurrentBufferSizeSamples() override { return actualBufferSize; }
  693. int getCurrentBitDepth() override { return supportsFloatingPoint ? 32 : 16; }
  694. BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
  695. BigInteger getActiveInputChannels() const override { return activeInputChans; }
  696. String getLastError() override { return lastError; }
  697. bool isPlaying() override { return callback != nullptr; }
  698. int getDefaultBufferSize() override
  699. {
  700. // Only on a Pro-Audio device will we set the lowest possible buffer size
  701. // by default. We need to be more conservative on other devices
  702. // as they may be low-latency, but still have a crappy CPU.
  703. return (isProAudioDevice() ? 1 : 6)
  704. * defaultBufferSizeIsMultipleOfNative * getNativeBufferSize();
  705. }
  706. double getCurrentSampleRate() override
  707. {
  708. return (sampleRate == 0.0 ? getNativeSampleRate() : sampleRate);
  709. }
  710. void start (AudioIODeviceCallback* newCallback) override
  711. {
  712. if (session != nullptr && callback != newCallback)
  713. {
  714. AudioIODeviceCallback* oldCallback = callback;
  715. if (newCallback != nullptr)
  716. newCallback->audioDeviceAboutToStart (this);
  717. if (oldCallback != nullptr)
  718. {
  719. // already running
  720. if (newCallback == nullptr)
  721. stop();
  722. else
  723. session->setCallback (newCallback);
  724. oldCallback->audioDeviceStopped();
  725. }
  726. else
  727. {
  728. jassert (newCallback != nullptr);
  729. // session hasn't started yet
  730. session->setCallback (newCallback);
  731. session->start();
  732. }
  733. callback = newCallback;
  734. }
  735. }
  736. void stop() override
  737. {
  738. if (session != nullptr && callback != nullptr)
  739. {
  740. callback = nullptr;
  741. session->stop();
  742. session->setCallback (nullptr);
  743. }
  744. }
  745. bool setAudioPreprocessingEnabled (bool shouldAudioProcessingBeEnabled) override
  746. {
  747. audioProcessingEnabled = shouldAudioProcessingBeEnabled;
  748. if (session != nullptr)
  749. session->setAudioPreprocessingEnabled (audioProcessingEnabled);
  750. return true;
  751. }
  752. static const char* const openSLTypeName;
  753. private:
  754. //==============================================================================
  755. DynamicLibrary slLibrary;
  756. int actualBufferSize, sampleRate;
  757. int inputLatency, outputLatency;
  758. bool deviceOpen, supportsFloatingPoint, audioProcessingEnabled;
  759. String lastError;
  760. BigInteger activeOutputChans, activeInputChans;
  761. AudioIODeviceCallback* callback;
  762. ScopedPointer<OpenSLSession> session;
  763. enum
  764. {
  765. // The number of buffers to enqueue needs to be at least two for the audio to use the low-latency
  766. // audio path (see "Performance" section in ndk/docs/Additional_library_docs/opensles/index.html)
  767. buffersToEnqueueForLowLatency = 2,
  768. buffersToEnqueueSlowAudio = 4,
  769. defaultBufferSizeIsMultipleOfNative = 1
  770. };
  771. //==============================================================================
  772. static String audioManagerGetProperty (const String& property)
  773. {
  774. const LocalRef<jstring> jProperty (javaString (property));
  775. const LocalRef<jstring> text ((jstring) android.activity.callObjectMethod (JuceAppActivity.audioManagerGetProperty,
  776. jProperty.get()));
  777. if (text.get() != 0)
  778. return juceString (text);
  779. return String();
  780. }
  781. static bool androidHasSystemFeature (const String& property)
  782. {
  783. const LocalRef<jstring> jProperty (javaString (property));
  784. return android.activity.callBooleanMethod (JuceAppActivity.hasSystemFeature, jProperty.get());
  785. }
  786. static double getNativeSampleRate()
  787. {
  788. return audioManagerGetProperty ("android.media.property.OUTPUT_SAMPLE_RATE").getDoubleValue();
  789. }
  790. static int getNativeBufferSize()
  791. {
  792. const int val = audioManagerGetProperty ("android.media.property.OUTPUT_FRAMES_PER_BUFFER").getIntValue();
  793. return val > 0 ? val : 512;
  794. }
  795. static bool isProAudioDevice()
  796. {
  797. return androidHasSystemFeature ("android.hardware.audio.pro");
  798. }
  799. static bool hasLowLatencyAudioPath()
  800. {
  801. return androidHasSystemFeature ("android.hardware.audio.low_latency");
  802. }
  803. static bool getSupportsFloatingPoint()
  804. {
  805. return (getEnv()->GetStaticIntField (AndroidBuildVersion, AndroidBuildVersion.SDK_INT) >= 21);
  806. }
  807. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenSLAudioIODevice)
  808. };
  809. OpenSLAudioIODevice::OpenSLSession* OpenSLAudioIODevice::OpenSLSession::create (DynamicLibrary& slLibrary,
  810. int numInputChannels, int numOutputChannels,
  811. double samleRateToUse, int bufferSizeToUse,
  812. int numBuffersToUse,
  813. bool floatingPointSupport)
  814. {
  815. ScopedPointer<OpenSLSession> retval;
  816. if (floatingPointSupport)
  817. retval = new OpenSLSessionT<float> (slLibrary, numInputChannels, numOutputChannels, samleRateToUse,
  818. bufferSizeToUse, numBuffersToUse);
  819. else
  820. retval = new OpenSLSessionT<int16> (slLibrary, numInputChannels, numOutputChannels, samleRateToUse,
  821. bufferSizeToUse, numBuffersToUse);
  822. if (retval != nullptr && (! retval->openedOK()))
  823. retval = nullptr;
  824. return retval.release();
  825. }
  826. //==============================================================================
  827. class OpenSLAudioDeviceType : public AudioIODeviceType
  828. {
  829. public:
  830. OpenSLAudioDeviceType() : AudioIODeviceType (OpenSLAudioIODevice::openSLTypeName) {}
  831. //==============================================================================
  832. void scanForDevices() override {}
  833. StringArray getDeviceNames (bool) const override { return StringArray (OpenSLAudioIODevice::openSLTypeName); }
  834. int getDefaultDeviceIndex (bool) const override { return 0; }
  835. int getIndexOfDevice (AudioIODevice* device, bool) const override { return device != nullptr ? 0 : -1; }
  836. bool hasSeparateInputsAndOutputs() const override { return false; }
  837. AudioIODevice* createDevice (const String& outputDeviceName,
  838. const String& inputDeviceName) override
  839. {
  840. ScopedPointer<OpenSLAudioIODevice> dev;
  841. if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty())
  842. dev = new OpenSLAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
  843. : inputDeviceName);
  844. return dev.release();
  845. }
  846. static bool isOpenSLAvailable()
  847. {
  848. DynamicLibrary library;
  849. return library.open ("libOpenSLES.so");
  850. }
  851. private:
  852. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenSLAudioDeviceType)
  853. };
  854. const char* const OpenSLAudioIODevice::openSLTypeName = "Android OpenSL";
  855. //==============================================================================
  856. bool isOpenSLAvailable() { return OpenSLAudioDeviceType::isOpenSLAvailable(); }
  857. AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_OpenSLES()
  858. {
  859. return isOpenSLAvailable() ? new OpenSLAudioDeviceType() : nullptr;
  860. }