Browse Source

Made the AudioDeviceManager input/output level getters return a reference-counted struct to ensure that the level processing code is only executed when needed

tags/2021-05-28
ed 7 years ago
parent
commit
dc96e99738
3 changed files with 44 additions and 46 deletions
  1. +7
    -16
      modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
  2. +34
    -27
      modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
  3. +3
    -3
      modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp

+ 7
- 16
modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp View File

@@ -684,8 +684,8 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat
{
const ScopedLock sl (audioCallbackLock);
inputLevelMeter.updateLevel (inputChannelData, numInputChannels, numSamples);
outputLevelMeter.updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);
inputLevelGetter->updateLevel (inputChannelData, numInputChannels, numSamples);
outputLevelGetter->updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);
if (callbacks.size() > 0)
{
@@ -912,9 +912,12 @@ AudioDeviceManager::LevelMeter::LevelMeter() noexcept : level() {}
void AudioDeviceManager::LevelMeter::updateLevel (const float* const* channelData, int numChannels, int numSamples) noexcept
{
if (getReferenceCount() <= 1)
return;
auto localLevel = level.get();
if (enabled.get() != 0 && numChannels > 0)
if (numChannels > 0)
{
for (int j = 0; j < numSamples; ++j)
{
@@ -943,15 +946,9 @@ void AudioDeviceManager::LevelMeter::updateLevel (const float* const* channelDat
level = localLevel;
}
void AudioDeviceManager::LevelMeter::setEnabled (bool shouldBeEnabled) noexcept
{
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!
jassert (getReferenceCount() > 1);
return level.get();
}
@@ -997,10 +994,4 @@ int AudioDeviceManager::getXRunCount() const noexcept
return (deviceXRuns >= 0 ? deviceXRuns : xruns);
}
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); }
} // namespace juce

+ 34
- 27
modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h View File

@@ -403,28 +403,45 @@ public:
void playTestSound();
//==============================================================================
/** Turns on level-measuring for input channels.
@see getCurrentInputLevel()
*/
void enableInputLevelMeasurement (bool enableMeasurement) noexcept;
/**
A simple reference-counted struct that holds a level-meter value that can be read
using getCurrentLevel().
This is used to ensure that the level processing code is only executed when something
holds a reference to one of these objects and will be bypassed otherwise.
/** Turns on level-measuring for output channels.
@see getCurrentOutputLevel()
@see getInputLevelGetter, getOutputLevelGetter
*/
void enableOutputLevelMeasurement (bool enableMeasurement) noexcept;
struct LevelMeter : public ReferenceCountedObject
{
typedef ReferenceCountedObjectPtr<LevelMeter> Ptr;
LevelMeter() noexcept;
double getCurrentLevel() const noexcept;
private:
friend class AudioDeviceManager;
Atomic<float> level { 0 };
void updateLevel (const float* const*, int numChannels, int numSamples) noexcept;
};
/** Returns a reference-counted object that can be used to get the current input level.
/** Returns the current input level.
To use this, you must first enable it by calling enableInputLevelMeasurement().
@see enableInputLevelMeasurement()
You need to store this object locally to ensure that the reference count is incremented
and decremented properly. The current input level value can be read using getCurrentLevel().
*/
double getCurrentInputLevel() const noexcept;
LevelMeter::Ptr getInputLevelGetter() noexcept { return inputLevelGetter; }
/** Returns a reference-counted object that can be used to get the current input level.
/** Returns the current output level.
To use this, you must first enable it by calling enableOutputLevelMeasurement().
@see enableOutputLevelMeasurement()
You need to store this object locally to ensure that the reference count is incremented
and decremented properly. The current input level value can be read using getCurrentLevel().
*/
double getCurrentOutputLevel() const noexcept;
LevelMeter::Ptr getOutputLevelGetter() noexcept { return outputLevelGetter; }
//==============================================================================
/** 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
it must only be used for very brief periods when absolutely necessary.
@@ -481,18 +498,8 @@ private:
double cpuUsageMs = 0, timeToCpuScale = 0, msPerBlock = 0;
int xruns = 0;
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;
Atomic<float> level;
};
LevelMeter inputLevelMeter, outputLevelMeter;
LevelMeter::Ptr inputLevelGetter { new LevelMeter() },
outputLevelGetter { new LevelMeter() };
//==============================================================================
class CallbackHandler;


+ 3
- 3
modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp View File

@@ -33,19 +33,18 @@ struct SimpleDeviceManagerInputLevelMeter : public Component,
SimpleDeviceManagerInputLevelMeter (AudioDeviceManager& m) : manager (m)
{
startTimerHz (20);
manager.enableInputLevelMeasurement (true);
inputLevelGetter = manager.getInputLevelGetter();
}
~SimpleDeviceManagerInputLevelMeter()
{
manager.enableInputLevelMeasurement (false);
}
void timerCallback() override
{
if (isShowing())
{
auto newLevel = (float) manager.getCurrentInputLevel();
auto newLevel = (float) inputLevelGetter->getCurrentLevel();
if (std::abs (level - newLevel) > 0.005f)
{
@@ -66,6 +65,7 @@ struct SimpleDeviceManagerInputLevelMeter : public Component,
}
AudioDeviceManager& manager;
AudioDeviceManager::LevelMeter::Ptr inputLevelGetter;
float level = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SimpleDeviceManagerInputLevelMeter)


Loading…
Cancel
Save