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.

614 lines
23KB

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