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.

943 lines
32KB

  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. #include "../../core/juce_StandardHeader.h"
  19. BEGIN_JUCE_NAMESPACE
  20. #include "juce_AudioDeviceManager.h"
  21. //==============================================================================
  22. AudioDeviceManager::AudioDeviceSetup::AudioDeviceSetup()
  23. : sampleRate (0),
  24. bufferSize (0),
  25. useDefaultInputChannels (true),
  26. useDefaultOutputChannels (true)
  27. {
  28. }
  29. bool AudioDeviceManager::AudioDeviceSetup::operator== (const AudioDeviceManager::AudioDeviceSetup& other) const
  30. {
  31. return outputDeviceName == other.outputDeviceName
  32. && inputDeviceName == other.inputDeviceName
  33. && sampleRate == other.sampleRate
  34. && bufferSize == other.bufferSize
  35. && inputChannels == other.inputChannels
  36. && useDefaultInputChannels == other.useDefaultInputChannels
  37. && outputChannels == other.outputChannels
  38. && useDefaultOutputChannels == other.useDefaultOutputChannels;
  39. }
  40. //==============================================================================
  41. AudioDeviceManager::AudioDeviceManager()
  42. : numInputChansNeeded (0),
  43. numOutputChansNeeded (2),
  44. listNeedsScanning (true),
  45. useInputNames (false),
  46. inputLevelMeasurementEnabledCount (0),
  47. inputLevel (0),
  48. tempBuffer (2, 2),
  49. cpuUsageMs (0),
  50. timeToCpuScale (0)
  51. {
  52. callbackHandler.owner = this;
  53. }
  54. AudioDeviceManager::~AudioDeviceManager()
  55. {
  56. currentAudioDevice = nullptr;
  57. defaultMidiOutput = nullptr;
  58. }
  59. //==============================================================================
  60. void AudioDeviceManager::createDeviceTypesIfNeeded()
  61. {
  62. if (availableDeviceTypes.size() == 0)
  63. {
  64. createAudioDeviceTypes (availableDeviceTypes);
  65. while (lastDeviceTypeConfigs.size() < availableDeviceTypes.size())
  66. lastDeviceTypeConfigs.add (new AudioDeviceSetup());
  67. if (availableDeviceTypes.size() > 0)
  68. currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
  69. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  70. availableDeviceTypes.getUnchecked(i)->addListener (&callbackHandler);
  71. }
  72. }
  73. const OwnedArray <AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
  74. {
  75. scanDevicesIfNeeded();
  76. return availableDeviceTypes;
  77. }
  78. void AudioDeviceManager::audioDeviceListChanged()
  79. {
  80. sendChangeMessage();
  81. }
  82. //==============================================================================
  83. static void addIfNotNull (OwnedArray <AudioIODeviceType>& list, AudioIODeviceType* const device)
  84. {
  85. if (device != nullptr)
  86. list.add (device);
  87. }
  88. void AudioDeviceManager::createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& list)
  89. {
  90. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI());
  91. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound());
  92. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ASIO());
  93. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_CoreAudio());
  94. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_iOSAudio());
  95. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ALSA());
  96. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_JACK());
  97. addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Android());
  98. }
  99. //==============================================================================
  100. String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
  101. const int numOutputChannelsNeeded,
  102. const XmlElement* const e,
  103. const bool selectDefaultDeviceOnFailure,
  104. const String& preferredDefaultDeviceName,
  105. const AudioDeviceSetup* preferredSetupOptions)
  106. {
  107. scanDevicesIfNeeded();
  108. numInputChansNeeded = numInputChannelsNeeded;
  109. numOutputChansNeeded = numOutputChannelsNeeded;
  110. if (e != nullptr && e->hasTagName ("DEVICESETUP"))
  111. {
  112. lastExplicitSettings = new XmlElement (*e);
  113. String error;
  114. AudioDeviceSetup setup;
  115. if (preferredSetupOptions != nullptr)
  116. setup = *preferredSetupOptions;
  117. if (e->getStringAttribute ("audioDeviceName").isNotEmpty())
  118. {
  119. setup.inputDeviceName = setup.outputDeviceName
  120. = e->getStringAttribute ("audioDeviceName");
  121. }
  122. else
  123. {
  124. setup.inputDeviceName = e->getStringAttribute ("audioInputDeviceName");
  125. setup.outputDeviceName = e->getStringAttribute ("audioOutputDeviceName");
  126. }
  127. currentDeviceType = e->getStringAttribute ("deviceType");
  128. if (currentDeviceType.isEmpty())
  129. {
  130. AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName);
  131. if (type != nullptr)
  132. currentDeviceType = type->getTypeName();
  133. else if (availableDeviceTypes.size() > 0)
  134. currentDeviceType = availableDeviceTypes[0]->getTypeName();
  135. }
  136. setup.bufferSize = e->getIntAttribute ("audioDeviceBufferSize");
  137. setup.sampleRate = e->getDoubleAttribute ("audioDeviceRate");
  138. setup.inputChannels.parseString (e->getStringAttribute ("audioDeviceInChans", "11"), 2);
  139. setup.outputChannels.parseString (e->getStringAttribute ("audioDeviceOutChans", "11"), 2);
  140. setup.useDefaultInputChannels = ! e->hasAttribute ("audioDeviceInChans");
  141. setup.useDefaultOutputChannels = ! e->hasAttribute ("audioDeviceOutChans");
  142. error = setAudioDeviceSetup (setup, true);
  143. midiInsFromXml.clear();
  144. forEachXmlChildElementWithTagName (*e, c, "MIDIINPUT")
  145. midiInsFromXml.add (c->getStringAttribute ("name"));
  146. const StringArray allMidiIns (MidiInput::getDevices());
  147. for (int i = allMidiIns.size(); --i >= 0;)
  148. setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
  149. if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
  150. error = initialise (numInputChannelsNeeded, numOutputChannelsNeeded, 0,
  151. false, preferredDefaultDeviceName);
  152. setDefaultMidiOutput (e->getStringAttribute ("defaultMidiOutput"));
  153. return error;
  154. }
  155. else
  156. {
  157. AudioDeviceSetup setup;
  158. if (preferredSetupOptions != nullptr)
  159. {
  160. setup = *preferredSetupOptions;
  161. }
  162. else if (preferredDefaultDeviceName.isNotEmpty())
  163. {
  164. for (int j = availableDeviceTypes.size(); --j >= 0;)
  165. {
  166. AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j);
  167. StringArray outs (type->getDeviceNames (false));
  168. int i;
  169. for (i = 0; i < outs.size(); ++i)
  170. {
  171. if (outs[i].matchesWildcard (preferredDefaultDeviceName, true))
  172. {
  173. setup.outputDeviceName = outs[i];
  174. break;
  175. }
  176. }
  177. StringArray ins (type->getDeviceNames (true));
  178. for (i = 0; i < ins.size(); ++i)
  179. {
  180. if (ins[i].matchesWildcard (preferredDefaultDeviceName, true))
  181. {
  182. setup.inputDeviceName = ins[i];
  183. break;
  184. }
  185. }
  186. }
  187. }
  188. insertDefaultDeviceNames (setup);
  189. return setAudioDeviceSetup (setup, false);
  190. }
  191. }
  192. void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
  193. {
  194. AudioIODeviceType* type = getCurrentDeviceTypeObject();
  195. if (type != nullptr)
  196. {
  197. if (setup.outputDeviceName.isEmpty())
  198. setup.outputDeviceName = type->getDeviceNames (false) [type->getDefaultDeviceIndex (false)];
  199. if (setup.inputDeviceName.isEmpty())
  200. setup.inputDeviceName = type->getDeviceNames (true) [type->getDefaultDeviceIndex (true)];
  201. }
  202. }
  203. XmlElement* AudioDeviceManager::createStateXml() const
  204. {
  205. return lastExplicitSettings != nullptr ? new XmlElement (*lastExplicitSettings) : nullptr;
  206. }
  207. //==============================================================================
  208. void AudioDeviceManager::scanDevicesIfNeeded()
  209. {
  210. if (listNeedsScanning)
  211. {
  212. listNeedsScanning = false;
  213. createDeviceTypesIfNeeded();
  214. for (int i = availableDeviceTypes.size(); --i >= 0;)
  215. availableDeviceTypes.getUnchecked(i)->scanForDevices();
  216. }
  217. }
  218. AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const String& outputName)
  219. {
  220. scanDevicesIfNeeded();
  221. for (int i = availableDeviceTypes.size(); --i >= 0;)
  222. {
  223. AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(i);
  224. if ((inputName.isNotEmpty() && type->getDeviceNames (true).contains (inputName, true))
  225. || (outputName.isNotEmpty() && type->getDeviceNames (false).contains (outputName, true)))
  226. {
  227. return type;
  228. }
  229. }
  230. return nullptr;
  231. }
  232. void AudioDeviceManager::getAudioDeviceSetup (AudioDeviceSetup& setup)
  233. {
  234. setup = currentSetup;
  235. }
  236. void AudioDeviceManager::deleteCurrentDevice()
  237. {
  238. currentAudioDevice = nullptr;
  239. currentSetup.inputDeviceName = String::empty;
  240. currentSetup.outputDeviceName = String::empty;
  241. }
  242. void AudioDeviceManager::setCurrentAudioDeviceType (const String& type,
  243. const bool treatAsChosenDevice)
  244. {
  245. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  246. {
  247. if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type
  248. && currentDeviceType != type)
  249. {
  250. currentDeviceType = type;
  251. AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i));
  252. insertDefaultDeviceNames (s);
  253. setAudioDeviceSetup (s, treatAsChosenDevice);
  254. sendChangeMessage();
  255. break;
  256. }
  257. }
  258. }
  259. AudioIODeviceType* AudioDeviceManager::getCurrentDeviceTypeObject() const
  260. {
  261. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  262. if (availableDeviceTypes[i]->getTypeName() == currentDeviceType)
  263. return availableDeviceTypes[i];
  264. return availableDeviceTypes[0];
  265. }
  266. String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup,
  267. const bool treatAsChosenDevice)
  268. {
  269. jassert (&newSetup != &currentSetup); // this will have no effect
  270. if (newSetup == currentSetup && currentAudioDevice != nullptr)
  271. return String::empty;
  272. if (! (newSetup == currentSetup))
  273. sendChangeMessage();
  274. stopDevice();
  275. const String newInputDeviceName (numInputChansNeeded == 0 ? String::empty : newSetup.inputDeviceName);
  276. const String newOutputDeviceName (numOutputChansNeeded == 0 ? String::empty : newSetup.outputDeviceName);
  277. String error;
  278. AudioIODeviceType* type = getCurrentDeviceTypeObject();
  279. if (type == nullptr || (newInputDeviceName.isEmpty() && newOutputDeviceName.isEmpty()))
  280. {
  281. deleteCurrentDevice();
  282. if (treatAsChosenDevice)
  283. updateXml();
  284. return String::empty;
  285. }
  286. if (currentSetup.inputDeviceName != newInputDeviceName
  287. || currentSetup.outputDeviceName != newOutputDeviceName
  288. || currentAudioDevice == nullptr)
  289. {
  290. deleteCurrentDevice();
  291. scanDevicesIfNeeded();
  292. if (newOutputDeviceName.isNotEmpty()
  293. && ! type->getDeviceNames (false).contains (newOutputDeviceName))
  294. {
  295. return "No such device: " + newOutputDeviceName;
  296. }
  297. if (newInputDeviceName.isNotEmpty()
  298. && ! type->getDeviceNames (true).contains (newInputDeviceName))
  299. {
  300. return "No such device: " + newInputDeviceName;
  301. }
  302. currentAudioDevice = type->createDevice (newOutputDeviceName, newInputDeviceName);
  303. if (currentAudioDevice == nullptr)
  304. error = "Can't open the audio device!\n\nThis may be because another application is currently using the same device - if so, you should close any other applications and try again!";
  305. else
  306. error = currentAudioDevice->getLastError();
  307. if (error.isNotEmpty())
  308. {
  309. deleteCurrentDevice();
  310. return error;
  311. }
  312. if (newSetup.useDefaultInputChannels)
  313. {
  314. inputChannels.clear();
  315. inputChannels.setRange (0, numInputChansNeeded, true);
  316. }
  317. if (newSetup.useDefaultOutputChannels)
  318. {
  319. outputChannels.clear();
  320. outputChannels.setRange (0, numOutputChansNeeded, true);
  321. }
  322. if (newInputDeviceName.isEmpty())
  323. inputChannels.clear();
  324. if (newOutputDeviceName.isEmpty())
  325. outputChannels.clear();
  326. }
  327. if (! newSetup.useDefaultInputChannels)
  328. inputChannels = newSetup.inputChannels;
  329. if (! newSetup.useDefaultOutputChannels)
  330. outputChannels = newSetup.outputChannels;
  331. currentSetup = newSetup;
  332. currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate);
  333. currentSetup.bufferSize = chooseBestBufferSize (newSetup.bufferSize);
  334. error = currentAudioDevice->open (inputChannels,
  335. outputChannels,
  336. currentSetup.sampleRate,
  337. currentSetup.bufferSize);
  338. if (error.isEmpty())
  339. {
  340. currentDeviceType = currentAudioDevice->getTypeName();
  341. currentAudioDevice->start (&callbackHandler);
  342. currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
  343. currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
  344. currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
  345. currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
  346. for (int i = 0; i < availableDeviceTypes.size(); ++i)
  347. if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType)
  348. *(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup;
  349. if (treatAsChosenDevice)
  350. updateXml();
  351. }
  352. else
  353. {
  354. deleteCurrentDevice();
  355. }
  356. return error;
  357. }
  358. double AudioDeviceManager::chooseBestSampleRate (double rate) const
  359. {
  360. jassert (currentAudioDevice != nullptr);
  361. if (rate > 0)
  362. for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
  363. if (currentAudioDevice->getSampleRate (i) == rate)
  364. return rate;
  365. double lowestAbove44 = 0.0;
  366. for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
  367. {
  368. const double sr = currentAudioDevice->getSampleRate (i);
  369. if (sr >= 44100.0 && (lowestAbove44 < 1.0 || sr < lowestAbove44))
  370. lowestAbove44 = sr;
  371. }
  372. if (lowestAbove44 > 0.0)
  373. return lowestAbove44;
  374. return currentAudioDevice->getSampleRate (0);
  375. }
  376. int AudioDeviceManager::chooseBestBufferSize (int bufferSize) const
  377. {
  378. jassert (currentAudioDevice != nullptr);
  379. if (bufferSize > 0)
  380. for (int i = currentAudioDevice->getNumBufferSizesAvailable(); --i >= 0;)
  381. if (currentAudioDevice->getBufferSizeSamples(i) == bufferSize)
  382. return bufferSize;
  383. return currentAudioDevice->getDefaultBufferSize();
  384. }
  385. void AudioDeviceManager::stopDevice()
  386. {
  387. if (currentAudioDevice != nullptr)
  388. currentAudioDevice->stop();
  389. testSound = nullptr;
  390. }
  391. void AudioDeviceManager::closeAudioDevice()
  392. {
  393. stopDevice();
  394. currentAudioDevice = nullptr;
  395. }
  396. void AudioDeviceManager::restartLastAudioDevice()
  397. {
  398. if (currentAudioDevice == nullptr)
  399. {
  400. if (currentSetup.inputDeviceName.isEmpty()
  401. && currentSetup.outputDeviceName.isEmpty())
  402. {
  403. // This method will only reload the last device that was running
  404. // before closeAudioDevice() was called - you need to actually open
  405. // one first, with setAudioDevice().
  406. jassertfalse;
  407. return;
  408. }
  409. AudioDeviceSetup s (currentSetup);
  410. setAudioDeviceSetup (s, false);
  411. }
  412. }
  413. void AudioDeviceManager::updateXml()
  414. {
  415. lastExplicitSettings = new XmlElement ("DEVICESETUP");
  416. lastExplicitSettings->setAttribute ("deviceType", currentDeviceType);
  417. lastExplicitSettings->setAttribute ("audioOutputDeviceName", currentSetup.outputDeviceName);
  418. lastExplicitSettings->setAttribute ("audioInputDeviceName", currentSetup.inputDeviceName);
  419. if (currentAudioDevice != nullptr)
  420. {
  421. lastExplicitSettings->setAttribute ("audioDeviceRate", currentAudioDevice->getCurrentSampleRate());
  422. if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
  423. lastExplicitSettings->setAttribute ("audioDeviceBufferSize", currentAudioDevice->getCurrentBufferSizeSamples());
  424. if (! currentSetup.useDefaultInputChannels)
  425. lastExplicitSettings->setAttribute ("audioDeviceInChans", currentSetup.inputChannels.toString (2));
  426. if (! currentSetup.useDefaultOutputChannels)
  427. lastExplicitSettings->setAttribute ("audioDeviceOutChans", currentSetup.outputChannels.toString (2));
  428. }
  429. for (int i = 0; i < enabledMidiInputs.size(); ++i)
  430. {
  431. XmlElement* const m = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
  432. m->setAttribute ("name", enabledMidiInputs[i]->getName());
  433. }
  434. if (midiInsFromXml.size() > 0)
  435. {
  436. // Add any midi devices that have been enabled before, but which aren't currently
  437. // open because the device has been disconnected.
  438. const StringArray availableMidiDevices (MidiInput::getDevices());
  439. for (int i = 0; i < midiInsFromXml.size(); ++i)
  440. {
  441. if (! availableMidiDevices.contains (midiInsFromXml[i], true))
  442. {
  443. XmlElement* const m = lastExplicitSettings->createNewChildElement ("MIDIINPUT");
  444. m->setAttribute ("name", midiInsFromXml[i]);
  445. }
  446. }
  447. }
  448. if (defaultMidiOutputName.isNotEmpty())
  449. lastExplicitSettings->setAttribute ("defaultMidiOutput", defaultMidiOutputName);
  450. }
  451. //==============================================================================
  452. void AudioDeviceManager::addAudioCallback (AudioIODeviceCallback* newCallback)
  453. {
  454. {
  455. const ScopedLock sl (audioCallbackLock);
  456. if (callbacks.contains (newCallback))
  457. return;
  458. }
  459. if (currentAudioDevice != nullptr && newCallback != nullptr)
  460. newCallback->audioDeviceAboutToStart (currentAudioDevice);
  461. const ScopedLock sl (audioCallbackLock);
  462. callbacks.add (newCallback);
  463. }
  464. void AudioDeviceManager::removeAudioCallback (AudioIODeviceCallback* callbackToRemove)
  465. {
  466. if (callbackToRemove != nullptr)
  467. {
  468. bool needsDeinitialising = currentAudioDevice != nullptr;
  469. {
  470. const ScopedLock sl (audioCallbackLock);
  471. needsDeinitialising = needsDeinitialising && callbacks.contains (callbackToRemove);
  472. callbacks.removeValue (callbackToRemove);
  473. }
  474. if (needsDeinitialising)
  475. callbackToRemove->audioDeviceStopped();
  476. }
  477. }
  478. void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,
  479. int numInputChannels,
  480. float** outputChannelData,
  481. int numOutputChannels,
  482. int numSamples)
  483. {
  484. const ScopedLock sl (audioCallbackLock);
  485. if (inputLevelMeasurementEnabledCount > 0 && numInputChannels > 0)
  486. {
  487. for (int j = 0; j < numSamples; ++j)
  488. {
  489. float s = 0;
  490. for (int i = 0; i < numInputChannels; ++i)
  491. s += std::abs (inputChannelData[i][j]);
  492. s /= numInputChannels;
  493. const double decayFactor = 0.99992;
  494. if (s > inputLevel)
  495. inputLevel = s;
  496. else if (inputLevel > 0.001f)
  497. inputLevel *= decayFactor;
  498. else
  499. inputLevel = 0;
  500. }
  501. }
  502. else
  503. {
  504. inputLevel = 0;
  505. }
  506. if (callbacks.size() > 0)
  507. {
  508. const double callbackStartTime = Time::getMillisecondCounterHiRes();
  509. tempBuffer.setSize (jmax (1, numOutputChannels), jmax (1, numSamples), false, false, true);
  510. callbacks.getUnchecked(0)->audioDeviceIOCallback (inputChannelData, numInputChannels,
  511. outputChannelData, numOutputChannels, numSamples);
  512. float** const tempChans = tempBuffer.getArrayOfChannels();
  513. for (int i = callbacks.size(); --i > 0;)
  514. {
  515. callbacks.getUnchecked(i)->audioDeviceIOCallback (inputChannelData, numInputChannels,
  516. tempChans, numOutputChannels, numSamples);
  517. for (int chan = 0; chan < numOutputChannels; ++chan)
  518. {
  519. const float* const src = tempChans [chan];
  520. float* const dst = outputChannelData [chan];
  521. if (src != nullptr && dst != nullptr)
  522. for (int j = 0; j < numSamples; ++j)
  523. dst[j] += src[j];
  524. }
  525. }
  526. const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime;
  527. const double filterAmount = 0.2;
  528. cpuUsageMs += filterAmount * (msTaken - cpuUsageMs);
  529. }
  530. else
  531. {
  532. for (int i = 0; i < numOutputChannels; ++i)
  533. zeromem (outputChannelData[i], sizeof (float) * numSamples);
  534. }
  535. if (testSound != nullptr)
  536. {
  537. const int numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
  538. const float* const src = testSound->getSampleData (0, testSoundPosition);
  539. for (int i = 0; i < numOutputChannels; ++i)
  540. for (int j = 0; j < numSamps; ++j)
  541. outputChannelData [i][j] += src[j];
  542. testSoundPosition += numSamps;
  543. if (testSoundPosition >= testSound->getNumSamples())
  544. testSound = nullptr;
  545. }
  546. }
  547. void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)
  548. {
  549. cpuUsageMs = 0;
  550. const double sampleRate = device->getCurrentSampleRate();
  551. const int blockSize = device->getCurrentBufferSizeSamples();
  552. if (sampleRate > 0.0 && blockSize > 0)
  553. {
  554. const double msPerBlock = 1000.0 * blockSize / sampleRate;
  555. timeToCpuScale = (msPerBlock > 0.0) ? (1.0 / msPerBlock) : 0.0;
  556. }
  557. {
  558. const ScopedLock sl (audioCallbackLock);
  559. for (int i = callbacks.size(); --i >= 0;)
  560. callbacks.getUnchecked(i)->audioDeviceAboutToStart (device);
  561. }
  562. sendChangeMessage();
  563. }
  564. void AudioDeviceManager::audioDeviceStoppedInt()
  565. {
  566. cpuUsageMs = 0;
  567. timeToCpuScale = 0;
  568. sendChangeMessage();
  569. const ScopedLock sl (audioCallbackLock);
  570. for (int i = callbacks.size(); --i >= 0;)
  571. callbacks.getUnchecked(i)->audioDeviceStopped();
  572. }
  573. double AudioDeviceManager::getCpuUsage() const
  574. {
  575. return jlimit (0.0, 1.0, timeToCpuScale * cpuUsageMs);
  576. }
  577. //==============================================================================
  578. void AudioDeviceManager::setMidiInputEnabled (const String& name,
  579. const bool enabled)
  580. {
  581. if (enabled != isMidiInputEnabled (name))
  582. {
  583. if (enabled)
  584. {
  585. const int index = MidiInput::getDevices().indexOf (name);
  586. if (index >= 0)
  587. {
  588. MidiInput* const midiIn = MidiInput::openDevice (index, &callbackHandler);
  589. if (midiIn != nullptr)
  590. {
  591. enabledMidiInputs.add (midiIn);
  592. midiIn->start();
  593. }
  594. }
  595. }
  596. else
  597. {
  598. for (int i = enabledMidiInputs.size(); --i >= 0;)
  599. if (enabledMidiInputs[i]->getName() == name)
  600. enabledMidiInputs.remove (i);
  601. }
  602. updateXml();
  603. sendChangeMessage();
  604. }
  605. }
  606. bool AudioDeviceManager::isMidiInputEnabled (const String& name) const
  607. {
  608. for (int i = enabledMidiInputs.size(); --i >= 0;)
  609. if (enabledMidiInputs[i]->getName() == name)
  610. return true;
  611. return false;
  612. }
  613. void AudioDeviceManager::addMidiInputCallback (const String& name,
  614. MidiInputCallback* callbackToAdd)
  615. {
  616. removeMidiInputCallback (name, callbackToAdd);
  617. if (name.isEmpty() || isMidiInputEnabled (name))
  618. {
  619. const ScopedLock sl (midiCallbackLock);
  620. midiCallbacks.add (callbackToAdd);
  621. midiCallbackDevices.add (name);
  622. }
  623. }
  624. void AudioDeviceManager::removeMidiInputCallback (const String& name, MidiInputCallback* callbackToRemove)
  625. {
  626. for (int i = midiCallbacks.size(); --i >= 0;)
  627. {
  628. if (midiCallbackDevices[i] == name && midiCallbacks.getUnchecked(i) == callbackToRemove)
  629. {
  630. const ScopedLock sl (midiCallbackLock);
  631. midiCallbacks.remove (i);
  632. midiCallbackDevices.remove (i);
  633. }
  634. }
  635. }
  636. void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source,
  637. const MidiMessage& message)
  638. {
  639. if (! message.isActiveSense())
  640. {
  641. const bool isDefaultSource = (source == nullptr || source == enabledMidiInputs.getFirst());
  642. const ScopedLock sl (midiCallbackLock);
  643. for (int i = midiCallbackDevices.size(); --i >= 0;)
  644. {
  645. const String name (midiCallbackDevices[i]);
  646. if ((isDefaultSource && name.isEmpty()) || (name.isNotEmpty() && name == source->getName()))
  647. midiCallbacks.getUnchecked(i)->handleIncomingMidiMessage (source, message);
  648. }
  649. }
  650. }
  651. //==============================================================================
  652. void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
  653. {
  654. if (defaultMidiOutputName != deviceName)
  655. {
  656. Array <AudioIODeviceCallback*> oldCallbacks;
  657. {
  658. const ScopedLock sl (audioCallbackLock);
  659. oldCallbacks = callbacks;
  660. callbacks.clear();
  661. }
  662. if (currentAudioDevice != nullptr)
  663. for (int i = oldCallbacks.size(); --i >= 0;)
  664. oldCallbacks.getUnchecked(i)->audioDeviceStopped();
  665. defaultMidiOutput = nullptr;
  666. defaultMidiOutputName = deviceName;
  667. if (deviceName.isNotEmpty())
  668. defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName));
  669. if (currentAudioDevice != nullptr)
  670. for (int i = oldCallbacks.size(); --i >= 0;)
  671. oldCallbacks.getUnchecked(i)->audioDeviceAboutToStart (currentAudioDevice);
  672. {
  673. const ScopedLock sl (audioCallbackLock);
  674. callbacks = oldCallbacks;
  675. }
  676. updateXml();
  677. sendChangeMessage();
  678. }
  679. }
  680. //==============================================================================
  681. void AudioDeviceManager::CallbackHandler::audioDeviceIOCallback (const float** inputChannelData,
  682. int numInputChannels,
  683. float** outputChannelData,
  684. int numOutputChannels,
  685. int numSamples)
  686. {
  687. owner->audioDeviceIOCallbackInt (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples);
  688. }
  689. void AudioDeviceManager::CallbackHandler::audioDeviceAboutToStart (AudioIODevice* device)
  690. {
  691. owner->audioDeviceAboutToStartInt (device);
  692. }
  693. void AudioDeviceManager::CallbackHandler::audioDeviceStopped()
  694. {
  695. owner->audioDeviceStoppedInt();
  696. }
  697. void AudioDeviceManager::CallbackHandler::handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message)
  698. {
  699. owner->handleIncomingMidiMessageInt (source, message);
  700. }
  701. void AudioDeviceManager::CallbackHandler::audioDeviceListChanged()
  702. {
  703. owner->audioDeviceListChanged();
  704. }
  705. //==============================================================================
  706. void AudioDeviceManager::playTestSound()
  707. {
  708. { // cunningly nested to swap, unlock and delete in that order.
  709. ScopedPointer <AudioSampleBuffer> oldSound;
  710. {
  711. const ScopedLock sl (audioCallbackLock);
  712. oldSound = testSound;
  713. }
  714. }
  715. testSoundPosition = 0;
  716. if (currentAudioDevice != nullptr)
  717. {
  718. const double sampleRate = currentAudioDevice->getCurrentSampleRate();
  719. const int soundLength = (int) sampleRate;
  720. AudioSampleBuffer* const newSound = new AudioSampleBuffer (1, soundLength);
  721. float* samples = newSound->getSampleData (0);
  722. const double frequency = MidiMessage::getMidiNoteInHertz (80);
  723. const float amplitude = 0.5f;
  724. const double phasePerSample = double_Pi * 2.0 / (sampleRate / frequency);
  725. for (int i = 0; i < soundLength; ++i)
  726. samples[i] = amplitude * (float) std::sin (i * phasePerSample);
  727. newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
  728. newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
  729. const ScopedLock sl (audioCallbackLock);
  730. testSound = newSound;
  731. }
  732. }
  733. void AudioDeviceManager::enableInputLevelMeasurement (const bool enableMeasurement)
  734. {
  735. const ScopedLock sl (audioCallbackLock);
  736. if (enableMeasurement)
  737. ++inputLevelMeasurementEnabledCount;
  738. else
  739. --inputLevelMeasurementEnabledCount;
  740. inputLevel = 0;
  741. }
  742. double AudioDeviceManager::getCurrentInputLevel() const
  743. {
  744. jassert (inputLevelMeasurementEnabledCount > 0); // you need to call enableInputLevelMeasurement() before using this!
  745. return inputLevel;
  746. }
  747. END_JUCE_NAMESPACE