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.

979 lines
32KB

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