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.

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