Refactoring of the analog AGC functionality to add multichannel support
This CL refactors the analog AGC functionality. In particular it: -Breaks then tight dependency between the analog AGC and the digital AGC implementation. -Removes the complicated callback interface for reporting the analog level and replaces it with an int. Bug: webrtc:10859 Change-Id: I3572d60ab98edebbcffa25af64cc74c66f9868fc Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/159039 Reviewed-by: Sam Zackrisson <saza@webrtc.org> Commit-Queue: Per Åhgren <peah@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29838}
This commit is contained in:
parent
f3fcde36c2
commit
0e3198e434
@ -124,8 +124,6 @@ rtc_library("audio_processing") {
|
||||
"echo_detector/moving_max.h",
|
||||
"echo_detector/normalized_covariance_estimator.cc",
|
||||
"echo_detector/normalized_covariance_estimator.h",
|
||||
"gain_control_for_experimental_agc.cc",
|
||||
"gain_control_for_experimental_agc.h",
|
||||
"gain_control_impl.cc",
|
||||
"gain_control_impl.h",
|
||||
"gain_controller2.cc",
|
||||
|
||||
@ -36,6 +36,7 @@ rtc_library("agc") {
|
||||
"../../../system_wrappers:metrics",
|
||||
"../agc2:level_estimation_agc",
|
||||
"../vad",
|
||||
"//third_party/abseil-cpp/absl/types:optional",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -116,31 +116,6 @@ int LevelFromGainError(int gain_error, int level, int min_mic_level) {
|
||||
return new_level;
|
||||
}
|
||||
|
||||
int InitializeGainControl(GainControl* gain_control,
|
||||
bool disable_digital_adaptive) {
|
||||
if (gain_control->set_mode(GainControl::kFixedDigital) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed.";
|
||||
return -1;
|
||||
}
|
||||
const int target_level_dbfs = disable_digital_adaptive ? 0 : 2;
|
||||
if (gain_control->set_target_level_dbfs(target_level_dbfs) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed.";
|
||||
return -1;
|
||||
}
|
||||
const int compression_gain_db =
|
||||
disable_digital_adaptive ? 0 : kDefaultCompressionGain;
|
||||
if (gain_control->set_compression_gain_db(compression_gain_db) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed.";
|
||||
return -1;
|
||||
}
|
||||
const bool enable_limiter = !disable_digital_adaptive;
|
||||
if (gain_control->enable_limiter(enable_limiter) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "enable_limiter() failed.";
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the proportion of samples in the buffer which are at full-scale
|
||||
// (and presumably clipped).
|
||||
float ComputeClippedRatio(const float* const* audio,
|
||||
@ -164,29 +139,18 @@ float ComputeClippedRatio(const float* const* audio,
|
||||
} // namespace
|
||||
|
||||
AgcManagerDirect::AgcManagerDirect(Agc* agc,
|
||||
GainControl* gctrl,
|
||||
VolumeCallbacks* volume_callbacks,
|
||||
int startup_min_level,
|
||||
int clipped_level_min)
|
||||
: AgcManagerDirect(gctrl,
|
||||
volume_callbacks,
|
||||
startup_min_level,
|
||||
clipped_level_min,
|
||||
false,
|
||||
false) {
|
||||
: AgcManagerDirect(startup_min_level, clipped_level_min, false, false) {
|
||||
RTC_DCHECK(agc_);
|
||||
agc_.reset(agc);
|
||||
}
|
||||
|
||||
AgcManagerDirect::AgcManagerDirect(GainControl* gctrl,
|
||||
VolumeCallbacks* volume_callbacks,
|
||||
int startup_min_level,
|
||||
AgcManagerDirect::AgcManagerDirect(int startup_min_level,
|
||||
int clipped_level_min,
|
||||
bool use_agc2_level_estimation,
|
||||
bool disable_digital_adaptive)
|
||||
: data_dumper_(new ApmDataDumper(instance_counter_)),
|
||||
gctrl_(gctrl),
|
||||
volume_callbacks_(volume_callbacks),
|
||||
frames_since_clipped_(kClippedWaitFrames),
|
||||
level_(0),
|
||||
max_level_(kMaxMicLevel),
|
||||
@ -211,7 +175,7 @@ AgcManagerDirect::AgcManagerDirect(GainControl* gctrl,
|
||||
|
||||
AgcManagerDirect::~AgcManagerDirect() {}
|
||||
|
||||
int AgcManagerDirect::Initialize() {
|
||||
void AgcManagerDirect::Initialize() {
|
||||
RTC_DLOG(LS_INFO) << "AgcManagerDirect::Initialize";
|
||||
max_level_ = kMaxMicLevel;
|
||||
max_compression_gain_ = kMaxCompressionGain;
|
||||
@ -224,8 +188,25 @@ int AgcManagerDirect::Initialize() {
|
||||
// example, what happens when we change devices.
|
||||
|
||||
data_dumper_->InitiateNewSetOfRecordings();
|
||||
}
|
||||
|
||||
return InitializeGainControl(gctrl_, disable_digital_adaptive_);
|
||||
void AgcManagerDirect::ConfigureGainControl(GainControl* gain_control) const {
|
||||
if (gain_control->set_mode(GainControl::kFixedDigital) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "set_mode(GainControl::kFixedDigital) failed.";
|
||||
}
|
||||
const int target_level_dbfs = disable_digital_adaptive_ ? 0 : 2;
|
||||
if (gain_control->set_target_level_dbfs(target_level_dbfs) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "set_target_level_dbfs() failed.";
|
||||
}
|
||||
const int compression_gain_db =
|
||||
disable_digital_adaptive_ ? 0 : kDefaultCompressionGain;
|
||||
if (gain_control->set_compression_gain_db(compression_gain_db) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "set_compression_gain_db() failed.";
|
||||
}
|
||||
const bool enable_limiter = !disable_digital_adaptive_;
|
||||
if (gain_control->enable_limiter(enable_limiter) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "enable_limiter() failed.";
|
||||
}
|
||||
}
|
||||
|
||||
void AgcManagerDirect::AnalyzePreProcess(const float* const* audio,
|
||||
@ -274,7 +255,8 @@ void AgcManagerDirect::AnalyzePreProcess(const float* const* audio,
|
||||
|
||||
void AgcManagerDirect::Process(const float* audio,
|
||||
size_t length,
|
||||
int sample_rate_hz) {
|
||||
int sample_rate_hz,
|
||||
GainControl* gain_control) {
|
||||
if (capture_muted_) {
|
||||
return;
|
||||
}
|
||||
@ -305,12 +287,19 @@ void AgcManagerDirect::Process(const float* audio,
|
||||
UpdateCompressor();
|
||||
}
|
||||
|
||||
if (new_compression_to_set_) {
|
||||
if (gain_control->set_compression_gain_db(*new_compression_to_set_) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << compression_
|
||||
<< ") failed.";
|
||||
}
|
||||
}
|
||||
new_compression_to_set_ = absl::nullopt;
|
||||
data_dumper_->DumpRaw("experimental_gain_control_compression_gain_db", 1,
|
||||
&compression_);
|
||||
}
|
||||
|
||||
void AgcManagerDirect::SetLevel(int new_level) {
|
||||
int voe_level = volume_callbacks_->GetMicVolume();
|
||||
int voe_level = stream_analog_level_;
|
||||
if (voe_level == 0) {
|
||||
RTC_DLOG(LS_INFO)
|
||||
<< "[agc] VolumeCallbacks returned level=0, taking no action.";
|
||||
@ -344,7 +333,7 @@ void AgcManagerDirect::SetLevel(int new_level) {
|
||||
return;
|
||||
}
|
||||
|
||||
volume_callbacks_->SetMicVolume(new_level);
|
||||
stream_analog_level_ = new_level;
|
||||
RTC_DLOG(LS_INFO) << "[agc] voe_level=" << voe_level << ", "
|
||||
<< "level_=" << level_ << ", "
|
||||
<< "new_level=" << new_level;
|
||||
@ -382,7 +371,7 @@ float AgcManagerDirect::voice_probability() {
|
||||
}
|
||||
|
||||
int AgcManagerDirect::CheckVolumeAndReset() {
|
||||
int level = volume_callbacks_->GetMicVolume();
|
||||
int level = stream_analog_level_;
|
||||
// Reasons for taking action at startup:
|
||||
// 1) A person starting a call is expected to be heard.
|
||||
// 2) Independent of interpretation of |level| == 0 we should raise it so the
|
||||
@ -403,7 +392,7 @@ int AgcManagerDirect::CheckVolumeAndReset() {
|
||||
if (level < minLevel) {
|
||||
level = minLevel;
|
||||
RTC_DLOG(LS_INFO) << "[agc] Initial volume too low, raising to " << level;
|
||||
volume_callbacks_->SetMicVolume(level);
|
||||
stream_analog_level_ = level;
|
||||
}
|
||||
agc_->Reset();
|
||||
level_ = level;
|
||||
@ -508,10 +497,7 @@ void AgcManagerDirect::UpdateCompressor() {
|
||||
kMaxCompressionGain + 1);
|
||||
compression_ = new_compression;
|
||||
compression_accumulator_ = new_compression;
|
||||
if (gctrl_->set_compression_gain_db(compression_) != 0) {
|
||||
RTC_LOG(LS_ERROR) << "set_compression_gain_db(" << compression_
|
||||
<< ") failed.";
|
||||
}
|
||||
new_compression_to_set_ = compression_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "modules/audio_processing/agc/agc.h"
|
||||
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
||||
#include "rtc_base/constructor_magic.h"
|
||||
@ -23,17 +24,6 @@ namespace webrtc {
|
||||
class AudioFrame;
|
||||
class GainControl;
|
||||
|
||||
// Callbacks that need to be injected into AgcManagerDirect to read and control
|
||||
// the volume values. This is done to remove the VoiceEngine dependency in
|
||||
// AgcManagerDirect.
|
||||
// TODO(aluebs): Remove VolumeCallbacks.
|
||||
class VolumeCallbacks {
|
||||
public:
|
||||
virtual ~VolumeCallbacks() {}
|
||||
virtual void SetMicVolume(int volume) = 0;
|
||||
virtual int GetMicVolume() = 0;
|
||||
};
|
||||
|
||||
// Direct interface to use AGC to set volume and compression values.
|
||||
// AudioProcessing uses this interface directly to integrate the callback-less
|
||||
// AGC.
|
||||
@ -45,20 +35,23 @@ class AgcManagerDirect final {
|
||||
// responsible for processing the audio using it after the call to Process.
|
||||
// The operating range of startup_min_level is [12, 255] and any input value
|
||||
// outside that range will be clamped.
|
||||
AgcManagerDirect(GainControl* gctrl,
|
||||
VolumeCallbacks* volume_callbacks,
|
||||
int startup_min_level,
|
||||
AgcManagerDirect(int startup_min_level,
|
||||
int clipped_level_min,
|
||||
bool use_agc2_level_estimation,
|
||||
bool disable_digital_adaptive);
|
||||
|
||||
~AgcManagerDirect();
|
||||
|
||||
int Initialize();
|
||||
void Initialize();
|
||||
void ConfigureGainControl(GainControl* gain_control) const;
|
||||
|
||||
void AnalyzePreProcess(const float* const* audio,
|
||||
int num_channels,
|
||||
size_t samples_per_channel);
|
||||
void Process(const float* audio, size_t length, int sample_rate_hz);
|
||||
void Process(const float* audio,
|
||||
size_t length,
|
||||
int sample_rate_hz,
|
||||
GainControl* gain_control);
|
||||
|
||||
// Call when the capture stream has been muted/unmuted. This causes the
|
||||
// manager to disregard all incoming audio; chances are good it's background
|
||||
@ -68,6 +61,9 @@ class AgcManagerDirect final {
|
||||
|
||||
float voice_probability();
|
||||
|
||||
int stream_analog_level() const { return stream_analog_level_; }
|
||||
void set_stream_analog_level(int level) { stream_analog_level_ = level; }
|
||||
|
||||
private:
|
||||
friend class AgcManagerDirectTest;
|
||||
|
||||
@ -79,8 +75,6 @@ class AgcManagerDirect final {
|
||||
// Dependency injection for testing. Don't delete |agc| as the memory is owned
|
||||
// by the manager.
|
||||
AgcManagerDirect(Agc* agc,
|
||||
GainControl* gctrl,
|
||||
VolumeCallbacks* volume_callbacks,
|
||||
int startup_min_level,
|
||||
int clipped_level_min);
|
||||
|
||||
@ -104,8 +98,6 @@ class AgcManagerDirect final {
|
||||
static int instance_counter_;
|
||||
|
||||
std::unique_ptr<Agc> agc_;
|
||||
GainControl* gctrl_;
|
||||
VolumeCallbacks* volume_callbacks_;
|
||||
|
||||
int frames_since_clipped_;
|
||||
int level_;
|
||||
@ -122,6 +114,8 @@ class AgcManagerDirect final {
|
||||
int startup_min_level_;
|
||||
const int clipped_level_min_;
|
||||
int calls_since_last_gain_log_ = 0;
|
||||
int stream_analog_level_ = 0;
|
||||
absl::optional<int> new_compression_to_set_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(AgcManagerDirect);
|
||||
};
|
||||
|
||||
@ -55,27 +55,18 @@ class MockGainControl : public GainControl {
|
||||
MOCK_CONST_METHOD0(stream_is_saturated, bool());
|
||||
};
|
||||
|
||||
class TestVolumeCallbacks : public VolumeCallbacks {
|
||||
public:
|
||||
TestVolumeCallbacks() : volume_(0) {}
|
||||
void SetMicVolume(int volume) override { volume_ = volume; }
|
||||
int GetMicVolume() override { return volume_; }
|
||||
|
||||
private:
|
||||
int volume_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
class AgcManagerDirectTest : public ::testing::Test {
|
||||
protected:
|
||||
AgcManagerDirectTest()
|
||||
: agc_(new MockAgc),
|
||||
manager_(agc_, &gctrl_, &volume_, kInitialVolume, kClippedMin),
|
||||
manager_(agc_, kInitialVolume, kClippedMin),
|
||||
audio(kNumChannels),
|
||||
audio_data(kNumChannels * kSamplesPerChannel, 0.f) {
|
||||
ExpectInitialize();
|
||||
manager_.Initialize();
|
||||
manager_.ConfigureGainControl(&gctrl_);
|
||||
for (size_t ch = 0; ch < kNumChannels; ++ch) {
|
||||
audio[ch] = &audio_data[ch * kSamplesPerChannel];
|
||||
}
|
||||
@ -88,12 +79,12 @@ class AgcManagerDirectTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
void SetVolumeAndProcess(int volume) {
|
||||
volume_.SetMicVolume(volume);
|
||||
manager_.set_stream_analog_level(volume);
|
||||
FirstProcess();
|
||||
}
|
||||
|
||||
void ExpectCheckVolumeAndReset(int volume) {
|
||||
volume_.SetMicVolume(volume);
|
||||
manager_.set_stream_analog_level(volume);
|
||||
EXPECT_CALL(*agc_, Reset());
|
||||
}
|
||||
|
||||
@ -107,7 +98,7 @@ class AgcManagerDirectTest : public ::testing::Test {
|
||||
void CallProcess(int num_calls) {
|
||||
for (int i = 0; i < num_calls; ++i) {
|
||||
EXPECT_CALL(*agc_, Process(_, _, _)).WillOnce(Return());
|
||||
manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz);
|
||||
manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz, &gctrl_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,7 +120,6 @@ class AgcManagerDirectTest : public ::testing::Test {
|
||||
|
||||
MockAgc* agc_;
|
||||
MockGainControl gctrl_;
|
||||
TestVolumeCallbacks volume_;
|
||||
AgcManagerDirect manager_;
|
||||
std::vector<float*> audio;
|
||||
std::vector<float> audio_data;
|
||||
@ -137,7 +127,7 @@ class AgcManagerDirectTest : public ::testing::Test {
|
||||
|
||||
TEST_F(AgcManagerDirectTest, StartupMinVolumeConfigurationIsRespected) {
|
||||
FirstProcess();
|
||||
EXPECT_EQ(kInitialVolume, volume_.GetMicVolume());
|
||||
EXPECT_EQ(kInitialVolume, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) {
|
||||
@ -157,12 +147,12 @@ TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) {
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(130, volume_.GetMicVolume());
|
||||
EXPECT_EQ(130, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(168, volume_.GetMicVolume());
|
||||
EXPECT_EQ(168, manager_.stream_analog_level());
|
||||
|
||||
// Inside the compressor's window; no change of volume.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
@ -176,17 +166,17 @@ TEST_F(AgcManagerDirectTest, MicVolumeResponseToRmsError) {
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(167, volume_.GetMicVolume());
|
||||
EXPECT_EQ(167, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(163, volume_.GetMicVolume());
|
||||
EXPECT_EQ(163, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-9), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(129, volume_.GetMicVolume());
|
||||
EXPECT_EQ(129, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, MicVolumeIsLimited) {
|
||||
@ -196,60 +186,60 @@ TEST_F(AgcManagerDirectTest, MicVolumeIsLimited) {
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(183, volume_.GetMicVolume());
|
||||
EXPECT_EQ(183, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(243, volume_.GetMicVolume());
|
||||
EXPECT_EQ(243, manager_.stream_analog_level());
|
||||
|
||||
// Won't go higher than the maximum.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(255, volume_.GetMicVolume());
|
||||
EXPECT_EQ(255, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(254, volume_.GetMicVolume());
|
||||
EXPECT_EQ(254, manager_.stream_analog_level());
|
||||
|
||||
// Maximum downwards change is limited.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(194, volume_.GetMicVolume());
|
||||
EXPECT_EQ(194, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(137, volume_.GetMicVolume());
|
||||
EXPECT_EQ(137, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(88, volume_.GetMicVolume());
|
||||
EXPECT_EQ(88, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(54, volume_.GetMicVolume());
|
||||
EXPECT_EQ(54, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(33, volume_.GetMicVolume());
|
||||
EXPECT_EQ(33, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(18, volume_.GetMicVolume());
|
||||
EXPECT_EQ(18, manager_.stream_analog_level());
|
||||
|
||||
// Won't go lower than the minimum.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(12, volume_.GetMicVolume());
|
||||
EXPECT_EQ(12, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, CompressorStepsTowardsTarget) {
|
||||
@ -374,7 +364,7 @@ TEST_F(AgcManagerDirectTest, CompressorReachesMinimum) {
|
||||
|
||||
TEST_F(AgcManagerDirectTest, NoActionWhileMuted) {
|
||||
manager_.SetCaptureMuted(true);
|
||||
manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz);
|
||||
manager_.Process(nullptr, kSamplesPerChannel, kSampleRateHz, &gctrl_);
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, UnmutingChecksVolumeWithoutRaising) {
|
||||
@ -386,7 +376,7 @@ TEST_F(AgcManagerDirectTest, UnmutingChecksVolumeWithoutRaising) {
|
||||
// SetMicVolume should not be called.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(127, volume_.GetMicVolume());
|
||||
EXPECT_EQ(127, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, UnmutingRaisesTooLowVolume) {
|
||||
@ -397,7 +387,7 @@ TEST_F(AgcManagerDirectTest, UnmutingRaisesTooLowVolume) {
|
||||
ExpectCheckVolumeAndReset(11);
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_)).WillOnce(Return(false));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(12, volume_.GetMicVolume());
|
||||
EXPECT_EQ(12, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, ManualLevelChangeResultsInNoSetMicCall) {
|
||||
@ -413,24 +403,24 @@ TEST_F(AgcManagerDirectTest, ManualLevelChangeResultsInNoSetMicCall) {
|
||||
|
||||
// GetMicVolume returns a value outside of the quantization slack, indicating
|
||||
// a manual volume change.
|
||||
ASSERT_NE(volume_.GetMicVolume(), 154);
|
||||
volume_.SetMicVolume(154);
|
||||
ASSERT_NE(manager_.stream_analog_level(), 154);
|
||||
manager_.set_stream_analog_level(154);
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(154, volume_.GetMicVolume());
|
||||
EXPECT_EQ(154, manager_.stream_analog_level());
|
||||
|
||||
// Do the same thing, except downwards now.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
||||
volume_.SetMicVolume(100);
|
||||
manager_.set_stream_analog_level(100);
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(100, volume_.GetMicVolume());
|
||||
EXPECT_EQ(100, manager_.stream_analog_level());
|
||||
|
||||
// And finally verify the AGC continues working without a manual change.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(99, volume_.GetMicVolume());
|
||||
EXPECT_EQ(99, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeFromMax) {
|
||||
@ -441,25 +431,25 @@ TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeFromMax) {
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(183, volume_.GetMicVolume());
|
||||
EXPECT_EQ(183, manager_.stream_analog_level());
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(243, volume_.GetMicVolume());
|
||||
EXPECT_EQ(243, manager_.stream_analog_level());
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(255, volume_.GetMicVolume());
|
||||
EXPECT_EQ(255, manager_.stream_analog_level());
|
||||
|
||||
// Manual change does not result in SetMicVolume call.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
||||
volume_.SetMicVolume(50);
|
||||
manager_.set_stream_analog_level(50);
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(50, volume_.GetMicVolume());
|
||||
EXPECT_EQ(50, manager_.stream_analog_level());
|
||||
|
||||
// Continues working as usual afterwards.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(69, volume_.GetMicVolume());
|
||||
EXPECT_EQ(69, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeBelowMin) {
|
||||
@ -469,40 +459,40 @@ TEST_F(AgcManagerDirectTest, RecoveryAfterManualLevelChangeBelowMin) {
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-1), Return(true)));
|
||||
// Don't set to zero, which will cause AGC to take no action.
|
||||
volume_.SetMicVolume(1);
|
||||
manager_.set_stream_analog_level(1);
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(1, volume_.GetMicVolume());
|
||||
EXPECT_EQ(1, manager_.stream_analog_level());
|
||||
|
||||
// Continues working as usual afterwards.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(2, volume_.GetMicVolume());
|
||||
EXPECT_EQ(2, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(11, volume_.GetMicVolume());
|
||||
EXPECT_EQ(11, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(20), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(18, volume_.GetMicVolume());
|
||||
EXPECT_EQ(18, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, NoClippingHasNoImpact) {
|
||||
FirstProcess();
|
||||
|
||||
CallPreProc(100, 0);
|
||||
EXPECT_EQ(128, volume_.GetMicVolume());
|
||||
EXPECT_EQ(128, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, ClippingUnderThresholdHasNoImpact) {
|
||||
FirstProcess();
|
||||
|
||||
CallPreProc(1, 0.099);
|
||||
EXPECT_EQ(128, volume_.GetMicVolume());
|
||||
EXPECT_EQ(128, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, ClippingLowersVolume) {
|
||||
@ -510,7 +500,7 @@ TEST_F(AgcManagerDirectTest, ClippingLowersVolume) {
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, 0.2);
|
||||
EXPECT_EQ(240, volume_.GetMicVolume());
|
||||
EXPECT_EQ(240, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, WaitingPeriodBetweenClippingChecks) {
|
||||
@ -518,15 +508,15 @@ TEST_F(AgcManagerDirectTest, WaitingPeriodBetweenClippingChecks) {
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(240, volume_.GetMicVolume());
|
||||
EXPECT_EQ(240, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(0);
|
||||
CallPreProc(300, kAboveClippedThreshold);
|
||||
EXPECT_EQ(240, volume_.GetMicVolume());
|
||||
EXPECT_EQ(240, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(225, volume_.GetMicVolume());
|
||||
EXPECT_EQ(225, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, ClippingLoweringIsLimited) {
|
||||
@ -534,11 +524,11 @@ TEST_F(AgcManagerDirectTest, ClippingLoweringIsLimited) {
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
|
||||
EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(0);
|
||||
CallPreProc(1000, kAboveClippedThreshold);
|
||||
EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
|
||||
EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenEqualToLevel) {
|
||||
@ -546,12 +536,12 @@ TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenEqualToLevel) {
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(240, volume_.GetMicVolume());
|
||||
EXPECT_EQ(240, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
|
||||
CallProcess(10);
|
||||
EXPECT_EQ(240, volume_.GetMicVolume());
|
||||
EXPECT_EQ(240, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenHigherThanLevel) {
|
||||
@ -559,14 +549,14 @@ TEST_F(AgcManagerDirectTest, ClippingMaxIsRespectedWhenHigherThanLevel) {
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(185, volume_.GetMicVolume());
|
||||
EXPECT_EQ(185, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(240, volume_.GetMicVolume());
|
||||
EXPECT_EQ(240, manager_.stream_analog_level());
|
||||
CallProcess(10);
|
||||
EXPECT_EQ(240, volume_.GetMicVolume());
|
||||
EXPECT_EQ(240, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) {
|
||||
@ -574,7 +564,7 @@ TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) {
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(195, volume_.GetMicVolume());
|
||||
EXPECT_EQ(195, manager_.stream_analog_level());
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(11), Return(true)))
|
||||
@ -601,12 +591,12 @@ TEST_F(AgcManagerDirectTest, MaxCompressionIsIncreasedAfterClipping) {
|
||||
CallPreProc(300, kAboveClippedThreshold);
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(180, volume_.GetMicVolume());
|
||||
EXPECT_EQ(180, manager_.stream_analog_level());
|
||||
|
||||
CallPreProc(300, kAboveClippedThreshold);
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(kClippedMin, volume_.GetMicVolume());
|
||||
EXPECT_EQ(kClippedMin, manager_.stream_analog_level());
|
||||
|
||||
// Current level is now at the minimum, but the maximum allowed level still
|
||||
// has more to decrease.
|
||||
@ -643,41 +633,41 @@ TEST_F(AgcManagerDirectTest, UserCanRaiseVolumeAfterClipping) {
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(210, volume_.GetMicVolume());
|
||||
EXPECT_EQ(210, manager_.stream_analog_level());
|
||||
|
||||
// High enough error to trigger a volume check.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(14), Return(true)));
|
||||
// User changed the volume.
|
||||
volume_.SetMicVolume(250);
|
||||
manager_.set_stream_analog_level(250);
|
||||
EXPECT_CALL(*agc_, Reset()).Times(AtLeast(1));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(250, volume_.GetMicVolume());
|
||||
EXPECT_EQ(250, manager_.stream_analog_level());
|
||||
|
||||
// Move down...
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(-10), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(210, volume_.GetMicVolume());
|
||||
EXPECT_EQ(210, manager_.stream_analog_level());
|
||||
// And back up to the new max established by the user.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(40), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(250, volume_.GetMicVolume());
|
||||
EXPECT_EQ(250, manager_.stream_analog_level());
|
||||
// Will not move above new maximum.
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(30), Return(true)));
|
||||
CallProcess(1);
|
||||
EXPECT_EQ(250, volume_.GetMicVolume());
|
||||
EXPECT_EQ(250, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, ClippingDoesNotPullLowVolumeBackUp) {
|
||||
SetVolumeAndProcess(80);
|
||||
|
||||
EXPECT_CALL(*agc_, Reset()).Times(0);
|
||||
int initial_volume = volume_.GetMicVolume();
|
||||
int initial_volume = manager_.stream_analog_level();
|
||||
CallPreProc(1, kAboveClippedThreshold);
|
||||
EXPECT_EQ(initial_volume, volume_.GetMicVolume());
|
||||
EXPECT_EQ(initial_volume, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST_F(AgcManagerDirectTest, TakesNoActionOnZeroMicVolume) {
|
||||
@ -685,17 +675,15 @@ TEST_F(AgcManagerDirectTest, TakesNoActionOnZeroMicVolume) {
|
||||
|
||||
EXPECT_CALL(*agc_, GetRmsErrorDb(_))
|
||||
.WillRepeatedly(DoAll(SetArgPointee<0>(30), Return(true)));
|
||||
volume_.SetMicVolume(0);
|
||||
manager_.set_stream_analog_level(0);
|
||||
CallProcess(10);
|
||||
EXPECT_EQ(0, volume_.GetMicVolume());
|
||||
EXPECT_EQ(0, manager_.stream_analog_level());
|
||||
}
|
||||
|
||||
TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
|
||||
auto agc = std::unique_ptr<Agc>(new ::testing::NiceMock<MockAgc>());
|
||||
MockGainControl gctrl;
|
||||
TestVolumeCallbacks volume;
|
||||
|
||||
AgcManagerDirect manager(&gctrl, &volume, kInitialVolume, kClippedMin,
|
||||
AgcManagerDirect manager(kInitialVolume, kClippedMin,
|
||||
/* use agc2 level estimation */ false,
|
||||
/* disable digital adaptive */ true);
|
||||
|
||||
@ -705,18 +693,19 @@ TEST(AgcManagerDirectStandaloneTest, DisableDigitalDisablesDigital) {
|
||||
EXPECT_CALL(gctrl, enable_limiter(false));
|
||||
|
||||
manager.Initialize();
|
||||
manager.ConfigureGainControl(&gctrl);
|
||||
}
|
||||
|
||||
TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
|
||||
auto agc_man = std::unique_ptr<AgcManagerDirect>(new AgcManagerDirect(
|
||||
nullptr, nullptr, kInitialVolume, kClippedMin, true, true));
|
||||
auto agc_man = std::unique_ptr<AgcManagerDirect>(
|
||||
new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
|
||||
EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
|
||||
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
|
||||
{
|
||||
test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Disabled/");
|
||||
agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume,
|
||||
kClippedMin, true, true));
|
||||
agc_man.reset(
|
||||
new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
|
||||
EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
|
||||
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
|
||||
}
|
||||
@ -724,16 +713,16 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
|
||||
// Valid range of field-trial parameter is [0,255].
|
||||
test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-256/");
|
||||
agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume,
|
||||
kClippedMin, true, true));
|
||||
agc_man.reset(
|
||||
new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
|
||||
EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
|
||||
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
|
||||
}
|
||||
{
|
||||
test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled--1/");
|
||||
agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume,
|
||||
kClippedMin, true, true));
|
||||
agc_man.reset(
|
||||
new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
|
||||
EXPECT_EQ(agc_man->min_mic_level(), kMinMicLevel);
|
||||
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
|
||||
}
|
||||
@ -743,8 +732,8 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
|
||||
// be changed.
|
||||
test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
|
||||
agc_man.reset(new AgcManagerDirect(nullptr, nullptr, kInitialVolume,
|
||||
kClippedMin, true, true));
|
||||
agc_man.reset(
|
||||
new AgcManagerDirect(kInitialVolume, kClippedMin, true, true));
|
||||
EXPECT_EQ(agc_man->min_mic_level(), 50);
|
||||
EXPECT_EQ(agc_man->startup_min_level(), kInitialVolume);
|
||||
}
|
||||
@ -754,8 +743,7 @@ TEST(AgcManagerDirectStandaloneTest, AgcMinMicLevelExperiment) {
|
||||
// level set by the experiment.
|
||||
test::ScopedFieldTrials field_trial(
|
||||
"WebRTC-Audio-AgcMinMicLevelExperiment/Enabled-50/");
|
||||
agc_man.reset(
|
||||
new AgcManagerDirect(nullptr, nullptr, 30, kClippedMin, true, true));
|
||||
agc_man.reset(new AgcManagerDirect(30, kClippedMin, true, true));
|
||||
EXPECT_EQ(agc_man->min_mic_level(), 50);
|
||||
EXPECT_EQ(agc_man->startup_min_level(), 50);
|
||||
}
|
||||
|
||||
@ -323,18 +323,20 @@ AudioProcessingImpl::AudioProcessingImpl(
|
||||
submodules_(std::move(capture_post_processor),
|
||||
std::move(render_pre_processor),
|
||||
std::move(echo_detector),
|
||||
std::move(capture_analyzer)),
|
||||
constants_(config.Get<ExperimentalAgc>().startup_min_volume,
|
||||
config.Get<ExperimentalAgc>().clipped_level_min,
|
||||
std::move(capture_analyzer),
|
||||
config.Get<ExperimentalAgc>().startup_min_volume,
|
||||
config.Get<ExperimentalAgc>().clipped_level_min,
|
||||
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
|
||||
/* enabled= */ false,
|
||||
/* enabled_agc2_level_estimator= */ false,
|
||||
/* digital_adaptive_disabled= */ false,
|
||||
/* enabled= */ false,
|
||||
/* enabled_agc2_level_estimator= */ false,
|
||||
/* digital_adaptive_disabled= */ false
|
||||
#else
|
||||
config.Get<ExperimentalAgc>().enabled,
|
||||
config.Get<ExperimentalAgc>().enabled_agc2_level_estimator,
|
||||
config.Get<ExperimentalAgc>().digital_adaptive_disabled,
|
||||
config.Get<ExperimentalAgc>().enabled,
|
||||
config.Get<ExperimentalAgc>().enabled_agc2_level_estimator,
|
||||
config.Get<ExperimentalAgc>().digital_adaptive_disabled
|
||||
#endif
|
||||
),
|
||||
constants_(config.Get<ExperimentalAgc>().clipped_level_min,
|
||||
!field_trial::IsEnabled(
|
||||
"WebRTC-ApmExperimentalMultiChannelRenderKillSwitch"),
|
||||
!field_trial::IsEnabled(
|
||||
@ -359,8 +361,6 @@ AudioProcessingImpl::AudioProcessingImpl(
|
||||
static_cast<bool>(echo_control_factory_);
|
||||
|
||||
submodules_.gain_control.reset(new GainControlImpl());
|
||||
submodules_.gain_control_for_experimental_agc.reset(
|
||||
new GainControlForExperimentalAgc(submodules_.gain_control.get()));
|
||||
|
||||
// If no echo detector is injected, use the ResidualEchoDetector.
|
||||
if (!submodules_.echo_detector) {
|
||||
@ -375,13 +375,7 @@ AudioProcessingImpl::AudioProcessingImpl(
|
||||
SetExtraOptions(config);
|
||||
}
|
||||
|
||||
AudioProcessingImpl::~AudioProcessingImpl() {
|
||||
// Depends on gain_control_ and
|
||||
// submodules_.gain_control_for_experimental_agc.
|
||||
submodules_.agc_manager.reset();
|
||||
// Depends on gain_control_.
|
||||
submodules_.gain_control_for_experimental_agc.reset();
|
||||
}
|
||||
AudioProcessingImpl::~AudioProcessingImpl() = default;
|
||||
|
||||
int AudioProcessingImpl::Initialize() {
|
||||
// Run in a single-threaded manner during initialization.
|
||||
@ -484,18 +478,11 @@ int AudioProcessingImpl::InitializeLocked() {
|
||||
|
||||
submodules_.gain_control->Initialize(num_proc_channels(),
|
||||
proc_sample_rate_hz());
|
||||
if (constants_.use_experimental_agc) {
|
||||
if (!submodules_.agc_manager.get()) {
|
||||
submodules_.agc_manager.reset(new AgcManagerDirect(
|
||||
submodules_.gain_control.get(),
|
||||
submodules_.gain_control_for_experimental_agc.get(),
|
||||
constants_.agc_startup_min_volume, constants_.agc_clipped_level_min,
|
||||
constants_.use_experimental_agc_agc2_level_estimation,
|
||||
constants_.use_experimental_agc_agc2_digital_adaptive));
|
||||
}
|
||||
if (submodules_.agc_manager) {
|
||||
submodules_.agc_manager->Initialize();
|
||||
submodules_.agc_manager->ConfigureGainControl(
|
||||
submodules_.gain_control.get());
|
||||
submodules_.agc_manager->SetCaptureMuted(capture_.output_will_be_muted);
|
||||
submodules_.gain_control_for_experimental_agc->Initialize();
|
||||
}
|
||||
InitializeTransient();
|
||||
InitializeHighPassFilter();
|
||||
@ -695,34 +682,25 @@ void AudioProcessingImpl::ApplyConfig(const AudioProcessing::Config& config) {
|
||||
|
||||
void AudioProcessingImpl::ApplyAgc1Config(
|
||||
const Config::GainController1& config) {
|
||||
GainControl* agc = agc1();
|
||||
int error = agc->Enable(config.enabled);
|
||||
int error = submodules_.gain_control->Enable(config.enabled);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = agc->set_mode(Agc1ConfigModeToInterfaceMode(config.mode));
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = agc->set_target_level_dbfs(config.target_level_dbfs);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = agc->set_compression_gain_db(config.compression_gain_db);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = agc->enable_limiter(config.enable_limiter);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = agc->set_analog_level_limits(config.analog_level_minimum,
|
||||
config.analog_level_maximum);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
}
|
||||
|
||||
GainControl* AudioProcessingImpl::agc1() {
|
||||
if (constants_.use_experimental_agc) {
|
||||
return submodules_.gain_control_for_experimental_agc.get();
|
||||
if (!submodules_.agc_manager) {
|
||||
error = submodules_.gain_control->set_mode(
|
||||
Agc1ConfigModeToInterfaceMode(config.mode));
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = submodules_.gain_control->set_target_level_dbfs(
|
||||
config.target_level_dbfs);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = submodules_.gain_control->set_compression_gain_db(
|
||||
config.compression_gain_db);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = submodules_.gain_control->enable_limiter(config.enable_limiter);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
error = submodules_.gain_control->set_analog_level_limits(
|
||||
config.analog_level_minimum, config.analog_level_maximum);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
}
|
||||
return submodules_.gain_control.get();
|
||||
}
|
||||
|
||||
const GainControl* AudioProcessingImpl::agc1() const {
|
||||
if (constants_.use_experimental_agc) {
|
||||
return submodules_.gain_control_for_experimental_agc.get();
|
||||
}
|
||||
return submodules_.gain_control.get();
|
||||
}
|
||||
|
||||
void AudioProcessingImpl::SetExtraOptions(const webrtc::Config& config) {
|
||||
@ -926,12 +904,15 @@ void AudioProcessingImpl::HandleCaptureRuntimeSettings() {
|
||||
// TODO(bugs.chromium.org/9138): Log setting handling by Aec Dump.
|
||||
break;
|
||||
case RuntimeSetting::Type::kCaptureCompressionGain: {
|
||||
float value;
|
||||
setting.GetFloat(&value);
|
||||
int int_value = static_cast<int>(value + .5f);
|
||||
config_.gain_controller1.compression_gain_db = int_value;
|
||||
int error = agc1()->set_compression_gain_db(int_value);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
if (!submodules_.agc_manager) {
|
||||
float value;
|
||||
setting.GetFloat(&value);
|
||||
int int_value = static_cast<int>(value + .5f);
|
||||
config_.gain_controller1.compression_gain_db = int_value;
|
||||
int error =
|
||||
submodules_.gain_control->set_compression_gain_db(int_value);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RuntimeSetting::Type::kCaptureFixedPostGain: {
|
||||
@ -1023,7 +1004,7 @@ void AudioProcessingImpl::QueueBandedRenderAudio(AudioBuffer* audio) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!constants_.use_experimental_agc) {
|
||||
if (!submodules_.agc_manager) {
|
||||
GainControlImpl::PackRenderAudioBuffer(audio, &agc_render_queue_buffer_);
|
||||
// Insert the samples into the queue.
|
||||
if (!agc_render_signal_queue_->Insert(&agc_render_queue_buffer_)) {
|
||||
@ -1255,7 +1236,7 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
||||
|
||||
if (submodules_.echo_controller) {
|
||||
// Detect and flag any change in the analog gain.
|
||||
int analog_mic_level = agc1()->stream_analog_level();
|
||||
int analog_mic_level = recommended_stream_analog_level();
|
||||
capture_.echo_path_gain_change =
|
||||
capture_.prev_analog_mic_level != analog_mic_level &&
|
||||
capture_.prev_analog_mic_level != -1;
|
||||
@ -1281,8 +1262,7 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
||||
submodules_.echo_controller->AnalyzeCapture(capture_buffer);
|
||||
}
|
||||
|
||||
if (constants_.use_experimental_agc &&
|
||||
submodules_.gain_control->is_enabled()) {
|
||||
if (submodules_.agc_manager && submodules_.gain_control->is_enabled()) {
|
||||
submodules_.agc_manager->AnalyzePreProcess(
|
||||
capture_buffer->channels_const(), capture_buffer->num_channels(),
|
||||
capture_nonlocked_.capture_processing_format.num_frames());
|
||||
@ -1370,11 +1350,11 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
||||
capture_.stats.voice_detected = absl::nullopt;
|
||||
}
|
||||
|
||||
if (constants_.use_experimental_agc &&
|
||||
submodules_.gain_control->is_enabled()) {
|
||||
if (submodules_.agc_manager && submodules_.gain_control->is_enabled()) {
|
||||
submodules_.agc_manager->Process(
|
||||
capture_buffer->split_bands_const_f(0)[kBand0To8kHz],
|
||||
capture_buffer->num_frames_per_band(), capture_nonlocked_.split_rate);
|
||||
capture_buffer->num_frames_per_band(), capture_nonlocked_.split_rate,
|
||||
submodules_.gain_control.get());
|
||||
}
|
||||
// TODO(peah): Add reporting from AEC3 whether there is echo.
|
||||
RETURN_ON_ERR(submodules_.gain_control->ProcessCaptureAudio(
|
||||
@ -1428,7 +1408,7 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
||||
|
||||
if (config_.gain_controller2.enabled) {
|
||||
submodules_.gain_controller2->NotifyAnalogLevel(
|
||||
agc1()->stream_analog_level());
|
||||
recommended_stream_analog_level());
|
||||
submodules_.gain_controller2->Process(capture_buffer);
|
||||
}
|
||||
|
||||
@ -1455,6 +1435,12 @@ int AudioProcessingImpl::ProcessCaptureStreamLocked() {
|
||||
levels.peak, 1, RmsLevel::kMinLevelDb, 64);
|
||||
}
|
||||
|
||||
if (submodules_.agc_manager) {
|
||||
int level = recommended_stream_analog_level();
|
||||
data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1,
|
||||
&level);
|
||||
}
|
||||
|
||||
capture_.was_stream_delay_set = false;
|
||||
return kNoError;
|
||||
}
|
||||
@ -1678,13 +1664,23 @@ int AudioProcessingImpl::delay_offset_ms() const {
|
||||
|
||||
void AudioProcessingImpl::set_stream_analog_level(int level) {
|
||||
rtc::CritScope cs_capture(&crit_capture_);
|
||||
int error = agc1()->set_stream_analog_level(level);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
|
||||
if (submodules_.agc_manager) {
|
||||
submodules_.agc_manager->set_stream_analog_level(level);
|
||||
data_dumper_->DumpRaw("experimental_gain_control_set_stream_analog_level",
|
||||
1, &level);
|
||||
} else {
|
||||
int error = submodules_.gain_control->set_stream_analog_level(level);
|
||||
RTC_DCHECK_EQ(kNoError, error);
|
||||
}
|
||||
}
|
||||
|
||||
int AudioProcessingImpl::recommended_stream_analog_level() const {
|
||||
rtc::CritScope cs_capture(&crit_capture_);
|
||||
return agc1()->stream_analog_level();
|
||||
if (submodules_.agc_manager) {
|
||||
return submodules_.agc_manager->stream_analog_level();
|
||||
}
|
||||
return submodules_.gain_control->stream_analog_level();
|
||||
}
|
||||
|
||||
void AudioProcessingImpl::AttachAecDump(std::unique_ptr<AecDump> aec_dump) {
|
||||
@ -2050,7 +2046,7 @@ void AudioProcessingImpl::WriteAecDumpConfigMessage(bool forced) {
|
||||
apm_config.agc_mode = static_cast<int>(submodules_.gain_control->mode());
|
||||
apm_config.agc_limiter_enabled =
|
||||
submodules_.gain_control->is_limiter_enabled();
|
||||
apm_config.noise_robust_agc_enabled = constants_.use_experimental_agc;
|
||||
apm_config.noise_robust_agc_enabled = !!submodules_.agc_manager;
|
||||
|
||||
apm_config.hpf_enabled = config_.high_pass_filter.enabled;
|
||||
|
||||
@ -2120,7 +2116,7 @@ void AudioProcessingImpl::RecordAudioProcessingState() {
|
||||
submodules_.echo_cancellation
|
||||
? submodules_.echo_cancellation->stream_drift_samples()
|
||||
: 0;
|
||||
audio_proc_state.level = agc1()->stream_analog_level();
|
||||
audio_proc_state.level = recommended_stream_analog_level();
|
||||
audio_proc_state.keypress = capture_.key_pressed;
|
||||
aec_dump_->AddAudioProcessingState(audio_proc_state);
|
||||
}
|
||||
|
||||
@ -22,7 +22,6 @@
|
||||
#include "modules/audio_processing/audio_buffer.h"
|
||||
#include "modules/audio_processing/echo_cancellation_impl.h"
|
||||
#include "modules/audio_processing/echo_control_mobile_impl.h"
|
||||
#include "modules/audio_processing/gain_control_for_experimental_agc.h"
|
||||
#include "modules/audio_processing/gain_control_impl.h"
|
||||
#include "modules/audio_processing/gain_controller2.h"
|
||||
#include "modules/audio_processing/high_pass_filter.h"
|
||||
@ -254,11 +253,6 @@ class AudioProcessingImpl : public AudioProcessing {
|
||||
void ApplyAgc1Config(const Config::GainController1& agc_config)
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_capture_);
|
||||
|
||||
// Returns a direct pointer to the AGC1 submodule: either a GainControlImpl
|
||||
// or GainControlForExperimentalAgc instance.
|
||||
GainControl* agc1();
|
||||
const GainControl* agc1() const;
|
||||
|
||||
void EmptyQueuedRenderAudio();
|
||||
void AllocateRenderQueue()
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_render_, crit_capture_);
|
||||
@ -331,16 +325,26 @@ class AudioProcessingImpl : public AudioProcessing {
|
||||
Submodules(std::unique_ptr<CustomProcessing> capture_post_processor,
|
||||
std::unique_ptr<CustomProcessing> render_pre_processor,
|
||||
rtc::scoped_refptr<EchoDetector> echo_detector,
|
||||
std::unique_ptr<CustomAudioAnalyzer> capture_analyzer)
|
||||
std::unique_ptr<CustomAudioAnalyzer> capture_analyzer,
|
||||
int agc_startup_min_volume,
|
||||
int agc_clipped_level_min,
|
||||
bool use_experimental_agc,
|
||||
bool use_experimental_agc_agc2_level_estimation,
|
||||
bool use_experimental_agc_agc2_digital_adaptive)
|
||||
: echo_detector(std::move(echo_detector)),
|
||||
capture_post_processor(std::move(capture_post_processor)),
|
||||
render_pre_processor(std::move(render_pre_processor)),
|
||||
capture_analyzer(std::move(capture_analyzer)) {}
|
||||
capture_analyzer(std::move(capture_analyzer)) {
|
||||
if (use_experimental_agc) {
|
||||
agc_manager = std::make_unique<AgcManagerDirect>(
|
||||
agc_startup_min_volume, agc_clipped_level_min,
|
||||
use_experimental_agc_agc2_level_estimation,
|
||||
use_experimental_agc_agc2_digital_adaptive);
|
||||
}
|
||||
}
|
||||
// Accessed internally from capture or during initialization.
|
||||
std::unique_ptr<AgcManagerDirect> agc_manager;
|
||||
std::unique_ptr<GainControlImpl> gain_control;
|
||||
std::unique_ptr<GainControlForExperimentalAgc>
|
||||
gain_control_for_experimental_agc;
|
||||
std::unique_ptr<GainController2> gain_controller2;
|
||||
std::unique_ptr<HighPassFilter> high_pass_filter;
|
||||
rtc::scoped_refptr<EchoDetector> echo_detector;
|
||||
@ -377,29 +381,15 @@ class AudioProcessingImpl : public AudioProcessing {
|
||||
|
||||
// APM constants.
|
||||
const struct ApmConstants {
|
||||
ApmConstants(int agc_startup_min_volume,
|
||||
int agc_clipped_level_min,
|
||||
bool use_experimental_agc,
|
||||
bool use_experimental_agc_agc2_level_estimation,
|
||||
bool use_experimental_agc_agc2_digital_adaptive,
|
||||
ApmConstants(int agc_clipped_level_min,
|
||||
bool experimental_multi_channel_render_support,
|
||||
bool experimental_multi_channel_capture_support)
|
||||
: agc_startup_min_volume(agc_startup_min_volume),
|
||||
agc_clipped_level_min(agc_clipped_level_min),
|
||||
use_experimental_agc(use_experimental_agc),
|
||||
use_experimental_agc_agc2_level_estimation(
|
||||
use_experimental_agc_agc2_level_estimation),
|
||||
use_experimental_agc_agc2_digital_adaptive(
|
||||
use_experimental_agc_agc2_digital_adaptive),
|
||||
: agc_clipped_level_min(agc_clipped_level_min),
|
||||
experimental_multi_channel_render_support(
|
||||
experimental_multi_channel_render_support),
|
||||
experimental_multi_channel_capture_support(
|
||||
experimental_multi_channel_capture_support) {}
|
||||
int agc_startup_min_volume;
|
||||
int agc_clipped_level_min;
|
||||
bool use_experimental_agc;
|
||||
bool use_experimental_agc_agc2_level_estimation;
|
||||
bool use_experimental_agc_agc2_digital_adaptive;
|
||||
bool experimental_multi_channel_render_support;
|
||||
bool experimental_multi_channel_capture_support;
|
||||
} constants_;
|
||||
|
||||
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/audio_processing/gain_control_for_experimental_agc.h"
|
||||
|
||||
#include "modules/audio_processing/include/audio_processing.h"
|
||||
#include "modules/audio_processing/logging/apm_data_dumper.h"
|
||||
#include "rtc_base/atomic_ops.h"
|
||||
#include "rtc_base/critical_section.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
int GainControlForExperimentalAgc::instance_counter_ = 0;
|
||||
|
||||
GainControlForExperimentalAgc::GainControlForExperimentalAgc(
|
||||
GainControl* gain_control)
|
||||
: data_dumper_(
|
||||
new ApmDataDumper(rtc::AtomicOps::Increment(&instance_counter_))),
|
||||
real_gain_control_(gain_control),
|
||||
volume_(0) {}
|
||||
|
||||
GainControlForExperimentalAgc::~GainControlForExperimentalAgc() = default;
|
||||
|
||||
int GainControlForExperimentalAgc::Enable(bool enable) {
|
||||
return real_gain_control_->Enable(enable);
|
||||
}
|
||||
|
||||
bool GainControlForExperimentalAgc::is_enabled() const {
|
||||
return real_gain_control_->is_enabled();
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::set_stream_analog_level(int level) {
|
||||
data_dumper_->DumpRaw("experimental_gain_control_set_stream_analog_level", 1,
|
||||
&level);
|
||||
do_log_level_ = true;
|
||||
volume_ = level;
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::stream_analog_level() const {
|
||||
if (do_log_level_) {
|
||||
data_dumper_->DumpRaw("experimental_gain_control_stream_analog_level", 1,
|
||||
&volume_);
|
||||
do_log_level_ = false;
|
||||
}
|
||||
return volume_;
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::set_mode(Mode mode) {
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
GainControl::Mode GainControlForExperimentalAgc::mode() const {
|
||||
return GainControl::kAdaptiveAnalog;
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::set_target_level_dbfs(int level) {
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::target_level_dbfs() const {
|
||||
return real_gain_control_->target_level_dbfs();
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::set_compression_gain_db(int gain) {
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::compression_gain_db() const {
|
||||
return real_gain_control_->compression_gain_db();
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::enable_limiter(bool enable) {
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
bool GainControlForExperimentalAgc::is_limiter_enabled() const {
|
||||
return real_gain_control_->is_limiter_enabled();
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::set_analog_level_limits(int minimum,
|
||||
int maximum) {
|
||||
return AudioProcessing::kNoError;
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::analog_level_minimum() const {
|
||||
return real_gain_control_->analog_level_minimum();
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::analog_level_maximum() const {
|
||||
return real_gain_control_->analog_level_maximum();
|
||||
}
|
||||
|
||||
bool GainControlForExperimentalAgc::stream_is_saturated() const {
|
||||
return real_gain_control_->stream_is_saturated();
|
||||
}
|
||||
|
||||
void GainControlForExperimentalAgc::SetMicVolume(int volume) {
|
||||
volume_ = volume;
|
||||
}
|
||||
|
||||
int GainControlForExperimentalAgc::GetMicVolume() {
|
||||
return volume_;
|
||||
}
|
||||
|
||||
void GainControlForExperimentalAgc::Initialize() {
|
||||
data_dumper_->InitiateNewSetOfRecordings();
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_
|
||||
#define MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_
|
||||
|
||||
#include "modules/audio_processing/agc/agc_manager_direct.h"
|
||||
#include "modules/audio_processing/agc/gain_control.h"
|
||||
#include "rtc_base/thread_checker.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class ApmDataDumper;
|
||||
|
||||
// This class has two main purposes:
|
||||
//
|
||||
// 1) It is returned instead of the real GainControl after the new AGC has been
|
||||
// enabled in order to prevent an outside user from overriding compression
|
||||
// settings. It doesn't do anything in its implementation, except for
|
||||
// delegating the const methods and Enable calls to the real GainControl, so
|
||||
// AGC can still be disabled.
|
||||
//
|
||||
// 2) It is injected into AgcManagerDirect and implements volume callbacks for
|
||||
// getting and setting the volume level. It just caches this value to be used
|
||||
// in VoiceEngine later.
|
||||
class GainControlForExperimentalAgc : public GainControl,
|
||||
public VolumeCallbacks {
|
||||
public:
|
||||
explicit GainControlForExperimentalAgc(GainControl* gain_control);
|
||||
GainControlForExperimentalAgc(const GainControlForExperimentalAgc&) = delete;
|
||||
GainControlForExperimentalAgc& operator=(
|
||||
const GainControlForExperimentalAgc&) = delete;
|
||||
|
||||
~GainControlForExperimentalAgc() override;
|
||||
|
||||
// GainControl implementation.
|
||||
int Enable(bool enable) override;
|
||||
bool is_enabled() const override;
|
||||
int set_stream_analog_level(int level) override;
|
||||
int stream_analog_level() const override;
|
||||
int set_mode(Mode mode) override;
|
||||
Mode mode() const override;
|
||||
int set_target_level_dbfs(int level) override;
|
||||
int target_level_dbfs() const override;
|
||||
int set_compression_gain_db(int gain) override;
|
||||
int compression_gain_db() const override;
|
||||
int enable_limiter(bool enable) override;
|
||||
bool is_limiter_enabled() const override;
|
||||
int set_analog_level_limits(int minimum, int maximum) override;
|
||||
int analog_level_minimum() const override;
|
||||
int analog_level_maximum() const override;
|
||||
bool stream_is_saturated() const override;
|
||||
|
||||
// VolumeCallbacks implementation.
|
||||
void SetMicVolume(int volume) override;
|
||||
int GetMicVolume() override;
|
||||
|
||||
void Initialize();
|
||||
|
||||
private:
|
||||
std::unique_ptr<ApmDataDumper> data_dumper_;
|
||||
GainControl* real_gain_control_;
|
||||
int volume_;
|
||||
mutable bool do_log_level_ = true;
|
||||
static int instance_counter_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_AUDIO_PROCESSING_GAIN_CONTROL_FOR_EXPERIMENTAL_AGC_H_
|
||||
@ -49,21 +49,20 @@ class GainControlImpl : public GainControl {
|
||||
int stream_analog_level() const override;
|
||||
bool is_limiter_enabled() const override;
|
||||
Mode mode() const override;
|
||||
|
||||
int Enable(bool enable) override;
|
||||
int set_mode(Mode mode) override;
|
||||
int compression_gain_db() const override;
|
||||
int set_analog_level_limits(int minimum, int maximum) override;
|
||||
int set_compression_gain_db(int gain) override;
|
||||
int set_target_level_dbfs(int level) override;
|
||||
int enable_limiter(bool enable) override;
|
||||
int set_stream_analog_level(int level) override;
|
||||
|
||||
private:
|
||||
class GainController;
|
||||
|
||||
// GainControl implementation.
|
||||
int Enable(bool enable) override;
|
||||
int set_stream_analog_level(int level) override;
|
||||
int set_mode(Mode mode) override;
|
||||
int set_target_level_dbfs(int level) override;
|
||||
int target_level_dbfs() const override;
|
||||
int set_compression_gain_db(int gain) override;
|
||||
int enable_limiter(bool enable) override;
|
||||
int set_analog_level_limits(int minimum, int maximum) override;
|
||||
int analog_level_minimum() const override;
|
||||
int analog_level_maximum() const override;
|
||||
bool stream_is_saturated() const override;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user