Browse Source

Added output level metering to AudioDeviceManager

tags/2021-05-28
jules 9 years ago
parent
commit
7fad2545c9
2 changed files with 71 additions and 50 deletions
  1. +43
    -34
      modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
  2. +28
    -16
      modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h

+ 43
- 34
modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp View File

@@ -151,7 +151,6 @@ AudioDeviceManager::AudioDeviceManager()
: numInputChansNeeded (0),
numOutputChansNeeded (2),
listNeedsScanning (true),
inputLevel (0),
cpuUsageMs (0),
timeToCpuScale (0)
{
@@ -761,31 +760,8 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat
{
const ScopedLock sl (audioCallbackLock);
if (inputLevelMeasurementEnabledCount.get() > 0 && numInputChannels > 0)
{
for (int j = 0; j < numSamples; ++j)
{
float s = 0;
for (int i = 0; i < numInputChannels; ++i)
s += std::abs (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;
}
}
else
{
inputLevel = 0;
}
inputLevelMeter.updateLevel (inputChannelData, numInputChannels, numSamples);
outputLevelMeter.updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);
if (callbacks.size() > 0)
{
@@ -1141,18 +1117,51 @@ void AudioDeviceManager::playTestSound()
}
//==============================================================================
void AudioDeviceManager::enableInputLevelMeasurement (const bool enableMeasurement)
AudioDeviceManager::LevelMeter::LevelMeter() noexcept : level() {}
void AudioDeviceManager::LevelMeter::updateLevel (const float* const* channelData, int numChannels, int numSamples) noexcept
{
if (enableMeasurement)
++inputLevelMeasurementEnabledCount;
if (enabled.get() != 0 && numChannels > 0)
{
for (int j = 0; j < numSamples; ++j)
{
float s = 0;
for (int i = 0; i < numChannels; ++i)
s += std::abs (channelData[i][j]);
s /= numChannels;
const double decayFactor = 0.99992;
if (s > level)
level = s;
else if (level > 0.001f)
level *= decayFactor;
else
level = 0;
}
}
else
--inputLevelMeasurementEnabledCount;
{
level = 0;
}
}
inputLevel = 0;
void AudioDeviceManager::LevelMeter::setEnabled (bool shouldBeEnabled) noexcept
{
enabled.set (shouldBeEnabled ? 1 : 0);
level = 0;
}
double AudioDeviceManager::getCurrentInputLevel() const
double AudioDeviceManager::LevelMeter::getCurrentLevel() const noexcept
{
jassert (inputLevelMeasurementEnabledCount.get() > 0); // you need to call enableInputLevelMeasurement() before using this!
return inputLevel;
jassert (enabled.get() != 0); // you need to call setEnabled (true) before using this!
return level;
}
double AudioDeviceManager::getCurrentInputLevel() const noexcept { return inputLevelMeter.getCurrentLevel(); }
double AudioDeviceManager::getCurrentOutputLevel() const noexcept { return outputLevelMeter.getCurrentLevel(); }
void AudioDeviceManager::enableInputLevelMeasurement (bool enable) noexcept { inputLevelMeter.setEnabled (enable); }
void AudioDeviceManager::enableOutputLevelMeasurement (bool enable) noexcept { outputLevelMeter.setEnabled (enable); }

+ 28
- 16
modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h View File

@@ -456,26 +456,27 @@ public:
bool playOnAllOutputChannels = false);
//==============================================================================
/** Turns on level-measuring.
When enabled, the device manager will measure the peak input level
across all channels, and you can get this level by calling getCurrentInputLevel().
This is mainly intended for audio setup UI panels to use to create a mic
level display, so that the user can check that they've selected the right
device.
/** Turns on level-measuring for input channels.
@see getCurrentInputLevel()
*/
void enableInputLevelMeasurement (bool enableMeasurement) noexcept;
A simple filter is used to make the level decay smoothly, but this is
only intended for giving rough feedback, and not for any kind of accurate
measurement.
/** Turns on level-measuring for output channels.
@see getCurrentOutputLevel()
*/
void enableInputLevelMeasurement (bool enableMeasurement);
void enableOutputLevelMeasurement (bool enableMeasurement) noexcept;
/** Returns the current input level.
To use this, you must first enable it by calling enableInputLevelMeasurement().
See enableInputLevelMeasurement() for more info.
@see enableInputLevelMeasurement()
*/
double getCurrentInputLevel() const noexcept;
/** Returns the current output level.
To use this, you must first enable it by calling enableOutputLevelMeasurement().
@see enableOutputLevelMeasurement()
*/
double getCurrentInputLevel() const;
double getCurrentOutputLevel() const noexcept;
/** Returns the a lock that can be used to synchronise access to the audio callback.
Obviously while this is locked, you're blocking the audio thread from running, so
@@ -502,8 +503,6 @@ private:
BigInteger inputChannels, outputChannels;
ScopedPointer<XmlElement> lastExplicitSettings;
mutable bool listNeedsScanning;
Atomic<int> inputLevelMeasurementEnabledCount;
double inputLevel;
AudioSampleBuffer tempBuffer;
struct MidiCallbackInfo
@@ -522,6 +521,19 @@ private:
double cpuUsageMs, timeToCpuScale;
struct LevelMeter
{
LevelMeter() noexcept;
void updateLevel (const float* const*, int numChannels, int numSamples) noexcept;
void setEnabled (bool) noexcept;
double getCurrentLevel() const noexcept;
Atomic<int> enabled;
double level;
};
LevelMeter inputLevelMeter, outputLevelMeter;
//==============================================================================
class CallbackHandler;
friend class CallbackHandler;


Loading…
Cancel
Save