1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-17 00:44:19 +00:00
JUCE/src/juce_appframework/audio/devices/juce_AudioDeviceManager.cpp
2008-10-03 15:04:27 +00:00

907 lines
29 KiB
C++

/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "../../../juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "juce_AudioDeviceManager.h"
#include "../../gui/components/juce_Desktop.h"
#include "../../../juce_core/text/juce_LocalisedStrings.h"
#include "../dsp/juce_AudioSampleBuffer.h"
//==============================================================================
AudioDeviceManager::AudioDeviceSetup::AudioDeviceSetup()
: sampleRate (0),
bufferSize (0),
useDefaultInputChannels (true),
useDefaultOutputChannels (true)
{
}
bool AudioDeviceManager::AudioDeviceSetup::operator== (const AudioDeviceManager::AudioDeviceSetup& other) const
{
return outputDeviceName == other.outputDeviceName
&& inputDeviceName == other.inputDeviceName
&& sampleRate == other.sampleRate
&& bufferSize == other.bufferSize
&& inputChannels == other.inputChannels
&& useDefaultInputChannels == other.useDefaultInputChannels
&& outputChannels == other.outputChannels
&& useDefaultOutputChannels == other.useDefaultOutputChannels;
}
//==============================================================================
AudioDeviceManager::AudioDeviceManager()
: currentAudioDevice (0),
currentCallback (0),
numInputChansNeeded (0),
numOutputChansNeeded (2),
lastExplicitSettings (0),
listNeedsScanning (true),
useInputNames (false),
inputLevelMeasurementEnabled (false),
inputLevel (0),
testSound (0),
enabledMidiInputs (4),
midiCallbacks (4),
midiCallbackDevices (4),
defaultMidiOutput (0),
cpuUsageMs (0),
timeToCpuScale (0)
{
callbackHandler.owner = this;
}
AudioDeviceManager::~AudioDeviceManager()
{
deleteAndZero (currentAudioDevice);
deleteAndZero (defaultMidiOutput);
delete lastExplicitSettings;
delete testSound;
}
//==============================================================================
void AudioDeviceManager::createDeviceTypesIfNeeded()
{
if (availableDeviceTypes.size() == 0)
{
createAudioDeviceTypes (availableDeviceTypes);
while (lastDeviceTypeConfigs.size() < availableDeviceTypes.size())
lastDeviceTypeConfigs.add (new AudioDeviceSetup());
if (availableDeviceTypes.size() > 0)
currentDeviceType = availableDeviceTypes.getUnchecked(0)->getTypeName();
}
}
const OwnedArray <AudioIODeviceType>& AudioDeviceManager::getAvailableDeviceTypes()
{
scanDevicesIfNeeded();
return availableDeviceTypes;
}
//==============================================================================
extern AudioIODeviceType* juce_createDefaultAudioIODeviceType();
#if JUCE_WIN32 && JUCE_ASIO
extern AudioIODeviceType* juce_createASIOAudioIODeviceType();
#endif
#if JUCE_WIN32 && JUCE_WDM_AUDIO
extern AudioIODeviceType* juce_createWDMAudioIODeviceType();
#endif
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray <AudioIODeviceType>& list)
{
AudioIODeviceType* const defaultDeviceType = juce_createDefaultAudioIODeviceType();
if (defaultDeviceType != 0)
list.add (defaultDeviceType);
#if JUCE_WIN32 && JUCE_ASIO
list.add (juce_createASIOAudioIODeviceType());
#endif
#if JUCE_WIN32 && JUCE_WDM_AUDIO
list.add (juce_createWDMAudioIODeviceType());
#endif
}
//==============================================================================
const String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
const int numOutputChannelsNeeded,
const XmlElement* const e,
const bool selectDefaultDeviceOnFailure,
const String& preferredDefaultDeviceName)
{
scanDevicesIfNeeded();
numInputChansNeeded = numInputChannelsNeeded;
numOutputChansNeeded = numOutputChannelsNeeded;
if (e != 0 && e->hasTagName (T("DEVICESETUP")))
{
delete lastExplicitSettings;
lastExplicitSettings = new XmlElement (*e);
String error;
AudioDeviceSetup setup;
if (e->getStringAttribute (T("audioDeviceName")).isNotEmpty())
{
setup.inputDeviceName = setup.outputDeviceName
= e->getStringAttribute (T("audioDeviceName"));
}
else
{
setup.inputDeviceName = e->getStringAttribute (T("audioInputDeviceName"));
setup.outputDeviceName = e->getStringAttribute (T("audioOutputDeviceName"));
}
currentDeviceType = e->getStringAttribute (T("deviceType"));
if (currentDeviceType.isEmpty())
{
AudioIODeviceType* const type = findType (setup.inputDeviceName, setup.outputDeviceName);
if (type != 0)
currentDeviceType = type->getTypeName();
else if (availableDeviceTypes.size() > 0)
currentDeviceType = availableDeviceTypes[0]->getTypeName();
}
setup.bufferSize = e->getIntAttribute (T("audioDeviceBufferSize"));
setup.sampleRate = e->getDoubleAttribute (T("audioDeviceRate"));
setup.inputChannels.parseString (e->getStringAttribute (T("audioDeviceInChans"), T("11")), 2);
setup.outputChannels.parseString (e->getStringAttribute (T("audioDeviceOutChans"), T("11")), 2);
setup.useDefaultInputChannels = ! e->hasAttribute (T("audioDeviceInChans"));
setup.useDefaultOutputChannels = ! e->hasAttribute (T("audioDeviceOutChans"));
error = setAudioDeviceSetup (setup, true);
midiInsFromXml.clear();
forEachXmlChildElementWithTagName (*e, c, T("MIDIINPUT"))
midiInsFromXml.add (c->getStringAttribute (T("name")));
const StringArray allMidiIns (MidiInput::getDevices());
for (int i = allMidiIns.size(); --i >= 0;)
setMidiInputEnabled (allMidiIns[i], midiInsFromXml.contains (allMidiIns[i]));
if (error.isNotEmpty() && selectDefaultDeviceOnFailure)
error = initialise (numInputChannelsNeeded, numOutputChannelsNeeded, 0,
false, preferredDefaultDeviceName);
setDefaultMidiOutput (e->getStringAttribute (T("defaultMidiOutput")));
return error;
}
else
{
AudioDeviceSetup setup;
if (preferredDefaultDeviceName.isNotEmpty())
{
for (int j = availableDeviceTypes.size(); --j >= 0;)
{
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(j);
StringArray outs (type->getDeviceNames (false));
int i;
for (i = 0; i < outs.size(); ++i)
{
if (outs[i].matchesWildcard (preferredDefaultDeviceName, true))
{
setup.outputDeviceName = outs[i];
break;
}
}
StringArray ins (type->getDeviceNames (true));
for (i = 0; i < ins.size(); ++i)
{
if (ins[i].matchesWildcard (preferredDefaultDeviceName, true))
{
setup.inputDeviceName = ins[i];
break;
}
}
}
}
insertDefaultDeviceNames (setup);
return setAudioDeviceSetup (setup, false);
}
}
void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const
{
AudioIODeviceType* type = getCurrentDeviceTypeObject();
if (type != 0)
{
if (setup.outputDeviceName.isEmpty())
setup.outputDeviceName = type->getDeviceNames (false) [type->getDefaultDeviceIndex (false)];
if (setup.inputDeviceName.isEmpty())
setup.inputDeviceName = type->getDeviceNames (true) [type->getDefaultDeviceIndex (true)];
}
}
XmlElement* AudioDeviceManager::createStateXml() const
{
return lastExplicitSettings != 0 ? new XmlElement (*lastExplicitSettings) : 0;
}
//==============================================================================
void AudioDeviceManager::scanDevicesIfNeeded()
{
if (listNeedsScanning)
{
listNeedsScanning = false;
createDeviceTypesIfNeeded();
for (int i = availableDeviceTypes.size(); --i >= 0;)
availableDeviceTypes.getUnchecked(i)->scanForDevices();
}
}
AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const String& outputName)
{
scanDevicesIfNeeded();
for (int i = availableDeviceTypes.size(); --i >= 0;)
{
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(i);
if ((inputName.isNotEmpty() && type->getDeviceNames (true).contains (inputName, true))
|| (outputName.isNotEmpty() && type->getDeviceNames (false).contains (outputName, true)))
{
return type;
}
}
return 0;
}
void AudioDeviceManager::getAudioDeviceSetup (AudioDeviceSetup& setup)
{
setup = currentSetup;
}
void AudioDeviceManager::deleteCurrentDevice()
{
deleteAndZero (currentAudioDevice);
currentSetup.inputDeviceName = String::empty;
currentSetup.outputDeviceName = String::empty;
}
void AudioDeviceManager::setCurrentAudioDeviceType (const String& type,
const bool treatAsChosenDevice)
{
for (int i = 0; i < availableDeviceTypes.size(); ++i)
{
if (availableDeviceTypes.getUnchecked(i)->getTypeName() == type
&& currentDeviceType != type)
{
currentDeviceType = type;
AudioDeviceSetup s (*lastDeviceTypeConfigs.getUnchecked(i));
insertDefaultDeviceNames (s);
setAudioDeviceSetup (s, treatAsChosenDevice);
sendChangeMessage (this);
break;
}
}
}
AudioIODeviceType* AudioDeviceManager::getCurrentDeviceTypeObject() const
{
for (int i = 0; i < availableDeviceTypes.size(); ++i)
if (availableDeviceTypes[i]->getTypeName() == currentDeviceType)
return availableDeviceTypes[i];
return availableDeviceTypes[0];
}
const String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup,
const bool treatAsChosenDevice)
{
jassert (&newSetup != &currentSetup); // this will have no effect
if (newSetup == currentSetup && currentAudioDevice != 0)
return String::empty;
if (! (newSetup == currentSetup))
sendChangeMessage (this);
stopDevice();
String error;
AudioIODeviceType* type = getCurrentDeviceTypeObject();
if (type == 0 || (newSetup.inputDeviceName.isEmpty()
&& newSetup.outputDeviceName.isEmpty()))
{
deleteCurrentDevice();
if (treatAsChosenDevice)
updateXml();
return String::empty;
}
if (currentSetup.inputDeviceName != newSetup.inputDeviceName
|| currentSetup.outputDeviceName != newSetup.outputDeviceName
|| currentAudioDevice == 0)
{
deleteCurrentDevice();
scanDevicesIfNeeded();
if (newSetup.outputDeviceName.isNotEmpty()
&& ! type->getDeviceNames (false).contains (newSetup.outputDeviceName))
{
return "No such device: " + newSetup.outputDeviceName;
}
if (newSetup.inputDeviceName.isNotEmpty()
&& ! type->getDeviceNames (true).contains (newSetup.inputDeviceName))
{
return "No such device: " + newSetup.outputDeviceName;
}
currentAudioDevice = type->createDevice (newSetup.outputDeviceName,
newSetup.inputDeviceName);
if (currentAudioDevice == 0)
error = "Can't open device";
else
error = currentAudioDevice->getLastError();
if (error.isNotEmpty())
{
deleteCurrentDevice();
return error;
}
if (newSetup.useDefaultInputChannels)
{
inputChannels.clear();
inputChannels.setRange (0, numInputChansNeeded, true);
}
if (newSetup.useDefaultOutputChannels)
{
outputChannels.clear();
outputChannels.setRange (0, numOutputChansNeeded, true);
}
}
if (! newSetup.useDefaultInputChannels)
inputChannels = newSetup.inputChannels;
if (! newSetup.useDefaultOutputChannels)
outputChannels = newSetup.outputChannels;
currentSetup = newSetup;
currentSetup.sampleRate = chooseBestSampleRate (newSetup.sampleRate);
error = currentAudioDevice->open (inputChannels,
outputChannels,
currentSetup.sampleRate,
currentSetup.bufferSize);
if (error.isEmpty())
{
currentDeviceType = currentAudioDevice->getTypeName();
currentAudioDevice->start (&callbackHandler);
currentSetup.sampleRate = currentAudioDevice->getCurrentSampleRate();
currentSetup.bufferSize = currentAudioDevice->getCurrentBufferSizeSamples();
currentSetup.inputChannels = currentAudioDevice->getActiveInputChannels();
currentSetup.outputChannels = currentAudioDevice->getActiveOutputChannels();
for (int i = 0; i < availableDeviceTypes.size(); ++i)
if (availableDeviceTypes.getUnchecked (i)->getTypeName() == currentDeviceType)
*(lastDeviceTypeConfigs.getUnchecked (i)) = currentSetup;
if (treatAsChosenDevice)
updateXml();
}
else
{
deleteCurrentDevice();
}
return error;
}
double AudioDeviceManager::chooseBestSampleRate (double rate) const
{
jassert (currentAudioDevice != 0);
if (rate > 0)
{
bool ok = false;
for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
{
const double sr = currentAudioDevice->getSampleRate (i);
if (sr == rate)
ok = true;
}
if (! ok)
rate = 0;
}
if (rate == 0)
{
double lowestAbove44 = 0.0;
for (int i = currentAudioDevice->getNumSampleRates(); --i >= 0;)
{
const double sr = currentAudioDevice->getSampleRate (i);
if (sr >= 44100.0 && (lowestAbove44 == 0 || sr < lowestAbove44))
lowestAbove44 = sr;
}
if (lowestAbove44 == 0.0)
rate = currentAudioDevice->getSampleRate (0);
else
rate = lowestAbove44;
}
return rate;
}
void AudioDeviceManager::stopDevice()
{
if (currentAudioDevice != 0)
currentAudioDevice->stop();
}
void AudioDeviceManager::closeAudioDevice()
{
stopDevice();
deleteAndZero (currentAudioDevice);
}
void AudioDeviceManager::restartLastAudioDevice()
{
if (currentAudioDevice == 0)
{
if (currentSetup.inputDeviceName.isEmpty()
&& currentSetup.outputDeviceName.isEmpty())
{
// This method will only reload the last device that was running
// before closeAudioDevice() was called - you need to actually open
// one first, with setAudioDevice().
jassertfalse
return;
}
AudioDeviceSetup s (currentSetup);
setAudioDeviceSetup (s, false);
}
}
void AudioDeviceManager::updateXml()
{
delete lastExplicitSettings;
lastExplicitSettings = new XmlElement (T("DEVICESETUP"));
lastExplicitSettings->setAttribute (T("deviceType"), currentDeviceType);
lastExplicitSettings->setAttribute (T("audioOutputDeviceName"), currentSetup.outputDeviceName);
lastExplicitSettings->setAttribute (T("audioInputDeviceName"), currentSetup.inputDeviceName);
if (currentAudioDevice != 0)
{
lastExplicitSettings->setAttribute (T("audioDeviceRate"), currentAudioDevice->getCurrentSampleRate());
if (currentAudioDevice->getDefaultBufferSize() != currentAudioDevice->getCurrentBufferSizeSamples())
lastExplicitSettings->setAttribute (T("audioDeviceBufferSize"), currentAudioDevice->getCurrentBufferSizeSamples());
if (! currentSetup.useDefaultInputChannels)
lastExplicitSettings->setAttribute (T("audioDeviceInChans"), currentSetup.inputChannels.toString (2));
if (! currentSetup.useDefaultOutputChannels)
lastExplicitSettings->setAttribute (T("audioDeviceOutChans"), currentSetup.outputChannels.toString (2));
}
for (int i = 0; i < enabledMidiInputs.size(); ++i)
{
XmlElement* const m = new XmlElement (T("MIDIINPUT"));
m->setAttribute (T("name"), enabledMidiInputs[i]->getName());
lastExplicitSettings->addChildElement (m);
}
if (midiInsFromXml.size() > 0)
{
// Add any midi devices that have been enabled before, but which aren't currently
// open because the device has been disconnected.
const StringArray availableMidiDevices (MidiInput::getDevices());
for (int i = 0; i < midiInsFromXml.size(); ++i)
{
if (! availableMidiDevices.contains (midiInsFromXml[i], true))
{
XmlElement* const m = new XmlElement (T("MIDIINPUT"));
m->setAttribute (T("name"), midiInsFromXml[i]);
lastExplicitSettings->addChildElement (m);
}
}
}
if (defaultMidiOutputName.isNotEmpty())
lastExplicitSettings->setAttribute (T("defaultMidiOutput"), defaultMidiOutputName);
}
//==============================================================================
void AudioDeviceManager::setAudioCallback (AudioIODeviceCallback* newCallback)
{
if (newCallback != currentCallback)
{
AudioIODeviceCallback* lastCallback = currentCallback;
audioCallbackLock.enter();
currentCallback = 0;
audioCallbackLock.exit();
if (currentAudioDevice != 0)
{
if (lastCallback != 0)
lastCallback->audioDeviceStopped();
if (newCallback != 0)
newCallback->audioDeviceAboutToStart (currentAudioDevice);
}
currentCallback = newCallback;
}
}
void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,
int numInputChannels,
float** outputChannelData,
int numOutputChannels,
int numSamples)
{
const ScopedLock sl (audioCallbackLock);
if (inputLevelMeasurementEnabled)
{
for (int j = 0; j < numSamples; ++j)
{
float s = 0;
for (int i = 0; i < numInputChannels; ++i)
s += fabsf (inputChannelData[i][j]);
s /= numInputChannels;
const double decayFactor = 0.99992;
if (s > inputLevel)
inputLevel = s;
else if (inputLevel > 0.001f)
inputLevel *= decayFactor;
else
inputLevel = 0;
}
}
if (currentCallback != 0)
{
const double callbackStartTime = Time::getMillisecondCounterHiRes();
currentCallback->audioDeviceIOCallback (inputChannelData,
numInputChannels,
outputChannelData,
numOutputChannels,
numSamples);
const double msTaken = Time::getMillisecondCounterHiRes() - callbackStartTime;
const double filterAmount = 0.2;
cpuUsageMs += filterAmount * (msTaken - cpuUsageMs);
}
else
{
for (int i = 0; i < numOutputChannels; ++i)
zeromem (outputChannelData[i], sizeof (float) * numSamples);
}
if (testSound != 0)
{
const int numSamps = jmin (numSamples, testSound->getNumSamples() - testSoundPosition);
const float* const src = testSound->getSampleData (0, testSoundPosition);
for (int i = 0; i < numOutputChannels; ++i)
for (int j = 0; j < numSamps; ++j)
outputChannelData [i][j] += src[j];
testSoundPosition += numSamps;
if (testSoundPosition >= testSound->getNumSamples())
{
delete testSound;
testSound = 0;
}
}
}
void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)
{
cpuUsageMs = 0;
const double sampleRate = device->getCurrentSampleRate();
const int blockSize = device->getCurrentBufferSizeSamples();
if (sampleRate > 0.0 && blockSize > 0)
{
const double msPerBlock = 1000.0 * blockSize / sampleRate;
timeToCpuScale = (msPerBlock > 0.0) ? (1.0 / msPerBlock) : 0.0;
}
if (currentCallback != 0)
currentCallback->audioDeviceAboutToStart (device);
sendChangeMessage (this);
}
void AudioDeviceManager::audioDeviceStoppedInt()
{
cpuUsageMs = 0;
timeToCpuScale = 0;
sendChangeMessage (this);
if (currentCallback != 0)
currentCallback->audioDeviceStopped();
}
double AudioDeviceManager::getCpuUsage() const
{
return jlimit (0.0, 1.0, timeToCpuScale * cpuUsageMs);
}
//==============================================================================
void AudioDeviceManager::setMidiInputEnabled (const String& name,
const bool enabled)
{
if (enabled != isMidiInputEnabled (name))
{
if (enabled)
{
const int index = MidiInput::getDevices().indexOf (name);
if (index >= 0)
{
MidiInput* const min = MidiInput::openDevice (index, &callbackHandler);
if (min != 0)
{
enabledMidiInputs.add (min);
min->start();
}
}
}
else
{
for (int i = enabledMidiInputs.size(); --i >= 0;)
if (enabledMidiInputs[i]->getName() == name)
enabledMidiInputs.remove (i);
}
updateXml();
sendChangeMessage (this);
}
}
bool AudioDeviceManager::isMidiInputEnabled (const String& name) const
{
for (int i = enabledMidiInputs.size(); --i >= 0;)
if (enabledMidiInputs[i]->getName() == name)
return true;
return false;
}
void AudioDeviceManager::addMidiInputCallback (const String& name,
MidiInputCallback* callback)
{
removeMidiInputCallback (name, callback);
if (name.isEmpty())
{
midiCallbacks.add (callback);
midiCallbackDevices.add (0);
}
else
{
for (int i = enabledMidiInputs.size(); --i >= 0;)
{
if (enabledMidiInputs[i]->getName() == name)
{
const ScopedLock sl (midiCallbackLock);
midiCallbacks.add (callback);
midiCallbackDevices.add (enabledMidiInputs[i]);
break;
}
}
}
}
void AudioDeviceManager::removeMidiInputCallback (const String& name,
MidiInputCallback* /*callback*/)
{
const ScopedLock sl (midiCallbackLock);
for (int i = midiCallbacks.size(); --i >= 0;)
{
String devName;
if (midiCallbackDevices.getUnchecked(i) != 0)
devName = midiCallbackDevices.getUnchecked(i)->getName();
if (devName == name)
{
midiCallbacks.remove (i);
midiCallbackDevices.remove (i);
}
}
}
void AudioDeviceManager::handleIncomingMidiMessageInt (MidiInput* source,
const MidiMessage& message)
{
if (! message.isActiveSense())
{
const bool isDefaultSource = (source == 0 || source == enabledMidiInputs.getFirst());
const ScopedLock sl (midiCallbackLock);
for (int i = midiCallbackDevices.size(); --i >= 0;)
{
MidiInput* const md = midiCallbackDevices.getUnchecked(i);
if (md == source || (md == 0 && isDefaultSource))
midiCallbacks.getUnchecked(i)->handleIncomingMidiMessage (source, message);
}
}
}
//==============================================================================
void AudioDeviceManager::setDefaultMidiOutput (const String& deviceName)
{
if (defaultMidiOutputName != deviceName)
{
deleteAndZero (defaultMidiOutput);
defaultMidiOutputName = deviceName;
if (deviceName.isNotEmpty())
defaultMidiOutput = MidiOutput::openDevice (MidiOutput::getDevices().indexOf (deviceName));
updateXml();
sendChangeMessage (this);
}
}
//==============================================================================
void AudioDeviceManager::CallbackHandler::audioDeviceIOCallback (const float** inputChannelData,
int numInputChannels,
float** outputChannelData,
int numOutputChannels,
int numSamples)
{
owner->audioDeviceIOCallbackInt (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples);
}
void AudioDeviceManager::CallbackHandler::audioDeviceAboutToStart (AudioIODevice* device)
{
owner->audioDeviceAboutToStartInt (device);
}
void AudioDeviceManager::CallbackHandler::audioDeviceStopped()
{
owner->audioDeviceStoppedInt();
}
void AudioDeviceManager::CallbackHandler::handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message)
{
owner->handleIncomingMidiMessageInt (source, message);
}
//==============================================================================
void AudioDeviceManager::playTestSound()
{
audioCallbackLock.enter();
AudioSampleBuffer* oldSound = testSound;
testSound = 0;
audioCallbackLock.exit();
delete oldSound;
testSoundPosition = 0;
if (currentAudioDevice != 0)
{
const double sampleRate = currentAudioDevice->getCurrentSampleRate();
const int soundLength = (int) sampleRate;
AudioSampleBuffer* const newSound = new AudioSampleBuffer (1, soundLength);
float* samples = newSound->getSampleData (0);
const double frequency = MidiMessage::getMidiNoteInHertz (80);
const float amplitude = 0.5f;
const double phasePerSample = double_Pi * 2.0 / (sampleRate / frequency);
for (int i = 0; i < soundLength; ++i)
samples[i] = amplitude * (float) sin (i * phasePerSample);
newSound->applyGainRamp (0, 0, soundLength / 10, 0.0f, 1.0f);
newSound->applyGainRamp (0, soundLength - soundLength / 4, soundLength / 4, 1.0f, 0.0f);
const ScopedLock sl (audioCallbackLock);
testSound = newSound;
}
}
void AudioDeviceManager::enableInputLevelMeasurement (const bool enableMeasurement)
{
if (inputLevelMeasurementEnabled != enableMeasurement)
{
const ScopedLock sl (audioCallbackLock);
inputLevelMeasurementEnabled = enableMeasurement;
inputLevel = 0;
}
}
double AudioDeviceManager::getCurrentInputLevel() const
{
jassert (inputLevelMeasurementEnabled); // you need to call enableInputLevelMeasurement() before using this!
return inputLevel;
}
END_JUCE_NAMESPACE