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.

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