diff --git a/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp b/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp index 25678d7b4a..62c99379ba 100755 --- a/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp +++ b/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp @@ -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 (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; - - inputLevel = 0; + { + level = 0; + } } -double AudioDeviceManager::getCurrentInputLevel() const +void AudioDeviceManager::LevelMeter::setEnabled (bool shouldBeEnabled) noexcept { - jassert (inputLevelMeasurementEnabledCount.get() > 0); // you need to call enableInputLevelMeasurement() before using this! - return inputLevel; + enabled.set (shouldBeEnabled ? 1 : 0); + level = 0; } + +double AudioDeviceManager::LevelMeter::getCurrentLevel() const noexcept +{ + 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); } diff --git a/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h b/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h index 4d94b53b5b..59977c6339 100644 --- a/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h +++ b/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h @@ -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. - - 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 input channels. + @see getCurrentInputLevel() */ - void enableInputLevelMeasurement (bool enableMeasurement); + void enableInputLevelMeasurement (bool enableMeasurement) noexcept; + + /** Turns on level-measuring for output channels. + @see getCurrentOutputLevel() + */ + 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; + double getCurrentInputLevel() const noexcept; + + /** Returns the current output level. + To use this, you must first enable it by calling enableOutputLevelMeasurement(). + @see enableOutputLevelMeasurement() + */ + 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 lastExplicitSettings; mutable bool listNeedsScanning; - Atomic 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 enabled; + double level; + }; + + LevelMeter inputLevelMeter, outputLevelMeter; + //============================================================================== class CallbackHandler; friend class CallbackHandler;