blob: eaf0859d3a40b7bb60e59abc5336a4b40ecccbea [file] [log] [blame]
alessiob3ec96df2017-05-22 06:57:06 -07001/*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/audio_processing/gain_controller2.h"
12
Alessio Bazzica270f7b52017-10-13 11:05:17 +020013#include <algorithm>
Alessio Bazzica980c4602021-04-14 19:09:17 +020014#include <cmath>
Mirko Bonadei317a1f02019-09-17 17:06:18 +020015#include <memory>
Alessio Bazzica6ee97342021-09-27 17:06:40 +020016#include <numeric>
Alessio Bazzica38901042021-10-14 12:14:21 +020017#include <tuple>
alessiob3ec96df2017-05-22 06:57:06 -070018
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "api/array_view.h"
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +010020#include "modules/audio_processing/agc2/agc2_testing_common.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/audio_processing/audio_buffer.h"
Alex Loiko5e784612018-11-01 14:51:56 +010022#include "modules/audio_processing/test/audio_buffer_tools.h"
23#include "modules/audio_processing/test/bitexactness_tools.h"
Alessio Bazzica270f7b52017-10-13 11:05:17 +020024#include "rtc_base/checks.h"
Hanna Silend7cfbe32022-11-02 19:12:20 +010025#include "test/gmock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "test/gtest.h"
alessiob3ec96df2017-05-22 06:57:06 -070027
28namespace webrtc {
29namespace test {
alessiob3ec96df2017-05-22 06:57:06 -070030namespace {
31
Hanna Silend7cfbe32022-11-02 19:12:20 +010032using ::testing::Eq;
33using ::testing::Optional;
34
Alessio Bazzica38901042021-10-14 12:14:21 +020035using Agc2Config = AudioProcessing::Config::GainController2;
36
Alessio Bazzica6ee97342021-09-27 17:06:40 +020037// Sets all the samples in `ab` to `value`.
38void SetAudioBufferSamples(float value, AudioBuffer& ab) {
39 for (size_t k = 0; k < ab.num_channels(); ++k) {
40 std::fill(ab.channels()[k], ab.channels()[k] + ab.num_frames(), value);
alessiob3ec96df2017-05-22 06:57:06 -070041 }
42}
43
Alessio Bazzica6ee97342021-09-27 17:06:40 +020044float RunAgc2WithConstantInput(GainController2& agc2,
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +010045 float input_level,
Alessio Bazzica6ee97342021-09-27 17:06:40 +020046 int num_frames,
Hanna Silend7cfbe32022-11-02 19:12:20 +010047 int sample_rate_hz,
48 int num_channels = 1,
49 int applied_initial_volume = 0) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +020050 const int num_samples = rtc::CheckedDivExact(sample_rate_hz, 100);
Hanna Silend7cfbe32022-11-02 19:12:20 +010051 AudioBuffer ab(sample_rate_hz, num_channels, sample_rate_hz, num_channels,
52 sample_rate_hz, num_channels);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +010053
54 // Give time to the level estimator to converge.
Alessio Bazzica6ee97342021-09-27 17:06:40 +020055 for (int i = 0; i < num_frames + 1; ++i) {
56 SetAudioBufferSamples(input_level, ab);
Hanna Silend7cfbe32022-11-02 19:12:20 +010057 const auto applied_volume = agc2.GetRecommendedInputVolume();
58 agc2.Analyze(i > 0 && applied_volume.has_value() ? *applied_volume
59 : applied_initial_volume,
60 ab);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +020061 agc2.Process(/*speech_probability=*/absl::nullopt,
62 /*input_volume_changed=*/false, &ab);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +010063 }
64
65 // Return the last sample from the last processed frame.
Per Ã…hgrend47941e2019-08-22 11:51:13 +020066 return ab.channels()[0][num_samples - 1];
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +010067}
68
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +010069std::unique_ptr<GainController2> CreateAgc2FixedDigitalMode(
70 float fixed_gain_db,
Alessio Bazzica6ee97342021-09-27 17:06:40 +020071 int sample_rate_hz) {
Alessio Bazzica38901042021-10-14 12:14:21 +020072 Agc2Config config;
73 config.adaptive_digital.enabled = false;
74 config.fixed_digital.gain_db = fixed_gain_db;
75 EXPECT_TRUE(GainController2::Validate(config));
76 return std::make_unique<GainController2>(config, sample_rate_hz,
Hanna Silen0c1ad292022-06-16 16:35:45 +020077 /*num_channels=*/1,
78 /*use_internal_vad=*/true);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +010079}
80
alessiob3ec96df2017-05-22 06:57:06 -070081} // namespace
82
Alessio Bazzica0c83e152020-10-14 12:49:54 +020083TEST(GainController2, CheckDefaultConfig) {
Alessio Bazzica38901042021-10-14 12:14:21 +020084 Agc2Config config;
Alessio Bazzica270f7b52017-10-13 11:05:17 +020085 EXPECT_TRUE(GainController2::Validate(config));
alessiob3ec96df2017-05-22 06:57:06 -070086}
87
Alessio Bazzica0c83e152020-10-14 12:49:54 +020088TEST(GainController2, CheckFixedDigitalConfig) {
Alessio Bazzica38901042021-10-14 12:14:21 +020089 Agc2Config config;
Alessio Bazzica0c83e152020-10-14 12:49:54 +020090 // Attenuation is not allowed.
Alessio Bazzica6ee97342021-09-27 17:06:40 +020091 config.fixed_digital.gain_db = -5.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +020092 EXPECT_FALSE(GainController2::Validate(config));
93 // No gain is allowed.
Alessio Bazzica6ee97342021-09-27 17:06:40 +020094 config.fixed_digital.gain_db = 0.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +020095 EXPECT_TRUE(GainController2::Validate(config));
96 // Positive gain is allowed.
Alessio Bazzica6ee97342021-09-27 17:06:40 +020097 config.fixed_digital.gain_db = 15.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +020098 EXPECT_TRUE(GainController2::Validate(config));
99}
alessiob3ec96df2017-05-22 06:57:06 -0700100
Alessio Bazzicaa850e6c2021-10-04 13:35:55 +0200101TEST(GainController2, CheckHeadroomDb) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200102 Agc2Config config;
Alessio Bazzicaa850e6c2021-10-04 13:35:55 +0200103 config.adaptive_digital.headroom_db = -1.0f;
104 EXPECT_FALSE(GainController2::Validate(config));
105 config.adaptive_digital.headroom_db = 0.0f;
106 EXPECT_TRUE(GainController2::Validate(config));
107 config.adaptive_digital.headroom_db = 5.0f;
108 EXPECT_TRUE(GainController2::Validate(config));
109}
110
111TEST(GainController2, CheckMaxGainDb) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200112 Agc2Config config;
Alessio Bazzicaa850e6c2021-10-04 13:35:55 +0200113 config.adaptive_digital.max_gain_db = -1.0f;
114 EXPECT_FALSE(GainController2::Validate(config));
115 config.adaptive_digital.max_gain_db = 0.0f;
116 EXPECT_FALSE(GainController2::Validate(config));
117 config.adaptive_digital.max_gain_db = 5.0f;
118 EXPECT_TRUE(GainController2::Validate(config));
119}
120
121TEST(GainController2, CheckInitialGainDb) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200122 Agc2Config config;
Alessio Bazzicaa850e6c2021-10-04 13:35:55 +0200123 config.adaptive_digital.initial_gain_db = -1.0f;
124 EXPECT_FALSE(GainController2::Validate(config));
125 config.adaptive_digital.initial_gain_db = 0.0f;
126 EXPECT_TRUE(GainController2::Validate(config));
127 config.adaptive_digital.initial_gain_db = 5.0f;
128 EXPECT_TRUE(GainController2::Validate(config));
129}
130
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200131TEST(GainController2, CheckAdaptiveDigitalMaxGainChangeSpeedConfig) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200132 Agc2Config config;
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200133 config.adaptive_digital.max_gain_change_db_per_second = -1.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200134 EXPECT_FALSE(GainController2::Validate(config));
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200135 config.adaptive_digital.max_gain_change_db_per_second = 0.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200136 EXPECT_FALSE(GainController2::Validate(config));
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200137 config.adaptive_digital.max_gain_change_db_per_second = 5.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200138 EXPECT_TRUE(GainController2::Validate(config));
139}
140
141TEST(GainController2, CheckAdaptiveDigitalMaxOutputNoiseLevelConfig) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200142 Agc2Config config;
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200143 config.adaptive_digital.max_output_noise_level_dbfs = 5.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200144 EXPECT_FALSE(GainController2::Validate(config));
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200145 config.adaptive_digital.max_output_noise_level_dbfs = 0.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200146 EXPECT_TRUE(GainController2::Validate(config));
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200147 config.adaptive_digital.max_output_noise_level_dbfs = -5.0f;
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200148 EXPECT_TRUE(GainController2::Validate(config));
149}
150
Hanna Silend7cfbe32022-11-02 19:12:20 +0100151TEST(GainController2,
152 CheckGetRecommendedInputVolumeWhenInputVolumeControllerNotEnabled) {
153 constexpr float kHighInputLevel = 32767.0f;
154 constexpr float kLowInputLevel = 1000.0f;
155 constexpr int kInitialInputVolume = 100;
156 constexpr int kNumChannels = 2;
157 constexpr int kNumFrames = 5;
158 constexpr int kSampleRateHz = 16000;
159
160 Agc2Config config;
161 config.input_volume_controller.enabled = false;
162 auto gain_controller =
163 std::make_unique<GainController2>(config, kSampleRateHz, kNumChannels,
164 /*use_internal_vad=*/true);
165
166 EXPECT_FALSE(gain_controller->GetRecommendedInputVolume().has_value());
167
168 // Run AGC for a signal with no clipping or detected speech.
169 RunAgc2WithConstantInput(*gain_controller, kLowInputLevel, kNumFrames,
170 kSampleRateHz, kNumChannels, kInitialInputVolume);
171
172 EXPECT_FALSE(gain_controller->GetRecommendedInputVolume().has_value());
173
174 // Run AGC for a signal with clipping.
175 RunAgc2WithConstantInput(*gain_controller, kHighInputLevel, kNumFrames,
176 kSampleRateHz, kNumChannels, kInitialInputVolume);
177
178 EXPECT_FALSE(gain_controller->GetRecommendedInputVolume().has_value());
179}
180
181TEST(GainController2,
182 CheckGetRecommendedInputVolumeWhenInputVolumeControllerEnabled) {
183 constexpr float kHighInputLevel = 32767.0f;
184 constexpr float kLowInputLevel = 1000.0f;
185 constexpr int kInitialInputVolume = 100;
186 constexpr int kNumChannels = 2;
187 constexpr int kNumFrames = 5;
188 constexpr int kSampleRateHz = 16000;
189
190 Agc2Config config;
191 config.input_volume_controller.enabled = true;
192 auto gain_controller =
193 std::make_unique<GainController2>(config, kSampleRateHz, kNumChannels,
194 /*use_internal_vad=*/true);
195
196 EXPECT_TRUE(gain_controller->GetRecommendedInputVolume().has_value());
197
198 // Run AGC for a signal with no clipping or detected speech.
199 RunAgc2WithConstantInput(*gain_controller, kLowInputLevel, kNumFrames,
200 kSampleRateHz, kNumChannels, kInitialInputVolume);
201
202 EXPECT_TRUE(gain_controller->GetRecommendedInputVolume().has_value());
203
204 // Run AGC for a signal with clipping.
205 RunAgc2WithConstantInput(*gain_controller, kHighInputLevel, kNumFrames,
206 kSampleRateHz, kNumChannels, kInitialInputVolume);
207
208 EXPECT_TRUE(gain_controller->GetRecommendedInputVolume().has_value());
209}
210
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200211// Checks that the default config is applied.
212TEST(GainController2, ApplyDefaultConfig) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200213 auto gain_controller2 = std::make_unique<GainController2>(
Hanna Silen0c1ad292022-06-16 16:35:45 +0200214 Agc2Config{}, /*sample_rate_hz=*/16000, /*num_channels=*/2,
215 /*use_internal_vad=*/true);
Alessio Bazzica38901042021-10-14 12:14:21 +0200216 EXPECT_TRUE(gain_controller2.get());
alessiob3ec96df2017-05-22 06:57:06 -0700217}
218
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100219TEST(GainController2FixedDigital, GainShouldChangeOnSetGain) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200220 constexpr float kInputLevel = 1000.0f;
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100221 constexpr size_t kNumFrames = 5;
222 constexpr size_t kSampleRateHz = 8000;
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200223 constexpr float kGain0Db = 0.0f;
224 constexpr float kGain20Db = 20.0f;
Alessio Bazzica270f7b52017-10-13 11:05:17 +0200225
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100226 auto agc2_fixed = CreateAgc2FixedDigitalMode(kGain0Db, kSampleRateHz);
227
228 // Signal level is unchanged with 0 db gain.
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200229 EXPECT_FLOAT_EQ(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel, kNumFrames,
230 kSampleRateHz),
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100231 kInputLevel);
232
233 // +20 db should increase signal by a factor of 10.
Alessio Bazzica38901042021-10-14 12:14:21 +0200234 agc2_fixed->SetFixedGainDb(kGain20Db);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200235 EXPECT_FLOAT_EQ(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel, kNumFrames,
236 kSampleRateHz),
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100237 kInputLevel * 10);
alessiob3ec96df2017-05-22 06:57:06 -0700238}
239
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100240TEST(GainController2FixedDigital, ChangeFixedGainShouldBeFastAndTimeInvariant) {
241 // Number of frames required for the fixed gain controller to adapt on the
242 // input signal when the gain changes.
243 constexpr size_t kNumFrames = 5;
Alex Loiko5e784612018-11-01 14:51:56 +0100244
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200245 constexpr float kInputLevel = 1000.0f;
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100246 constexpr size_t kSampleRateHz = 8000;
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200247 constexpr float kGainDbLow = 0.0f;
248 constexpr float kGainDbHigh = 25.0f;
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100249 static_assert(kGainDbLow < kGainDbHigh, "");
Alex Loiko5e784612018-11-01 14:51:56 +0100250
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100251 auto agc2_fixed = CreateAgc2FixedDigitalMode(kGainDbLow, kSampleRateHz);
252
253 // Start with a lower gain.
254 const float output_level_pre = RunAgc2WithConstantInput(
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200255 *agc2_fixed, kInputLevel, kNumFrames, kSampleRateHz);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100256
257 // Increase gain.
Alessio Bazzica38901042021-10-14 12:14:21 +0200258 agc2_fixed->SetFixedGainDb(kGainDbHigh);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200259 static_cast<void>(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel,
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100260 kNumFrames, kSampleRateHz));
261
262 // Back to the lower gain.
Alessio Bazzica38901042021-10-14 12:14:21 +0200263 agc2_fixed->SetFixedGainDb(kGainDbLow);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100264 const float output_level_post = RunAgc2WithConstantInput(
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200265 *agc2_fixed, kInputLevel, kNumFrames, kSampleRateHz);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100266
267 EXPECT_EQ(output_level_pre, output_level_post);
268}
269
Alessio Bazzica38901042021-10-14 12:14:21 +0200270class FixedDigitalTest
271 : public ::testing::TestWithParam<std::tuple<float, float, int, bool>> {
272 protected:
273 float gain_db_min() const { return std::get<0>(GetParam()); }
274 float gain_db_max() const { return std::get<1>(GetParam()); }
275 int sample_rate_hz() const { return std::get<2>(GetParam()); }
276 bool saturation_expected() const { return std::get<3>(GetParam()); }
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100277};
278
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100279TEST_P(FixedDigitalTest, CheckSaturationBehaviorWithLimiter) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200280 for (const float gain_db : test::LinSpace(gain_db_min(), gain_db_max(), 10)) {
281 SCOPED_TRACE(gain_db);
282 auto agc2_fixed = CreateAgc2FixedDigitalMode(gain_db, sample_rate_hz());
283 const float processed_sample =
284 RunAgc2WithConstantInput(*agc2_fixed, /*input_level=*/32767.0f,
285 /*num_frames=*/5, sample_rate_hz());
286 if (saturation_expected()) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200287 EXPECT_FLOAT_EQ(processed_sample, 32767.0f);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100288 } else {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200289 EXPECT_LT(processed_sample, 32767.0f);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100290 }
Alex Loiko5e784612018-11-01 14:51:56 +0100291 }
Alex Loiko5e784612018-11-01 14:51:56 +0100292}
293
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100294static_assert(test::kLimiterMaxInputLevelDbFs < 10, "");
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100295INSTANTIATE_TEST_SUITE_P(
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100296 GainController2,
297 FixedDigitalTest,
298 ::testing::Values(
Artem Titovcfea2182021-08-10 01:22:31 +0200299 // When gain < `test::kLimiterMaxInputLevelDbFs`, the limiter will not
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100300 // saturate the signal (at any sample rate).
Alessio Bazzica38901042021-10-14 12:14:21 +0200301 std::make_tuple(0.1f,
302 test::kLimiterMaxInputLevelDbFs - 0.01f,
303 8000,
304 false),
305 std::make_tuple(0.1,
306 test::kLimiterMaxInputLevelDbFs - 0.01f,
307 48000,
308 false),
Artem Titovcfea2182021-08-10 01:22:31 +0200309 // When gain > `test::kLimiterMaxInputLevelDbFs`, the limiter will
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100310 // saturate the signal (at any sample rate).
Alessio Bazzica38901042021-10-14 12:14:21 +0200311 std::make_tuple(test::kLimiterMaxInputLevelDbFs + 0.01f,
312 10.0f,
313 8000,
314 true),
315 std::make_tuple(test::kLimiterMaxInputLevelDbFs + 0.01f,
316 10.0f,
317 48000,
318 true)));
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100319
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200320// Processes a test audio file and checks that the gain applied at the end of
321// the recording is close to the expected value.
322TEST(GainController2, CheckFinalGainWithAdaptiveDigitalController) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200323 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz;
324 constexpr int kStereo = 2;
Alessio Bazzica38901042021-10-14 12:14:21 +0200325
326 // Create AGC2 enabling only the adaptive digital controller.
327 Agc2Config config;
328 config.fixed_digital.gain_db = 0.0f;
329 config.adaptive_digital.enabled = true;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200330 GainController2 agc2(config, kSampleRateHz, kStereo,
331 /*use_internal_vad=*/true);
Alessio Bazzica38901042021-10-14 12:14:21 +0200332
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200333 test::InputAudioFile input_file(
334 test::GetApmCaptureTestVectorFileName(kSampleRateHz),
335 /*loop_at_end=*/true);
Henrik Lundin64253a92022-02-04 09:02:48 +0000336 const StreamConfig stream_config(kSampleRateHz, kStereo);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200337
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200338 // Init buffers.
339 constexpr int kFrameDurationMs = 10;
340 std::vector<float> frame(kStereo * stream_config.num_frames());
341 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo,
342 kSampleRateHz, kStereo);
343
344 // Simulate.
345 constexpr float kGainDb = -6.0f;
346 const float gain = std::pow(10.0f, kGainDb / 20.0f);
347 constexpr int kDurationMs = 10000;
348 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs;
349 for (int i = 0; i < kNumFramesToProcess; ++i) {
350 ReadFloatSamplesFromStereoFile(stream_config.num_frames(),
351 stream_config.num_channels(), &input_file,
352 frame);
353 // Apply a fixed gain to the input audio.
Hanna Silen0c1ad292022-06-16 16:35:45 +0200354 for (float& x : frame) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200355 x *= gain;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200356 }
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200357 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200358 agc2.Process(/*speech_probability=*/absl::nullopt,
359 /*input_volume_changed=*/false, &audio_buffer);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200360 }
361
362 // Estimate the applied gain by processing a probing frame.
363 SetAudioBufferSamples(/*value=*/1.0f, audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200364 agc2.Process(/*speech_probability=*/absl::nullopt,
365 /*input_volume_changed=*/false, &audio_buffer);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200366 const float applied_gain_db =
367 20.0f * std::log10(audio_buffer.channels_const()[0][0]);
368
369 constexpr float kExpectedGainDb = 5.6f;
370 constexpr float kToleranceDb = 0.3f;
371 EXPECT_NEAR(applied_gain_db, kExpectedGainDb, kToleranceDb);
Alex Loiko5e784612018-11-01 14:51:56 +0100372}
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100373
Hanna Silen0c1ad292022-06-16 16:35:45 +0200374// Processes a test audio file and checks that the injected speech probability
375// is ignored when the internal VAD is used.
376TEST(GainController2,
377 CheckInjectedVadProbabilityNotUsedWithAdaptiveDigitalController) {
378 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz;
379 constexpr int kStereo = 2;
380
381 // Create AGC2 enabling only the adaptive digital controller.
382 Agc2Config config;
383 config.fixed_digital.gain_db = 0.0f;
384 config.adaptive_digital.enabled = true;
385 GainController2 agc2(config, kSampleRateHz, kStereo,
386 /*use_internal_vad=*/true);
387 GainController2 agc2_reference(config, kSampleRateHz, kStereo,
388 /*use_internal_vad=*/true);
389
390 test::InputAudioFile input_file(
391 test::GetApmCaptureTestVectorFileName(kSampleRateHz),
392 /*loop_at_end=*/true);
393 const StreamConfig stream_config(kSampleRateHz, kStereo);
394
395 // Init buffers.
396 constexpr int kFrameDurationMs = 10;
397 std::vector<float> frame(kStereo * stream_config.num_frames());
398 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo,
399 kSampleRateHz, kStereo);
400 AudioBuffer audio_buffer_reference(kSampleRateHz, kStereo, kSampleRateHz,
401 kStereo, kSampleRateHz, kStereo);
402
403 // Simulate.
404 constexpr float kGainDb = -6.0f;
405 const float gain = std::pow(10.0f, kGainDb / 20.0f);
406 constexpr int kDurationMs = 10000;
407 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs;
408 constexpr float kSpeechProbabilities[] = {1.0f, 0.3f};
409 constexpr float kEpsilon = 0.0001f;
410 bool all_samples_zero = true;
411 for (int i = 0, j = 0; i < kNumFramesToProcess; ++i, j = 1 - j) {
412 ReadFloatSamplesFromStereoFile(stream_config.num_frames(),
413 stream_config.num_channels(), &input_file,
414 frame);
415 // Apply a fixed gain to the input audio.
416 for (float& x : frame) {
417 x *= gain;
418 }
419 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200420 agc2.Process(kSpeechProbabilities[j], /*input_volume_changed=*/false,
421 &audio_buffer);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200422 test::CopyVectorToAudioBuffer(stream_config, frame,
423 &audio_buffer_reference);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200424 agc2_reference.Process(/*speech_probability=*/absl::nullopt,
425 /*input_volume_changed=*/false,
426 &audio_buffer_reference);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200427
428 // Check the output buffers.
429 for (int i = 0; i < kStereo; ++i) {
430 for (int j = 0; j < static_cast<int>(audio_buffer.num_frames()); ++j) {
431 all_samples_zero &=
432 fabs(audio_buffer.channels_const()[i][j]) < kEpsilon;
433 EXPECT_FLOAT_EQ(audio_buffer.channels_const()[i][j],
434 audio_buffer_reference.channels_const()[i][j]);
435 }
436 }
437 }
438 EXPECT_FALSE(all_samples_zero);
439}
440
441// Processes a test audio file and checks that the injected speech probability
442// is not ignored when the internal VAD is not used.
443TEST(GainController2,
444 CheckInjectedVadProbabilityUsedWithAdaptiveDigitalController) {
445 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz;
446 constexpr int kStereo = 2;
447
448 // Create AGC2 enabling only the adaptive digital controller.
449 Agc2Config config;
450 config.fixed_digital.gain_db = 0.0f;
451 config.adaptive_digital.enabled = true;
452 GainController2 agc2(config, kSampleRateHz, kStereo,
453 /*use_internal_vad=*/false);
454 GainController2 agc2_reference(config, kSampleRateHz, kStereo,
455 /*use_internal_vad=*/true);
456
457 test::InputAudioFile input_file(
458 test::GetApmCaptureTestVectorFileName(kSampleRateHz),
459 /*loop_at_end=*/true);
460 const StreamConfig stream_config(kSampleRateHz, kStereo);
461
462 // Init buffers.
463 constexpr int kFrameDurationMs = 10;
464 std::vector<float> frame(kStereo * stream_config.num_frames());
465 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo,
466 kSampleRateHz, kStereo);
467 AudioBuffer audio_buffer_reference(kSampleRateHz, kStereo, kSampleRateHz,
468 kStereo, kSampleRateHz, kStereo);
469 // Simulate.
470 constexpr float kGainDb = -6.0f;
471 const float gain = std::pow(10.0f, kGainDb / 20.0f);
472 constexpr int kDurationMs = 10000;
473 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs;
474 constexpr float kSpeechProbabilities[] = {1.0f, 0.3f};
475 constexpr float kEpsilon = 0.0001f;
476 bool all_samples_zero = true;
477 bool all_samples_equal = true;
478 for (int i = 0, j = 0; i < kNumFramesToProcess; ++i, j = 1 - j) {
479 ReadFloatSamplesFromStereoFile(stream_config.num_frames(),
480 stream_config.num_channels(), &input_file,
481 frame);
482 // Apply a fixed gain to the input audio.
483 for (float& x : frame) {
484 x *= gain;
485 }
486 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200487 agc2.Process(kSpeechProbabilities[j], /*input_volume_changed=*/false,
488 &audio_buffer);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200489 test::CopyVectorToAudioBuffer(stream_config, frame,
490 &audio_buffer_reference);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200491 agc2_reference.Process(/*speech_probability=*/absl::nullopt,
492 /*input_volume_changed=*/false,
493 &audio_buffer_reference);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200494 // Check the output buffers.
495 for (int i = 0; i < kStereo; ++i) {
496 for (int j = 0; j < static_cast<int>(audio_buffer.num_frames()); ++j) {
497 all_samples_zero &=
498 fabs(audio_buffer.channels_const()[i][j]) < kEpsilon;
499 all_samples_equal &=
500 fabs(audio_buffer.channels_const()[i][j] -
501 audio_buffer_reference.channels_const()[i][j]) < kEpsilon;
502 }
503 }
504 }
505 EXPECT_FALSE(all_samples_zero);
506 EXPECT_FALSE(all_samples_equal);
507}
508
509// Processes a test audio file and checks that the output is equal when
510// an injected speech probability from `VoiceActivityDetectorWrapper` and
511// the speech probability computed by the internal VAD are the same.
512TEST(GainController2,
513 CheckEqualResultFromInjectedVadProbabilityWithAdaptiveDigitalController) {
514 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz;
515 constexpr int kStereo = 2;
516
517 // Create AGC2 enabling only the adaptive digital controller.
518 Agc2Config config;
519 config.fixed_digital.gain_db = 0.0f;
520 config.adaptive_digital.enabled = true;
521 GainController2 agc2(config, kSampleRateHz, kStereo,
522 /*use_internal_vad=*/false);
523 GainController2 agc2_reference(config, kSampleRateHz, kStereo,
524 /*use_internal_vad=*/true);
525 VoiceActivityDetectorWrapper vad(config.adaptive_digital.vad_reset_period_ms,
526 GetAvailableCpuFeatures(), kSampleRateHz);
527 test::InputAudioFile input_file(
528 test::GetApmCaptureTestVectorFileName(kSampleRateHz),
529 /*loop_at_end=*/true);
530 const StreamConfig stream_config(kSampleRateHz, kStereo);
531
532 // Init buffers.
533 constexpr int kFrameDurationMs = 10;
534 std::vector<float> frame(kStereo * stream_config.num_frames());
535 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo,
536 kSampleRateHz, kStereo);
537 AudioBuffer audio_buffer_reference(kSampleRateHz, kStereo, kSampleRateHz,
538 kStereo, kSampleRateHz, kStereo);
539
540 // Simulate.
541 constexpr float kGainDb = -6.0f;
542 const float gain = std::pow(10.0f, kGainDb / 20.0f);
543 constexpr int kDurationMs = 10000;
544 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs;
545 for (int i = 0; i < kNumFramesToProcess; ++i) {
546 ReadFloatSamplesFromStereoFile(stream_config.num_frames(),
547 stream_config.num_channels(), &input_file,
548 frame);
549 // Apply a fixed gain to the input audio.
550 for (float& x : frame) {
551 x *= gain;
552 }
553 test::CopyVectorToAudioBuffer(stream_config, frame,
554 &audio_buffer_reference);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200555 agc2_reference.Process(absl::nullopt, /*input_volume_changed=*/false,
556 &audio_buffer_reference);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200557 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200558 float speech_probability = vad.Analyze(AudioFrameView<const float>(
559 audio_buffer.channels(), audio_buffer.num_channels(),
560 audio_buffer.num_frames()));
561 agc2.Process(speech_probability, /*input_volume_changed=*/false,
Hanna Silen0c1ad292022-06-16 16:35:45 +0200562 &audio_buffer);
563 // Check the output buffer.
564 for (int i = 0; i < kStereo; ++i) {
565 for (int j = 0; j < static_cast<int>(audio_buffer.num_frames()); ++j) {
566 EXPECT_FLOAT_EQ(audio_buffer.channels_const()[i][j],
567 audio_buffer_reference.channels_const()[i][j]);
568 }
569 }
570 }
571}
572
alessiob3ec96df2017-05-22 06:57:06 -0700573} // namespace test
574} // namespace webrtc