AGC2: retuning and large refactoring
- Bug fix: the desired initial gain quickly dropped to 0 dB hence
starting a call with a too low level
- New tuning to make AGC2 more robust to VAD mistakes
- Smarter max gain increase speed: to deal with an increased threshold
of adjacent speech frames, the gain applier temporarily allows a
faster gain increase to deal with a longer time spent waiting for
enough speech frames in a row to be observed
- Saturation protector isolated from `AdaptiveModeLevelEstimator` to
simplify the unit tests for the latter (non bit-exact change)
- AGC2 adaptive digital config: unnecessary params deprecated
- Code readability improvements
- Data dumps clean-up and better naming
Bug: webrtc:7494
Change-Id: I4e36059bdf2566cc2a7e1a7e95b7430ba9ae9844
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/215140
Commit-Queue: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Jesus de Vicente Pena <devicentepena@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33736}
diff --git a/modules/audio_processing/gain_controller2_unittest.cc b/modules/audio_processing/gain_controller2_unittest.cc
index 274c821..815d58e 100644
--- a/modules/audio_processing/gain_controller2_unittest.cc
+++ b/modules/audio_processing/gain_controller2_unittest.cc
@@ -11,6 +11,7 @@
#include "modules/audio_processing/gain_controller2.h"
#include <algorithm>
+#include <cmath>
#include <memory>
#include "api/array_view.h"
@@ -68,7 +69,8 @@
return agc2;
}
-float GainAfterProcessingFile(GainController2* gain_controller) {
+float GainDbAfterProcessingFile(GainController2& gain_controller,
+ int max_duration_ms) {
// Set up an AudioBuffer to be filled from the speech file.
constexpr size_t kStereo = 2u;
const StreamConfig capture_config(AudioProcessing::kSampleRate48kHz, kStereo,
@@ -82,24 +84,29 @@
std::vector<float> capture_input(capture_config.num_frames() *
capture_config.num_channels());
- // The file should contain at least this many frames. Every iteration, we put
- // a frame through the gain controller.
- const int kNumFramesToProcess = 100;
- for (int frame_no = 0; frame_no < kNumFramesToProcess; ++frame_no) {
+ // Process the input file which must be long enough to cover
+ // `max_duration_ms`.
+ RTC_DCHECK_GT(max_duration_ms, 0);
+ const int num_frames = rtc::CheckedDivExact(max_duration_ms, 10);
+ for (int i = 0; i < num_frames; ++i) {
ReadFloatSamplesFromStereoFile(capture_config.num_frames(),
capture_config.num_channels(), &capture_file,
capture_input);
-
test::CopyVectorToAudioBuffer(capture_config, capture_input, &ab);
- gain_controller->Process(&ab);
+ gain_controller.Process(&ab);
}
- // Send in a last frame with values constant 1 (It's low enough to detect high
- // gain, and for ease of computation). The applied gain is the result.
+ // Send in a last frame with minimum dBFS level.
constexpr float sample_value = 1.f;
SetAudioBufferSamples(sample_value, &ab);
- gain_controller->Process(&ab);
- return ab.channels()[0][0];
+ gain_controller.Process(&ab);
+ // Measure the RMS level after processing.
+ float rms = 0.0f;
+ for (size_t i = 0; i < capture_config.num_frames(); ++i) {
+ rms += ab.channels()[0][i] * ab.channels()[0][i];
+ }
+ // Return the applied gain in dB.
+ return 20.0f * std::log10(std::sqrt(rms / capture_config.num_frames()));
}
} // namespace
@@ -324,34 +331,20 @@
48000,
true)));
-TEST(GainController2, UsageSaturationMargin) {
+// Checks that the gain applied at the end of a PCM samples file is close to the
+// expected value.
+TEST(GainController2, CheckGainAdaptiveDigital) {
+ constexpr float kExpectedGainDb = 4.3f;
+ constexpr float kToleranceDb = 0.5f;
GainController2 gain_controller2;
gain_controller2.Initialize(AudioProcessing::kSampleRate48kHz);
-
AudioProcessing::Config::GainController2 config;
- // Check that samples are not amplified as much when extra margin is
- // high. They should not be amplified at all, but only after convergence. GC2
- // starts with a gain, and it takes time until it's down to 0 dB.
config.fixed_digital.gain_db = 0.f;
config.adaptive_digital.enabled = true;
- config.adaptive_digital.extra_saturation_margin_db = 50.f;
gain_controller2.ApplyConfig(config);
-
- EXPECT_LT(GainAfterProcessingFile(&gain_controller2), 2.f);
-}
-
-TEST(GainController2, UsageNoSaturationMargin) {
- GainController2 gain_controller2;
- gain_controller2.Initialize(AudioProcessing::kSampleRate48kHz);
-
- AudioProcessing::Config::GainController2 config;
- // Check that some gain is applied if there is no margin.
- config.fixed_digital.gain_db = 0.f;
- config.adaptive_digital.enabled = true;
- config.adaptive_digital.extra_saturation_margin_db = 0.f;
- gain_controller2.ApplyConfig(config);
-
- EXPECT_GT(GainAfterProcessingFile(&gain_controller2), 1.9f);
+ EXPECT_NEAR(
+ GainDbAfterProcessingFile(gain_controller2, /*max_duration_ms=*/2000),
+ kExpectedGainDb, kToleranceDb);
}
} // namespace test