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.

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