blob: 7fb0c26fc8304c3e0c00bb9309808d19c0fd2355 [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;
Hanna Silen27fed452022-11-22 15:00:58 +0100162
Hanna Silend7cfbe32022-11-02 19:12:20 +0100163 auto gain_controller =
164 std::make_unique<GainController2>(config, kSampleRateHz, kNumChannels,
165 /*use_internal_vad=*/true);
166
167 EXPECT_FALSE(gain_controller->GetRecommendedInputVolume().has_value());
168
169 // Run AGC for a signal with no clipping or detected speech.
170 RunAgc2WithConstantInput(*gain_controller, kLowInputLevel, kNumFrames,
171 kSampleRateHz, kNumChannels, kInitialInputVolume);
172
173 EXPECT_FALSE(gain_controller->GetRecommendedInputVolume().has_value());
174
175 // Run AGC for a signal with clipping.
176 RunAgc2WithConstantInput(*gain_controller, kHighInputLevel, kNumFrames,
177 kSampleRateHz, kNumChannels, kInitialInputVolume);
178
179 EXPECT_FALSE(gain_controller->GetRecommendedInputVolume().has_value());
180}
181
182TEST(GainController2,
183 CheckGetRecommendedInputVolumeWhenInputVolumeControllerEnabled) {
184 constexpr float kHighInputLevel = 32767.0f;
185 constexpr float kLowInputLevel = 1000.0f;
186 constexpr int kInitialInputVolume = 100;
187 constexpr int kNumChannels = 2;
188 constexpr int kNumFrames = 5;
189 constexpr int kSampleRateHz = 16000;
190
191 Agc2Config config;
192 config.input_volume_controller.enabled = true;
Hanna Silen27fed452022-11-22 15:00:58 +0100193 config.adaptive_digital.enabled = true;
194
Hanna Silend7cfbe32022-11-02 19:12:20 +0100195 auto gain_controller =
196 std::make_unique<GainController2>(config, kSampleRateHz, kNumChannels,
197 /*use_internal_vad=*/true);
198
199 EXPECT_TRUE(gain_controller->GetRecommendedInputVolume().has_value());
200
201 // Run AGC for a signal with no clipping or detected speech.
202 RunAgc2WithConstantInput(*gain_controller, kLowInputLevel, kNumFrames,
203 kSampleRateHz, kNumChannels, kInitialInputVolume);
204
205 EXPECT_TRUE(gain_controller->GetRecommendedInputVolume().has_value());
206
207 // Run AGC for a signal with clipping.
208 RunAgc2WithConstantInput(*gain_controller, kHighInputLevel, kNumFrames,
209 kSampleRateHz, kNumChannels, kInitialInputVolume);
210
211 EXPECT_TRUE(gain_controller->GetRecommendedInputVolume().has_value());
212}
213
Alessio Bazzica0c83e152020-10-14 12:49:54 +0200214// Checks that the default config is applied.
215TEST(GainController2, ApplyDefaultConfig) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200216 auto gain_controller2 = std::make_unique<GainController2>(
Hanna Silen0c1ad292022-06-16 16:35:45 +0200217 Agc2Config{}, /*sample_rate_hz=*/16000, /*num_channels=*/2,
218 /*use_internal_vad=*/true);
Alessio Bazzica38901042021-10-14 12:14:21 +0200219 EXPECT_TRUE(gain_controller2.get());
alessiob3ec96df2017-05-22 06:57:06 -0700220}
221
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100222TEST(GainController2FixedDigital, GainShouldChangeOnSetGain) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200223 constexpr float kInputLevel = 1000.0f;
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100224 constexpr size_t kNumFrames = 5;
225 constexpr size_t kSampleRateHz = 8000;
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200226 constexpr float kGain0Db = 0.0f;
227 constexpr float kGain20Db = 20.0f;
Alessio Bazzica270f7b52017-10-13 11:05:17 +0200228
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100229 auto agc2_fixed = CreateAgc2FixedDigitalMode(kGain0Db, kSampleRateHz);
230
231 // Signal level is unchanged with 0 db gain.
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200232 EXPECT_FLOAT_EQ(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel, kNumFrames,
233 kSampleRateHz),
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100234 kInputLevel);
235
236 // +20 db should increase signal by a factor of 10.
Alessio Bazzica38901042021-10-14 12:14:21 +0200237 agc2_fixed->SetFixedGainDb(kGain20Db);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200238 EXPECT_FLOAT_EQ(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel, kNumFrames,
239 kSampleRateHz),
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100240 kInputLevel * 10);
alessiob3ec96df2017-05-22 06:57:06 -0700241}
242
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100243TEST(GainController2FixedDigital, ChangeFixedGainShouldBeFastAndTimeInvariant) {
244 // Number of frames required for the fixed gain controller to adapt on the
245 // input signal when the gain changes.
246 constexpr size_t kNumFrames = 5;
Alex Loiko5e784612018-11-01 14:51:56 +0100247
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200248 constexpr float kInputLevel = 1000.0f;
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100249 constexpr size_t kSampleRateHz = 8000;
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200250 constexpr float kGainDbLow = 0.0f;
251 constexpr float kGainDbHigh = 25.0f;
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100252 static_assert(kGainDbLow < kGainDbHigh, "");
Alex Loiko5e784612018-11-01 14:51:56 +0100253
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100254 auto agc2_fixed = CreateAgc2FixedDigitalMode(kGainDbLow, kSampleRateHz);
255
256 // Start with a lower gain.
257 const float output_level_pre = RunAgc2WithConstantInput(
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200258 *agc2_fixed, kInputLevel, kNumFrames, kSampleRateHz);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100259
260 // Increase gain.
Alessio Bazzica38901042021-10-14 12:14:21 +0200261 agc2_fixed->SetFixedGainDb(kGainDbHigh);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200262 static_cast<void>(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel,
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100263 kNumFrames, kSampleRateHz));
264
265 // Back to the lower gain.
Alessio Bazzica38901042021-10-14 12:14:21 +0200266 agc2_fixed->SetFixedGainDb(kGainDbLow);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100267 const float output_level_post = RunAgc2WithConstantInput(
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200268 *agc2_fixed, kInputLevel, kNumFrames, kSampleRateHz);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100269
270 EXPECT_EQ(output_level_pre, output_level_post);
271}
272
Alessio Bazzica38901042021-10-14 12:14:21 +0200273class FixedDigitalTest
274 : public ::testing::TestWithParam<std::tuple<float, float, int, bool>> {
275 protected:
276 float gain_db_min() const { return std::get<0>(GetParam()); }
277 float gain_db_max() const { return std::get<1>(GetParam()); }
278 int sample_rate_hz() const { return std::get<2>(GetParam()); }
279 bool saturation_expected() const { return std::get<3>(GetParam()); }
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100280};
281
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100282TEST_P(FixedDigitalTest, CheckSaturationBehaviorWithLimiter) {
Alessio Bazzica38901042021-10-14 12:14:21 +0200283 for (const float gain_db : test::LinSpace(gain_db_min(), gain_db_max(), 10)) {
284 SCOPED_TRACE(gain_db);
285 auto agc2_fixed = CreateAgc2FixedDigitalMode(gain_db, sample_rate_hz());
286 const float processed_sample =
287 RunAgc2WithConstantInput(*agc2_fixed, /*input_level=*/32767.0f,
288 /*num_frames=*/5, sample_rate_hz());
289 if (saturation_expected()) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200290 EXPECT_FLOAT_EQ(processed_sample, 32767.0f);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100291 } else {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200292 EXPECT_LT(processed_sample, 32767.0f);
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100293 }
Alex Loiko5e784612018-11-01 14:51:56 +0100294 }
Alex Loiko5e784612018-11-01 14:51:56 +0100295}
296
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100297static_assert(test::kLimiterMaxInputLevelDbFs < 10, "");
Mirko Bonadeic84f6612019-01-31 12:20:57 +0100298INSTANTIATE_TEST_SUITE_P(
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100299 GainController2,
300 FixedDigitalTest,
301 ::testing::Values(
Artem Titovcfea2182021-08-10 01:22:31 +0200302 // When gain < `test::kLimiterMaxInputLevelDbFs`, the limiter will not
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100303 // saturate the signal (at any sample rate).
Alessio Bazzica38901042021-10-14 12:14:21 +0200304 std::make_tuple(0.1f,
305 test::kLimiterMaxInputLevelDbFs - 0.01f,
306 8000,
307 false),
308 std::make_tuple(0.1,
309 test::kLimiterMaxInputLevelDbFs - 0.01f,
310 48000,
311 false),
Artem Titovcfea2182021-08-10 01:22:31 +0200312 // When gain > `test::kLimiterMaxInputLevelDbFs`, the limiter will
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100313 // saturate the signal (at any sample rate).
Alessio Bazzica38901042021-10-14 12:14:21 +0200314 std::make_tuple(test::kLimiterMaxInputLevelDbFs + 0.01f,
315 10.0f,
316 8000,
317 true),
318 std::make_tuple(test::kLimiterMaxInputLevelDbFs + 0.01f,
319 10.0f,
320 48000,
321 true)));
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100322
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200323// Processes a test audio file and checks that the gain applied at the end of
324// the recording is close to the expected value.
325TEST(GainController2, CheckFinalGainWithAdaptiveDigitalController) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200326 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz;
327 constexpr int kStereo = 2;
Alessio Bazzica38901042021-10-14 12:14:21 +0200328
329 // Create AGC2 enabling only the adaptive digital controller.
330 Agc2Config config;
331 config.fixed_digital.gain_db = 0.0f;
332 config.adaptive_digital.enabled = true;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200333 GainController2 agc2(config, kSampleRateHz, kStereo,
334 /*use_internal_vad=*/true);
Alessio Bazzica38901042021-10-14 12:14:21 +0200335
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200336 test::InputAudioFile input_file(
337 test::GetApmCaptureTestVectorFileName(kSampleRateHz),
338 /*loop_at_end=*/true);
Henrik Lundin64253a92022-02-04 09:02:48 +0000339 const StreamConfig stream_config(kSampleRateHz, kStereo);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200340
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200341 // Init buffers.
342 constexpr int kFrameDurationMs = 10;
343 std::vector<float> frame(kStereo * stream_config.num_frames());
344 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo,
345 kSampleRateHz, kStereo);
346
347 // Simulate.
348 constexpr float kGainDb = -6.0f;
349 const float gain = std::pow(10.0f, kGainDb / 20.0f);
350 constexpr int kDurationMs = 10000;
351 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs;
352 for (int i = 0; i < kNumFramesToProcess; ++i) {
353 ReadFloatSamplesFromStereoFile(stream_config.num_frames(),
354 stream_config.num_channels(), &input_file,
355 frame);
356 // Apply a fixed gain to the input audio.
Hanna Silen0c1ad292022-06-16 16:35:45 +0200357 for (float& x : frame) {
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200358 x *= gain;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200359 }
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200360 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200361 agc2.Process(/*speech_probability=*/absl::nullopt,
362 /*input_volume_changed=*/false, &audio_buffer);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200363 }
364
365 // Estimate the applied gain by processing a probing frame.
366 SetAudioBufferSamples(/*value=*/1.0f, audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200367 agc2.Process(/*speech_probability=*/absl::nullopt,
368 /*input_volume_changed=*/false, &audio_buffer);
Alessio Bazzica6ee97342021-09-27 17:06:40 +0200369 const float applied_gain_db =
370 20.0f * std::log10(audio_buffer.channels_const()[0][0]);
371
372 constexpr float kExpectedGainDb = 5.6f;
373 constexpr float kToleranceDb = 0.3f;
374 EXPECT_NEAR(applied_gain_db, kExpectedGainDb, kToleranceDb);
Alex Loiko5e784612018-11-01 14:51:56 +0100375}
Alessio Bazzica3e4c77f2018-11-01 21:31:38 +0100376
Hanna Silen0c1ad292022-06-16 16:35:45 +0200377// Processes a test audio file and checks that the injected speech probability
378// is ignored when the internal VAD is used.
379TEST(GainController2,
380 CheckInjectedVadProbabilityNotUsedWithAdaptiveDigitalController) {
381 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz;
382 constexpr int kStereo = 2;
383
384 // Create AGC2 enabling only the adaptive digital controller.
385 Agc2Config config;
386 config.fixed_digital.gain_db = 0.0f;
387 config.adaptive_digital.enabled = true;
388 GainController2 agc2(config, kSampleRateHz, kStereo,
389 /*use_internal_vad=*/true);
390 GainController2 agc2_reference(config, kSampleRateHz, kStereo,
391 /*use_internal_vad=*/true);
392
393 test::InputAudioFile input_file(
394 test::GetApmCaptureTestVectorFileName(kSampleRateHz),
395 /*loop_at_end=*/true);
396 const StreamConfig stream_config(kSampleRateHz, kStereo);
397
398 // Init buffers.
399 constexpr int kFrameDurationMs = 10;
400 std::vector<float> frame(kStereo * stream_config.num_frames());
401 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo,
402 kSampleRateHz, kStereo);
403 AudioBuffer audio_buffer_reference(kSampleRateHz, kStereo, kSampleRateHz,
404 kStereo, kSampleRateHz, kStereo);
405
406 // Simulate.
407 constexpr float kGainDb = -6.0f;
408 const float gain = std::pow(10.0f, kGainDb / 20.0f);
409 constexpr int kDurationMs = 10000;
410 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs;
411 constexpr float kSpeechProbabilities[] = {1.0f, 0.3f};
412 constexpr float kEpsilon = 0.0001f;
413 bool all_samples_zero = true;
414 for (int i = 0, j = 0; i < kNumFramesToProcess; ++i, j = 1 - j) {
415 ReadFloatSamplesFromStereoFile(stream_config.num_frames(),
416 stream_config.num_channels(), &input_file,
417 frame);
418 // Apply a fixed gain to the input audio.
419 for (float& x : frame) {
420 x *= gain;
421 }
422 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200423 agc2.Process(kSpeechProbabilities[j], /*input_volume_changed=*/false,
424 &audio_buffer);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200425 test::CopyVectorToAudioBuffer(stream_config, frame,
426 &audio_buffer_reference);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200427 agc2_reference.Process(/*speech_probability=*/absl::nullopt,
428 /*input_volume_changed=*/false,
429 &audio_buffer_reference);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200430
431 // Check the output buffers.
432 for (int i = 0; i < kStereo; ++i) {
433 for (int j = 0; j < static_cast<int>(audio_buffer.num_frames()); ++j) {
434 all_samples_zero &=
435 fabs(audio_buffer.channels_const()[i][j]) < kEpsilon;
436 EXPECT_FLOAT_EQ(audio_buffer.channels_const()[i][j],
437 audio_buffer_reference.channels_const()[i][j]);
438 }
439 }
440 }
441 EXPECT_FALSE(all_samples_zero);
442}
443
444// Processes a test audio file and checks that the injected speech probability
445// is not ignored when the internal VAD is not used.
446TEST(GainController2,
447 CheckInjectedVadProbabilityUsedWithAdaptiveDigitalController) {
448 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz;
449 constexpr int kStereo = 2;
450
451 // Create AGC2 enabling only the adaptive digital controller.
452 Agc2Config config;
453 config.fixed_digital.gain_db = 0.0f;
454 config.adaptive_digital.enabled = true;
455 GainController2 agc2(config, kSampleRateHz, kStereo,
456 /*use_internal_vad=*/false);
457 GainController2 agc2_reference(config, kSampleRateHz, kStereo,
458 /*use_internal_vad=*/true);
459
460 test::InputAudioFile input_file(
461 test::GetApmCaptureTestVectorFileName(kSampleRateHz),
462 /*loop_at_end=*/true);
463 const StreamConfig stream_config(kSampleRateHz, kStereo);
464
465 // Init buffers.
466 constexpr int kFrameDurationMs = 10;
467 std::vector<float> frame(kStereo * stream_config.num_frames());
468 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo,
469 kSampleRateHz, kStereo);
470 AudioBuffer audio_buffer_reference(kSampleRateHz, kStereo, kSampleRateHz,
471 kStereo, kSampleRateHz, kStereo);
472 // Simulate.
473 constexpr float kGainDb = -6.0f;
474 const float gain = std::pow(10.0f, kGainDb / 20.0f);
475 constexpr int kDurationMs = 10000;
476 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs;
477 constexpr float kSpeechProbabilities[] = {1.0f, 0.3f};
478 constexpr float kEpsilon = 0.0001f;
479 bool all_samples_zero = true;
480 bool all_samples_equal = true;
481 for (int i = 0, j = 0; i < kNumFramesToProcess; ++i, j = 1 - j) {
482 ReadFloatSamplesFromStereoFile(stream_config.num_frames(),
483 stream_config.num_channels(), &input_file,
484 frame);
485 // Apply a fixed gain to the input audio.
486 for (float& x : frame) {
487 x *= gain;
488 }
489 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200490 agc2.Process(kSpeechProbabilities[j], /*input_volume_changed=*/false,
491 &audio_buffer);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200492 test::CopyVectorToAudioBuffer(stream_config, frame,
493 &audio_buffer_reference);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200494 agc2_reference.Process(/*speech_probability=*/absl::nullopt,
495 /*input_volume_changed=*/false,
496 &audio_buffer_reference);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200497 // Check the output buffers.
498 for (int i = 0; i < kStereo; ++i) {
499 for (int j = 0; j < static_cast<int>(audio_buffer.num_frames()); ++j) {
500 all_samples_zero &=
501 fabs(audio_buffer.channels_const()[i][j]) < kEpsilon;
502 all_samples_equal &=
503 fabs(audio_buffer.channels_const()[i][j] -
504 audio_buffer_reference.channels_const()[i][j]) < kEpsilon;
505 }
506 }
507 }
508 EXPECT_FALSE(all_samples_zero);
509 EXPECT_FALSE(all_samples_equal);
510}
511
512// Processes a test audio file and checks that the output is equal when
513// an injected speech probability from `VoiceActivityDetectorWrapper` and
514// the speech probability computed by the internal VAD are the same.
515TEST(GainController2,
516 CheckEqualResultFromInjectedVadProbabilityWithAdaptiveDigitalController) {
517 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz;
518 constexpr int kStereo = 2;
519
520 // Create AGC2 enabling only the adaptive digital controller.
521 Agc2Config config;
522 config.fixed_digital.gain_db = 0.0f;
523 config.adaptive_digital.enabled = true;
524 GainController2 agc2(config, kSampleRateHz, kStereo,
525 /*use_internal_vad=*/false);
526 GainController2 agc2_reference(config, kSampleRateHz, kStereo,
527 /*use_internal_vad=*/true);
528 VoiceActivityDetectorWrapper vad(config.adaptive_digital.vad_reset_period_ms,
529 GetAvailableCpuFeatures(), kSampleRateHz);
530 test::InputAudioFile input_file(
531 test::GetApmCaptureTestVectorFileName(kSampleRateHz),
532 /*loop_at_end=*/true);
533 const StreamConfig stream_config(kSampleRateHz, kStereo);
534
535 // Init buffers.
536 constexpr int kFrameDurationMs = 10;
537 std::vector<float> frame(kStereo * stream_config.num_frames());
538 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo,
539 kSampleRateHz, kStereo);
540 AudioBuffer audio_buffer_reference(kSampleRateHz, kStereo, kSampleRateHz,
541 kStereo, kSampleRateHz, kStereo);
542
543 // Simulate.
544 constexpr float kGainDb = -6.0f;
545 const float gain = std::pow(10.0f, kGainDb / 20.0f);
546 constexpr int kDurationMs = 10000;
547 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs;
548 for (int i = 0; i < kNumFramesToProcess; ++i) {
549 ReadFloatSamplesFromStereoFile(stream_config.num_frames(),
550 stream_config.num_channels(), &input_file,
551 frame);
552 // Apply a fixed gain to the input audio.
553 for (float& x : frame) {
554 x *= gain;
555 }
556 test::CopyVectorToAudioBuffer(stream_config, frame,
557 &audio_buffer_reference);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200558 agc2_reference.Process(absl::nullopt, /*input_volume_changed=*/false,
559 &audio_buffer_reference);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200560 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer);
Alessio Bazzicafcf1af32022-09-07 17:14:26 +0200561 float speech_probability = vad.Analyze(AudioFrameView<const float>(
562 audio_buffer.channels(), audio_buffer.num_channels(),
563 audio_buffer.num_frames()));
564 agc2.Process(speech_probability, /*input_volume_changed=*/false,
Hanna Silen0c1ad292022-06-16 16:35:45 +0200565 &audio_buffer);
566 // Check the output buffer.
567 for (int i = 0; i < kStereo; ++i) {
568 for (int j = 0; j < static_cast<int>(audio_buffer.num_frames()); ++j) {
569 EXPECT_FLOAT_EQ(audio_buffer.channels_const()[i][j],
570 audio_buffer_reference.channels_const()[i][j]);
571 }
572 }
573 }
574}
575
alessiob3ec96df2017-05-22 06:57:06 -0700576} // namespace test
577} // namespace webrtc