Audio plugin host https://kx.studio/carla
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.

juce_android_OpenSL.cpp 25KB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. const char* const openSLTypeName = "Android OpenSL";
  18. bool isOpenSLAvailable()
  19. {
  20. DynamicLibrary library;
  21. return library.open ("libOpenSLES.so");
  22. }
  23. //==============================================================================
  24. class OpenSLAudioIODevice : public AudioIODevice,
  25. public Thread
  26. {
  27. public:
  28. OpenSLAudioIODevice (const String& deviceName)
  29. : AudioIODevice (deviceName, openSLTypeName),
  30. Thread ("OpenSL"),
  31. callback (nullptr), sampleRate (0), deviceOpen (false),
  32. inputBuffer (2, 2), outputBuffer (2, 2)
  33. {
  34. // OpenSL has piss-poor support for determining latency, so the only way I can find to
  35. // get a number for this is by asking the AudioTrack/AudioRecord classes..
  36. AndroidAudioIODevice javaDevice (String::empty);
  37. // this is a total guess about how to calculate the latency, but seems to vaguely agree
  38. // with the devices I've tested.. YMMV
  39. inputLatency = ((javaDevice.minBufferSizeIn * 2) / 3);
  40. outputLatency = ((javaDevice.minBufferSizeOut * 2) / 3);
  41. const int longestLatency = jmax (inputLatency, outputLatency);
  42. const int totalLatency = inputLatency + outputLatency;
  43. inputLatency = ((longestLatency * inputLatency) / totalLatency) & ~15;
  44. outputLatency = ((longestLatency * outputLatency) / totalLatency) & ~15;
  45. }
  46. ~OpenSLAudioIODevice()
  47. {
  48. close();
  49. }
  50. bool openedOk() const { return engine.outputMixObject != nullptr; }
  51. StringArray getOutputChannelNames() override
  52. {
  53. StringArray s;
  54. s.add ("Left");
  55. s.add ("Right");
  56. return s;
  57. }
  58. StringArray getInputChannelNames() override
  59. {
  60. StringArray s;
  61. s.add ("Audio Input");
  62. return s;
  63. }
  64. Array<double> getAvailableSampleRates() override
  65. {
  66. static const double rates[] = { 8000.0, 16000.0, 32000.0, 44100.0, 48000.0 };
  67. return Array<double> (rates, numElementsInArray (rates));
  68. }
  69. Array<int> getAvailableBufferSizes() override
  70. {
  71. static const int sizes[] = { 256, 512, 768, 1024, 1280, 1600 }; // must all be multiples of the block size
  72. return Array<int> (sizes, numElementsInArray (sizes));
  73. }
  74. String open (const BigInteger& inputChannels,
  75. const BigInteger& outputChannels,
  76. double requestedSampleRate,
  77. int bufferSize) override
  78. {
  79. close();
  80. lastError.clear();
  81. sampleRate = (int) requestedSampleRate;
  82. int preferredBufferSize = (bufferSize <= 0) ? getDefaultBufferSize() : bufferSize;
  83. activeOutputChans = outputChannels;
  84. activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false);
  85. numOutputChannels = activeOutputChans.countNumberOfSetBits();
  86. activeInputChans = inputChannels;
  87. activeInputChans.setRange (1, activeInputChans.getHighestBit(), false);
  88. numInputChannels = activeInputChans.countNumberOfSetBits();
  89. actualBufferSize = preferredBufferSize;
  90. inputBuffer.setSize (jmax (1, numInputChannels), actualBufferSize);
  91. outputBuffer.setSize (jmax (1, numOutputChannels), actualBufferSize);
  92. outputBuffer.clear();
  93. recorder = engine.createRecorder (numInputChannels, sampleRate);
  94. player = engine.createPlayer (numOutputChannels, sampleRate);
  95. startThread (8);
  96. deviceOpen = true;
  97. return lastError;
  98. }
  99. void close() override
  100. {
  101. stop();
  102. stopThread (6000);
  103. deviceOpen = false;
  104. recorder = nullptr;
  105. player = nullptr;
  106. }
  107. int getDefaultBufferSize() override { return 1024; }
  108. int getOutputLatencyInSamples() override { return outputLatency; }
  109. int getInputLatencyInSamples() override { return inputLatency; }
  110. bool isOpen() override { return deviceOpen; }
  111. int getCurrentBufferSizeSamples() override { return actualBufferSize; }
  112. int getCurrentBitDepth() override { return 16; }
  113. double getCurrentSampleRate() override { return sampleRate; }
  114. BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
  115. BigInteger getActiveInputChannels() const override { return activeInputChans; }
  116. String getLastError() override { return lastError; }
  117. bool isPlaying() override { return callback != nullptr; }
  118. void start (AudioIODeviceCallback* newCallback) override
  119. {
  120. stop();
  121. if (deviceOpen && callback != newCallback)
  122. {
  123. if (newCallback != nullptr)
  124. newCallback->audioDeviceAboutToStart (this);
  125. setCallback (newCallback);
  126. }
  127. }
  128. void stop() override
  129. {
  130. if (AudioIODeviceCallback* const oldCallback = setCallback (nullptr))
  131. oldCallback->audioDeviceStopped();
  132. }
  133. bool setAudioPreprocessingEnabled (bool enable) override
  134. {
  135. return recorder != nullptr && recorder->setAudioPreprocessingEnabled (enable);
  136. }
  137. private:
  138. //==================================================================================================
  139. CriticalSection callbackLock;
  140. AudioIODeviceCallback* callback;
  141. int actualBufferSize, sampleRate;
  142. int inputLatency, outputLatency;
  143. bool deviceOpen;
  144. String lastError;
  145. BigInteger activeOutputChans, activeInputChans;
  146. int numInputChannels, numOutputChannels;
  147. AudioSampleBuffer inputBuffer, outputBuffer;
  148. struct Player;
  149. struct Recorder;
  150. AudioIODeviceCallback* setCallback (AudioIODeviceCallback* const newCallback)
  151. {
  152. const ScopedLock sl (callbackLock);
  153. AudioIODeviceCallback* const oldCallback = callback;
  154. callback = newCallback;
  155. return oldCallback;
  156. }
  157. void run() override
  158. {
  159. if (recorder != nullptr) recorder->start();
  160. if (player != nullptr) player->start();
  161. while (! threadShouldExit())
  162. {
  163. if (player != nullptr) player->writeBuffer (outputBuffer, *this);
  164. if (recorder != nullptr) recorder->readNextBlock (inputBuffer, *this);
  165. const ScopedLock sl (callbackLock);
  166. if (callback != nullptr)
  167. {
  168. callback->audioDeviceIOCallback (numInputChannels > 0 ? inputBuffer.getArrayOfReadPointers() : nullptr, numInputChannels,
  169. numOutputChannels > 0 ? outputBuffer.getArrayOfWritePointers() : nullptr, numOutputChannels,
  170. actualBufferSize);
  171. }
  172. else
  173. {
  174. outputBuffer.clear();
  175. }
  176. }
  177. }
  178. //==================================================================================================
  179. struct Engine
  180. {
  181. Engine()
  182. : engineObject (nullptr), engineInterface (nullptr), outputMixObject (nullptr)
  183. {
  184. if (library.open ("libOpenSLES.so"))
  185. {
  186. typedef SLresult (*CreateEngineFunc) (SLObjectItf*, SLuint32, const SLEngineOption*, SLuint32, const SLInterfaceID*, const SLboolean*);
  187. if (CreateEngineFunc createEngine = (CreateEngineFunc) library.getFunction ("slCreateEngine"))
  188. {
  189. check (createEngine (&engineObject, 0, nullptr, 0, nullptr, nullptr));
  190. SLInterfaceID* SL_IID_ENGINE = (SLInterfaceID*) library.getFunction ("SL_IID_ENGINE");
  191. SL_IID_ANDROIDSIMPLEBUFFERQUEUE = (SLInterfaceID*) library.getFunction ("SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
  192. SL_IID_PLAY = (SLInterfaceID*) library.getFunction ("SL_IID_PLAY");
  193. SL_IID_RECORD = (SLInterfaceID*) library.getFunction ("SL_IID_RECORD");
  194. SL_IID_ANDROIDCONFIGURATION = (SLInterfaceID*) library.getFunction ("SL_IID_ANDROIDCONFIGURATION");
  195. check ((*engineObject)->Realize (engineObject, SL_BOOLEAN_FALSE));
  196. check ((*engineObject)->GetInterface (engineObject, *SL_IID_ENGINE, &engineInterface));
  197. check ((*engineInterface)->CreateOutputMix (engineInterface, &outputMixObject, 0, nullptr, nullptr));
  198. check ((*outputMixObject)->Realize (outputMixObject, SL_BOOLEAN_FALSE));
  199. }
  200. }
  201. }
  202. ~Engine()
  203. {
  204. if (outputMixObject != nullptr) (*outputMixObject)->Destroy (outputMixObject);
  205. if (engineObject != nullptr) (*engineObject)->Destroy (engineObject);
  206. }
  207. Player* createPlayer (const int numChannels, const int sampleRate)
  208. {
  209. if (numChannels <= 0)
  210. return nullptr;
  211. ScopedPointer<Player> player (new Player (numChannels, sampleRate, *this));
  212. return player->openedOk() ? player.release() : nullptr;
  213. }
  214. Recorder* createRecorder (const int numChannels, const int sampleRate)
  215. {
  216. if (numChannels <= 0)
  217. return nullptr;
  218. ScopedPointer<Recorder> recorder (new Recorder (numChannels, sampleRate, *this));
  219. return recorder->openedOk() ? recorder.release() : nullptr;
  220. }
  221. SLObjectItf engineObject;
  222. SLEngineItf engineInterface;
  223. SLObjectItf outputMixObject;
  224. SLInterfaceID* SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
  225. SLInterfaceID* SL_IID_PLAY;
  226. SLInterfaceID* SL_IID_RECORD;
  227. SLInterfaceID* SL_IID_ANDROIDCONFIGURATION;
  228. private:
  229. DynamicLibrary library;
  230. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Engine)
  231. };
  232. //==================================================================================================
  233. struct BufferList
  234. {
  235. BufferList (const int numChannels_)
  236. : numChannels (numChannels_), bufferSpace (numChannels_ * numSamples * numBuffers), nextBlock (0)
  237. {
  238. }
  239. int16* waitForFreeBuffer (Thread& threadToCheck)
  240. {
  241. while (numBlocksOut.get() == numBuffers)
  242. {
  243. dataArrived.wait (1);
  244. if (threadToCheck.threadShouldExit())
  245. return nullptr;
  246. }
  247. return getNextBuffer();
  248. }
  249. int16* getNextBuffer()
  250. {
  251. if (++nextBlock == numBuffers)
  252. nextBlock = 0;
  253. return bufferSpace + nextBlock * numChannels * numSamples;
  254. }
  255. void bufferReturned() { --numBlocksOut; dataArrived.signal(); }
  256. void bufferSent() { ++numBlocksOut; dataArrived.signal(); }
  257. int getBufferSizeBytes() const { return numChannels * numSamples * sizeof (int16); }
  258. const int numChannels;
  259. enum { numSamples = 256, numBuffers = 16 };
  260. private:
  261. HeapBlock<int16> bufferSpace;
  262. int nextBlock;
  263. Atomic<int> numBlocksOut;
  264. WaitableEvent dataArrived;
  265. };
  266. //==================================================================================================
  267. struct Player
  268. {
  269. Player (int numChannels, int sampleRate, Engine& engine)
  270. : playerObject (nullptr), playerPlay (nullptr), playerBufferQueue (nullptr),
  271. bufferList (numChannels)
  272. {
  273. jassert (numChannels == 2);
  274. SLDataFormat_PCM pcmFormat =
  275. {
  276. SL_DATAFORMAT_PCM,
  277. numChannels,
  278. sampleRate * 1000, // (sample rate units are millihertz)
  279. SL_PCMSAMPLEFORMAT_FIXED_16,
  280. SL_PCMSAMPLEFORMAT_FIXED_16,
  281. SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
  282. SL_BYTEORDER_LITTLEENDIAN
  283. };
  284. SLDataLocator_AndroidSimpleBufferQueue bufferQueue = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, bufferList.numBuffers };
  285. SLDataSource audioSrc = { &bufferQueue, &pcmFormat };
  286. SLDataLocator_OutputMix outputMix = { SL_DATALOCATOR_OUTPUTMIX, engine.outputMixObject };
  287. SLDataSink audioSink = { &outputMix, nullptr };
  288. // (SL_IID_BUFFERQUEUE is not guaranteed to remain future-proof, so use SL_IID_ANDROIDSIMPLEBUFFERQUEUE)
  289. const SLInterfaceID interfaceIDs[] = { *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE };
  290. const SLboolean flags[] = { SL_BOOLEAN_TRUE };
  291. check ((*engine.engineInterface)->CreateAudioPlayer (engine.engineInterface, &playerObject, &audioSrc, &audioSink,
  292. 1, interfaceIDs, flags));
  293. check ((*playerObject)->Realize (playerObject, SL_BOOLEAN_FALSE));
  294. check ((*playerObject)->GetInterface (playerObject, *engine.SL_IID_PLAY, &playerPlay));
  295. check ((*playerObject)->GetInterface (playerObject, *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &playerBufferQueue));
  296. check ((*playerBufferQueue)->RegisterCallback (playerBufferQueue, staticCallback, this));
  297. }
  298. ~Player()
  299. {
  300. if (playerPlay != nullptr)
  301. check ((*playerPlay)->SetPlayState (playerPlay, SL_PLAYSTATE_STOPPED));
  302. if (playerBufferQueue != nullptr)
  303. check ((*playerBufferQueue)->Clear (playerBufferQueue));
  304. if (playerObject != nullptr)
  305. (*playerObject)->Destroy (playerObject);
  306. }
  307. bool openedOk() const noexcept { return playerBufferQueue != nullptr; }
  308. void start()
  309. {
  310. jassert (openedOk());
  311. check ((*playerPlay)->SetPlayState (playerPlay, SL_PLAYSTATE_PLAYING));
  312. }
  313. void writeBuffer (const AudioSampleBuffer& buffer, Thread& thread)
  314. {
  315. jassert (buffer.getNumChannels() == bufferList.numChannels);
  316. jassert (buffer.getNumSamples() < bufferList.numSamples * bufferList.numBuffers);
  317. int offset = 0;
  318. int numSamples = buffer.getNumSamples();
  319. while (numSamples > 0)
  320. {
  321. int16* const destBuffer = bufferList.waitForFreeBuffer (thread);
  322. if (destBuffer == nullptr)
  323. break;
  324. for (int i = 0; i < bufferList.numChannels; ++i)
  325. {
  326. typedef AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> DstSampleType;
  327. typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SrcSampleType;
  328. DstSampleType dstData (destBuffer + i, bufferList.numChannels);
  329. SrcSampleType srcData (buffer.getReadPointer (i, offset));
  330. dstData.convertSamples (srcData, bufferList.numSamples);
  331. }
  332. check ((*playerBufferQueue)->Enqueue (playerBufferQueue, destBuffer, bufferList.getBufferSizeBytes()));
  333. bufferList.bufferSent();
  334. numSamples -= bufferList.numSamples;
  335. offset += bufferList.numSamples;
  336. }
  337. }
  338. private:
  339. SLObjectItf playerObject;
  340. SLPlayItf playerPlay;
  341. SLAndroidSimpleBufferQueueItf playerBufferQueue;
  342. BufferList bufferList;
  343. static void staticCallback (SLAndroidSimpleBufferQueueItf queue, void* context)
  344. {
  345. jassert (queue == static_cast <Player*> (context)->playerBufferQueue); (void) queue;
  346. static_cast <Player*> (context)->bufferList.bufferReturned();
  347. }
  348. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Player)
  349. };
  350. //==================================================================================================
  351. struct Recorder
  352. {
  353. Recorder (int numChannels, int sampleRate, Engine& engine)
  354. : recorderObject (nullptr), recorderRecord (nullptr),
  355. recorderBufferQueue (nullptr), configObject (nullptr),
  356. bufferList (numChannels)
  357. {
  358. jassert (numChannels == 1); // STEREO doesn't always work!!
  359. SLDataFormat_PCM pcmFormat =
  360. {
  361. SL_DATAFORMAT_PCM,
  362. numChannels,
  363. sampleRate * 1000, // (sample rate units are millihertz)
  364. SL_PCMSAMPLEFORMAT_FIXED_16,
  365. SL_PCMSAMPLEFORMAT_FIXED_16,
  366. (numChannels == 1) ? SL_SPEAKER_FRONT_CENTER : (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT),
  367. SL_BYTEORDER_LITTLEENDIAN
  368. };
  369. SLDataLocator_IODevice ioDevice = { SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, SL_DEFAULTDEVICEID_AUDIOINPUT, nullptr };
  370. SLDataSource audioSrc = { &ioDevice, nullptr };
  371. SLDataLocator_AndroidSimpleBufferQueue bufferQueue = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, bufferList.numBuffers };
  372. SLDataSink audioSink = { &bufferQueue, &pcmFormat };
  373. const SLInterfaceID interfaceIDs[] = { *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE };
  374. const SLboolean flags[] = { SL_BOOLEAN_TRUE };
  375. if (check ((*engine.engineInterface)->CreateAudioRecorder (engine.engineInterface, &recorderObject, &audioSrc,
  376. &audioSink, 1, interfaceIDs, flags)))
  377. {
  378. if (check ((*recorderObject)->Realize (recorderObject, SL_BOOLEAN_FALSE)))
  379. {
  380. check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_RECORD, &recorderRecord));
  381. check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue));
  382. check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDCONFIGURATION, &configObject));
  383. check ((*recorderBufferQueue)->RegisterCallback (recorderBufferQueue, staticCallback, this));
  384. check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_STOPPED));
  385. for (int i = bufferList.numBuffers; --i >= 0;)
  386. {
  387. int16* const buffer = bufferList.getNextBuffer();
  388. jassert (buffer != nullptr);
  389. enqueueBuffer (buffer);
  390. }
  391. }
  392. }
  393. }
  394. ~Recorder()
  395. {
  396. if (recorderRecord != nullptr)
  397. check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_STOPPED));
  398. if (recorderBufferQueue != nullptr)
  399. check ((*recorderBufferQueue)->Clear (recorderBufferQueue));
  400. if (recorderObject != nullptr)
  401. (*recorderObject)->Destroy (recorderObject);
  402. }
  403. bool openedOk() const noexcept { return recorderBufferQueue != nullptr; }
  404. void start()
  405. {
  406. jassert (openedOk());
  407. check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_RECORDING));
  408. }
  409. void readNextBlock (AudioSampleBuffer& buffer, Thread& thread)
  410. {
  411. jassert (buffer.getNumChannels() == bufferList.numChannels);
  412. jassert (buffer.getNumSamples() < bufferList.numSamples * bufferList.numBuffers);
  413. jassert ((buffer.getNumSamples() % bufferList.numSamples) == 0);
  414. int offset = 0;
  415. int numSamples = buffer.getNumSamples();
  416. while (numSamples > 0)
  417. {
  418. int16* const srcBuffer = bufferList.waitForFreeBuffer (thread);
  419. if (srcBuffer == nullptr)
  420. break;
  421. for (int i = 0; i < bufferList.numChannels; ++i)
  422. {
  423. typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> DstSampleType;
  424. typedef AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const> SrcSampleType;
  425. DstSampleType dstData (buffer.getWritePointer (i, offset));
  426. SrcSampleType srcData (srcBuffer + i, bufferList.numChannels);
  427. dstData.convertSamples (srcData, bufferList.numSamples);
  428. }
  429. enqueueBuffer (srcBuffer);
  430. numSamples -= bufferList.numSamples;
  431. offset += bufferList.numSamples;
  432. }
  433. }
  434. bool setAudioPreprocessingEnabled (bool enable)
  435. {
  436. SLuint32 mode = enable ? SL_ANDROID_RECORDING_PRESET_GENERIC
  437. : SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
  438. return configObject != nullptr
  439. && check ((*configObject)->SetConfiguration (configObject, SL_ANDROID_KEY_RECORDING_PRESET, &mode, sizeof (mode)));
  440. }
  441. private:
  442. SLObjectItf recorderObject;
  443. SLRecordItf recorderRecord;
  444. SLAndroidSimpleBufferQueueItf recorderBufferQueue;
  445. SLAndroidConfigurationItf configObject;
  446. BufferList bufferList;
  447. void enqueueBuffer (int16* buffer)
  448. {
  449. check ((*recorderBufferQueue)->Enqueue (recorderBufferQueue, buffer, bufferList.getBufferSizeBytes()));
  450. bufferList.bufferSent();
  451. }
  452. static void staticCallback (SLAndroidSimpleBufferQueueItf queue, void* context)
  453. {
  454. jassert (queue == static_cast <Recorder*> (context)->recorderBufferQueue); (void) queue;
  455. static_cast <Recorder*> (context)->bufferList.bufferReturned();
  456. }
  457. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Recorder)
  458. };
  459. //==============================================================================
  460. Engine engine;
  461. ScopedPointer<Player> player;
  462. ScopedPointer<Recorder> recorder;
  463. //==============================================================================
  464. static bool check (const SLresult result)
  465. {
  466. jassert (result == SL_RESULT_SUCCESS);
  467. return result == SL_RESULT_SUCCESS;
  468. }
  469. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenSLAudioIODevice)
  470. };
  471. //==============================================================================
  472. class OpenSLAudioDeviceType : public AudioIODeviceType
  473. {
  474. public:
  475. OpenSLAudioDeviceType() : AudioIODeviceType (openSLTypeName) {}
  476. //==============================================================================
  477. void scanForDevices() {}
  478. StringArray getDeviceNames (bool wantInputNames) const { return StringArray (openSLTypeName); }
  479. int getDefaultDeviceIndex (bool forInput) const { return 0; }
  480. int getIndexOfDevice (AudioIODevice* device, bool asInput) const { return device != nullptr ? 0 : -1; }
  481. bool hasSeparateInputsAndOutputs() const { return false; }
  482. AudioIODevice* createDevice (const String& outputDeviceName,
  483. const String& inputDeviceName)
  484. {
  485. ScopedPointer<OpenSLAudioIODevice> dev;
  486. if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty())
  487. {
  488. dev = new OpenSLAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
  489. : inputDeviceName);
  490. if (! dev->openedOk())
  491. dev = nullptr;
  492. }
  493. return dev.release();
  494. }
  495. private:
  496. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenSLAudioDeviceType)
  497. };
  498. //==============================================================================
  499. AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_OpenSLES()
  500. {
  501. return isOpenSLAvailable() ? new OpenSLAudioDeviceType() : nullptr;
  502. }