gain_controller2_unittest.cc (25475B)
1 /* 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 11 #include "modules/audio_processing/gain_controller2.h" 12 13 #include <algorithm> 14 #include <cmath> 15 #include <cstddef> 16 #include <memory> 17 #include <optional> 18 #include <tuple> 19 #include <vector> 20 21 #include "api/audio/audio_processing.h" 22 #include "api/environment/environment.h" 23 #include "api/environment/environment_factory.h" 24 #include "modules/audio_coding/neteq/tools/input_audio_file.h" 25 #include "modules/audio_processing/agc2/agc2_testing_common.h" 26 #include "modules/audio_processing/agc2/cpu_features.h" 27 #include "modules/audio_processing/agc2/input_volume_controller.h" 28 #include "modules/audio_processing/agc2/vad_wrapper.h" 29 #include "modules/audio_processing/audio_buffer.h" 30 #include "modules/audio_processing/test/audio_buffer_tools.h" 31 #include "modules/audio_processing/test/bitexactness_tools.h" 32 #include "rtc_base/checks.h" 33 #include "test/gmock.h" 34 #include "test/gtest.h" 35 36 namespace webrtc { 37 namespace test { 38 namespace { 39 40 using ::testing::Eq; 41 using ::testing::Optional; 42 43 using Agc2Config = AudioProcessing::Config::GainController2; 44 using InputVolumeControllerConfig = InputVolumeController::Config; 45 46 // Sets all the samples in `ab` to `value`. 47 void SetAudioBufferSamples(float value, AudioBuffer& ab) { 48 for (size_t k = 0; k < ab.num_channels(); ++k) { 49 std::fill(ab.channels()[k], ab.channels()[k] + ab.num_frames(), value); 50 } 51 } 52 53 float RunAgc2WithConstantInput(GainController2& agc2, 54 float input_level, 55 int num_frames, 56 int sample_rate_hz, 57 int num_channels = 1, 58 int applied_initial_volume = 0) { 59 const int num_samples = CheckedDivExact(sample_rate_hz, 100); 60 AudioBuffer ab(sample_rate_hz, num_channels, sample_rate_hz, num_channels, 61 sample_rate_hz, num_channels); 62 63 // Give time to the level estimator to converge. 64 for (int i = 0; i < num_frames + 1; ++i) { 65 SetAudioBufferSamples(input_level, ab); 66 const auto applied_volume = agc2.recommended_input_volume(); 67 agc2.Analyze(applied_volume.value_or(applied_initial_volume), ab); 68 69 agc2.Process(/*speech_probability=*/std::nullopt, 70 /*input_volume_changed=*/false, &ab); 71 } 72 73 // Return the last sample from the last processed frame. 74 return ab.channels()[0][num_samples - 1]; 75 } 76 77 std::unique_ptr<GainController2> CreateAgc2FixedDigitalMode( 78 float fixed_gain_db, 79 int sample_rate_hz) { 80 Agc2Config config; 81 config.adaptive_digital.enabled = false; 82 config.fixed_digital.gain_db = fixed_gain_db; 83 EXPECT_TRUE(GainController2::Validate(config)); 84 return std::make_unique<GainController2>(CreateEnvironment(), config, 85 InputVolumeControllerConfig{}, 86 sample_rate_hz, 87 /*num_channels=*/1, 88 /*use_internal_vad=*/true); 89 } 90 91 constexpr InputVolumeControllerConfig kTestInputVolumeControllerConfig{ 92 .clipped_level_min = 20, 93 .clipped_level_step = 30, 94 .clipped_ratio_threshold = 0.4, 95 .clipped_wait_frames = 50, 96 .enable_clipping_predictor = true, 97 .target_range_max_dbfs = -6, 98 .target_range_min_dbfs = -70, 99 .update_input_volume_wait_frames = 100, 100 .speech_probability_threshold = 0.9, 101 .speech_ratio_threshold = 1, 102 }; 103 104 } // namespace 105 106 TEST(GainController2, CheckDefaultConfig) { 107 Agc2Config config; 108 EXPECT_TRUE(GainController2::Validate(config)); 109 } 110 111 TEST(GainController2, CheckFixedDigitalConfig) { 112 Agc2Config config; 113 // Attenuation is not allowed. 114 config.fixed_digital.gain_db = -5.0f; 115 EXPECT_FALSE(GainController2::Validate(config)); 116 // No gain is allowed. 117 config.fixed_digital.gain_db = 0.0f; 118 EXPECT_TRUE(GainController2::Validate(config)); 119 // Positive gain is allowed. 120 config.fixed_digital.gain_db = 15.0f; 121 EXPECT_TRUE(GainController2::Validate(config)); 122 } 123 124 TEST(GainController2, CheckHeadroomDb) { 125 Agc2Config config; 126 config.adaptive_digital.headroom_db = -1.0f; 127 EXPECT_FALSE(GainController2::Validate(config)); 128 config.adaptive_digital.headroom_db = 0.0f; 129 EXPECT_TRUE(GainController2::Validate(config)); 130 config.adaptive_digital.headroom_db = 5.0f; 131 EXPECT_TRUE(GainController2::Validate(config)); 132 } 133 134 TEST(GainController2, CheckMaxGainDb) { 135 Agc2Config config; 136 config.adaptive_digital.max_gain_db = -1.0f; 137 EXPECT_FALSE(GainController2::Validate(config)); 138 config.adaptive_digital.max_gain_db = 0.0f; 139 EXPECT_FALSE(GainController2::Validate(config)); 140 config.adaptive_digital.max_gain_db = 5.0f; 141 EXPECT_TRUE(GainController2::Validate(config)); 142 } 143 144 TEST(GainController2, CheckInitialGainDb) { 145 Agc2Config config; 146 config.adaptive_digital.initial_gain_db = -1.0f; 147 EXPECT_FALSE(GainController2::Validate(config)); 148 config.adaptive_digital.initial_gain_db = 0.0f; 149 EXPECT_TRUE(GainController2::Validate(config)); 150 config.adaptive_digital.initial_gain_db = 5.0f; 151 EXPECT_TRUE(GainController2::Validate(config)); 152 } 153 154 TEST(GainController2, CheckAdaptiveDigitalMaxGainChangeSpeedConfig) { 155 Agc2Config config; 156 config.adaptive_digital.max_gain_change_db_per_second = -1.0f; 157 EXPECT_FALSE(GainController2::Validate(config)); 158 config.adaptive_digital.max_gain_change_db_per_second = 0.0f; 159 EXPECT_FALSE(GainController2::Validate(config)); 160 config.adaptive_digital.max_gain_change_db_per_second = 5.0f; 161 EXPECT_TRUE(GainController2::Validate(config)); 162 } 163 164 TEST(GainController2, CheckAdaptiveDigitalMaxOutputNoiseLevelConfig) { 165 Agc2Config config; 166 config.adaptive_digital.max_output_noise_level_dbfs = 5.0f; 167 EXPECT_FALSE(GainController2::Validate(config)); 168 config.adaptive_digital.max_output_noise_level_dbfs = 0.0f; 169 EXPECT_TRUE(GainController2::Validate(config)); 170 config.adaptive_digital.max_output_noise_level_dbfs = -5.0f; 171 EXPECT_TRUE(GainController2::Validate(config)); 172 } 173 174 TEST(GainController2, 175 CheckGetRecommendedInputVolumeWhenInputVolumeControllerNotEnabled) { 176 constexpr float kHighInputLevel = 32767.0f; 177 constexpr float kLowInputLevel = 1000.0f; 178 constexpr int kInitialInputVolume = 100; 179 constexpr int kNumChannels = 2; 180 constexpr int kNumFrames = 5; 181 constexpr int kSampleRateHz = 16000; 182 183 Agc2Config config; 184 config.input_volume_controller.enabled = false; 185 186 auto gain_controller = std::make_unique<GainController2>( 187 CreateEnvironment(), config, InputVolumeControllerConfig{}, kSampleRateHz, 188 kNumChannels, 189 /*use_internal_vad=*/true); 190 191 EXPECT_FALSE(gain_controller->recommended_input_volume().has_value()); 192 193 // Run AGC for a signal with no clipping or detected speech. 194 RunAgc2WithConstantInput(*gain_controller, kLowInputLevel, kNumFrames, 195 kSampleRateHz, kNumChannels, kInitialInputVolume); 196 197 EXPECT_FALSE(gain_controller->recommended_input_volume().has_value()); 198 199 // Run AGC for a signal with clipping. 200 RunAgc2WithConstantInput(*gain_controller, kHighInputLevel, kNumFrames, 201 kSampleRateHz, kNumChannels, kInitialInputVolume); 202 203 EXPECT_FALSE(gain_controller->recommended_input_volume().has_value()); 204 } 205 206 TEST( 207 GainController2, 208 CheckGetRecommendedInputVolumeWhenInputVolumeControllerNotEnabledAndSpecificConfigUsed) { 209 constexpr float kHighInputLevel = 32767.0f; 210 constexpr float kLowInputLevel = 1000.0f; 211 constexpr int kInitialInputVolume = 100; 212 constexpr int kNumChannels = 2; 213 constexpr int kNumFrames = 5; 214 constexpr int kSampleRateHz = 16000; 215 216 Agc2Config config; 217 config.input_volume_controller.enabled = false; 218 219 auto gain_controller = std::make_unique<GainController2>( 220 CreateEnvironment(), config, kTestInputVolumeControllerConfig, 221 kSampleRateHz, kNumChannels, 222 /*use_internal_vad=*/true); 223 224 EXPECT_FALSE(gain_controller->recommended_input_volume().has_value()); 225 226 // Run AGC for a signal with no clipping or detected speech. 227 RunAgc2WithConstantInput(*gain_controller, kLowInputLevel, kNumFrames, 228 kSampleRateHz, kNumChannels, kInitialInputVolume); 229 230 EXPECT_FALSE(gain_controller->recommended_input_volume().has_value()); 231 232 // Run AGC for a signal with clipping. 233 RunAgc2WithConstantInput(*gain_controller, kHighInputLevel, kNumFrames, 234 kSampleRateHz, kNumChannels, kInitialInputVolume); 235 236 EXPECT_FALSE(gain_controller->recommended_input_volume().has_value()); 237 } 238 239 TEST(GainController2, 240 CheckGetRecommendedInputVolumeWhenInputVolumeControllerEnabled) { 241 constexpr float kHighInputLevel = 32767.0f; 242 constexpr float kLowInputLevel = 1000.0f; 243 constexpr int kInitialInputVolume = 100; 244 constexpr int kNumChannels = 2; 245 constexpr int kNumFrames = 5; 246 constexpr int kSampleRateHz = 16000; 247 248 Agc2Config config; 249 config.input_volume_controller.enabled = true; 250 config.adaptive_digital.enabled = true; 251 252 auto gain_controller = std::make_unique<GainController2>( 253 CreateEnvironment(), config, InputVolumeControllerConfig{}, kSampleRateHz, 254 kNumChannels, 255 /*use_internal_vad=*/true); 256 257 EXPECT_FALSE(gain_controller->recommended_input_volume().has_value()); 258 259 // Run AGC for a signal with no clipping or detected speech. 260 RunAgc2WithConstantInput(*gain_controller, kLowInputLevel, kNumFrames, 261 kSampleRateHz, kNumChannels, kInitialInputVolume); 262 263 EXPECT_TRUE(gain_controller->recommended_input_volume().has_value()); 264 265 // Run AGC for a signal with clipping. 266 RunAgc2WithConstantInput(*gain_controller, kHighInputLevel, kNumFrames, 267 kSampleRateHz, kNumChannels, kInitialInputVolume); 268 269 EXPECT_TRUE(gain_controller->recommended_input_volume().has_value()); 270 } 271 272 TEST( 273 GainController2, 274 CheckGetRecommendedInputVolumeWhenInputVolumeControllerEnabledAndSpecificConfigUsed) { 275 constexpr float kHighInputLevel = 32767.0f; 276 constexpr float kLowInputLevel = 1000.0f; 277 constexpr int kInitialInputVolume = 100; 278 constexpr int kNumChannels = 2; 279 constexpr int kNumFrames = 5; 280 constexpr int kSampleRateHz = 16000; 281 282 Agc2Config config; 283 config.input_volume_controller.enabled = true; 284 config.adaptive_digital.enabled = true; 285 286 auto gain_controller = std::make_unique<GainController2>( 287 CreateEnvironment(), config, kTestInputVolumeControllerConfig, 288 kSampleRateHz, kNumChannels, 289 /*use_internal_vad=*/true); 290 291 EXPECT_FALSE(gain_controller->recommended_input_volume().has_value()); 292 293 // Run AGC for a signal with no clipping or detected speech. 294 RunAgc2WithConstantInput(*gain_controller, kLowInputLevel, kNumFrames, 295 kSampleRateHz, kNumChannels, kInitialInputVolume); 296 297 EXPECT_TRUE(gain_controller->recommended_input_volume().has_value()); 298 299 // Run AGC for a signal with clipping. 300 RunAgc2WithConstantInput(*gain_controller, kHighInputLevel, kNumFrames, 301 kSampleRateHz, kNumChannels, kInitialInputVolume); 302 303 EXPECT_TRUE(gain_controller->recommended_input_volume().has_value()); 304 } 305 306 // Checks that the default config is applied. 307 TEST(GainController2, ApplyDefaultConfig) { 308 auto gain_controller2 = std::make_unique<GainController2>( 309 CreateEnvironment(), Agc2Config{}, InputVolumeControllerConfig{}, 310 /*sample_rate_hz=*/16000, /*num_channels=*/2, 311 /*use_internal_vad=*/true); 312 EXPECT_TRUE(gain_controller2.get()); 313 } 314 315 TEST(GainController2FixedDigital, GainShouldChangeOnSetGain) { 316 constexpr float kInputLevel = 1000.0f; 317 constexpr size_t kNumFrames = 5; 318 constexpr size_t kSampleRateHz = 8000; 319 constexpr float kGain0Db = 0.0f; 320 constexpr float kGain20Db = 20.0f; 321 322 auto agc2_fixed = CreateAgc2FixedDigitalMode(kGain0Db, kSampleRateHz); 323 324 // Signal level is unchanged with 0 db gain. 325 EXPECT_FLOAT_EQ(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel, kNumFrames, 326 kSampleRateHz), 327 kInputLevel); 328 329 // +20 db should increase signal by a factor of 10. 330 agc2_fixed->SetFixedGainDb(kGain20Db); 331 EXPECT_FLOAT_EQ(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel, kNumFrames, 332 kSampleRateHz), 333 kInputLevel * 10); 334 } 335 336 TEST(GainController2FixedDigital, ChangeFixedGainShouldBeFastAndTimeInvariant) { 337 // Number of frames required for the fixed gain controller to adapt on the 338 // input signal when the gain changes. 339 constexpr size_t kNumFrames = 5; 340 341 constexpr float kInputLevel = 1000.0f; 342 constexpr size_t kSampleRateHz = 8000; 343 constexpr float kGainDbLow = 0.0f; 344 constexpr float kGainDbHigh = 25.0f; 345 static_assert(kGainDbLow < kGainDbHigh, ""); 346 347 auto agc2_fixed = CreateAgc2FixedDigitalMode(kGainDbLow, kSampleRateHz); 348 349 // Start with a lower gain. 350 const float output_level_pre = RunAgc2WithConstantInput( 351 *agc2_fixed, kInputLevel, kNumFrames, kSampleRateHz); 352 353 // Increase gain. 354 agc2_fixed->SetFixedGainDb(kGainDbHigh); 355 static_cast<void>(RunAgc2WithConstantInput(*agc2_fixed, kInputLevel, 356 kNumFrames, kSampleRateHz)); 357 358 // Back to the lower gain. 359 agc2_fixed->SetFixedGainDb(kGainDbLow); 360 const float output_level_post = RunAgc2WithConstantInput( 361 *agc2_fixed, kInputLevel, kNumFrames, kSampleRateHz); 362 363 EXPECT_EQ(output_level_pre, output_level_post); 364 } 365 366 class FixedDigitalTest 367 : public ::testing::TestWithParam<std::tuple<float, float, int, bool>> { 368 protected: 369 float gain_db_min() const { return std::get<0>(GetParam()); } 370 float gain_db_max() const { return std::get<1>(GetParam()); } 371 int sample_rate_hz() const { return std::get<2>(GetParam()); } 372 bool saturation_expected() const { return std::get<3>(GetParam()); } 373 }; 374 375 TEST_P(FixedDigitalTest, CheckSaturationBehaviorWithLimiter) { 376 for (const float gain_db : test::LinSpace(gain_db_min(), gain_db_max(), 10)) { 377 SCOPED_TRACE(gain_db); 378 auto agc2_fixed = CreateAgc2FixedDigitalMode(gain_db, sample_rate_hz()); 379 const float processed_sample = 380 RunAgc2WithConstantInput(*agc2_fixed, /*input_level=*/32767.0f, 381 /*num_frames=*/5, sample_rate_hz()); 382 if (saturation_expected()) { 383 EXPECT_FLOAT_EQ(processed_sample, 32767.0f); 384 } else { 385 EXPECT_LT(processed_sample, 32767.0f); 386 } 387 } 388 } 389 390 static_assert(test::kLimiterMaxInputLevelDbFs < 10, ""); 391 INSTANTIATE_TEST_SUITE_P( 392 GainController2, 393 FixedDigitalTest, 394 ::testing::Values( 395 // When gain < `test::kLimiterMaxInputLevelDbFs`, the limiter will not 396 // saturate the signal (at any sample rate). 397 std::make_tuple(0.1f, 398 test::kLimiterMaxInputLevelDbFs - 0.01f, 399 8000, 400 false), 401 std::make_tuple(0.1, 402 test::kLimiterMaxInputLevelDbFs - 0.01f, 403 48000, 404 false), 405 // When gain > `test::kLimiterMaxInputLevelDbFs`, the limiter will 406 // saturate the signal (at any sample rate). 407 std::make_tuple(test::kLimiterMaxInputLevelDbFs + 0.01f, 408 10.0f, 409 8000, 410 true), 411 std::make_tuple(test::kLimiterMaxInputLevelDbFs + 0.01f, 412 10.0f, 413 48000, 414 true))); 415 416 // Processes a test audio file and checks that the gain applied at the end of 417 // the recording is close to the expected value. 418 TEST(GainController2, CheckFinalGainWithAdaptiveDigitalController) { 419 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz; 420 constexpr int kStereo = 2; 421 422 // Create AGC2 enabling only the adaptive digital controller. 423 Agc2Config config; 424 config.fixed_digital.gain_db = 0.0f; 425 config.adaptive_digital.enabled = true; 426 GainController2 agc2(CreateEnvironment(), config, 427 /*input_volume_controller_config=*/{}, kSampleRateHz, 428 kStereo, 429 /*use_internal_vad=*/true); 430 431 test::InputAudioFile input_file( 432 test::GetApmCaptureTestVectorFileName(kSampleRateHz), 433 /*loop_at_end=*/true); 434 const StreamConfig stream_config(kSampleRateHz, kStereo); 435 436 // Init buffers. 437 constexpr int kFrameDurationMs = 10; 438 std::vector<float> frame(kStereo * stream_config.num_frames()); 439 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo, 440 kSampleRateHz, kStereo); 441 442 // Simulate. 443 constexpr float kGainDb = -6.0f; 444 const float gain = std::pow(10.0f, kGainDb / 20.0f); 445 constexpr int kDurationMs = 10000; 446 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs; 447 for (int i = 0; i < kNumFramesToProcess; ++i) { 448 ReadFloatSamplesFromStereoFile(stream_config.num_frames(), 449 stream_config.num_channels(), &input_file, 450 frame); 451 // Apply a fixed gain to the input audio. 452 for (float& x : frame) { 453 x *= gain; 454 } 455 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer); 456 agc2.Process(/*speech_probability=*/std::nullopt, 457 /*input_volume_changed=*/false, &audio_buffer); 458 } 459 460 // Estimate the applied gain by processing a probing frame. 461 SetAudioBufferSamples(/*value=*/1.0f, audio_buffer); 462 agc2.Process(/*speech_probability=*/std::nullopt, 463 /*input_volume_changed=*/false, &audio_buffer); 464 const float applied_gain_db = 465 20.0f * std::log10(audio_buffer.channels_const()[0][0]); 466 467 constexpr float kExpectedGainDb = 7.0f; 468 constexpr float kToleranceDb = 0.3f; 469 EXPECT_NEAR(applied_gain_db, kExpectedGainDb, kToleranceDb); 470 } 471 472 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 473 // Checks that `GainController2` crashes in debug mode if it runs its internal 474 // VAD and the speech probability values are provided by the caller. 475 TEST(GainController2DeathTest, 476 DebugCrashIfUseInternalVadAndSpeechProbabilityGiven) { 477 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz; 478 constexpr int kStereo = 2; 479 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo, 480 kSampleRateHz, kStereo); 481 // Create AGC2 so that the interval VAD is also created. 482 GainController2 agc2( 483 CreateEnvironment(), /*config=*/{.adaptive_digital = {.enabled = true}}, 484 /*input_volume_controller_config=*/{}, kSampleRateHz, kStereo, 485 /*use_internal_vad=*/true); 486 487 EXPECT_DEATH(agc2.Process(/*speech_probability=*/0.123f, 488 /*input_volume_changed=*/false, &audio_buffer), 489 ""); 490 } 491 #endif 492 493 // Processes a test audio file and checks that the injected speech probability 494 // is not ignored when the internal VAD is not used. 495 TEST(GainController2, 496 CheckInjectedVadProbabilityUsedWithAdaptiveDigitalController) { 497 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz; 498 constexpr int kStereo = 2; 499 500 // Create AGC2 enabling only the adaptive digital controller. 501 const Environment env = CreateEnvironment(); 502 Agc2Config config; 503 config.fixed_digital.gain_db = 0.0f; 504 config.adaptive_digital.enabled = true; 505 GainController2 agc2(env, config, /*input_volume_controller_config=*/{}, 506 kSampleRateHz, kStereo, 507 /*use_internal_vad=*/false); 508 GainController2 agc2_reference(env, config, 509 /*input_volume_controller_config=*/{}, 510 kSampleRateHz, kStereo, 511 /*use_internal_vad=*/true); 512 513 test::InputAudioFile input_file( 514 test::GetApmCaptureTestVectorFileName(kSampleRateHz), 515 /*loop_at_end=*/true); 516 const StreamConfig stream_config(kSampleRateHz, kStereo); 517 518 // Init buffers. 519 constexpr int kFrameDurationMs = 10; 520 std::vector<float> frame(kStereo * stream_config.num_frames()); 521 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo, 522 kSampleRateHz, kStereo); 523 AudioBuffer audio_buffer_reference(kSampleRateHz, kStereo, kSampleRateHz, 524 kStereo, kSampleRateHz, kStereo); 525 // Simulate. 526 constexpr float kGainDb = -6.0f; 527 const float gain = std::pow(10.0f, kGainDb / 20.0f); 528 constexpr int kDurationMs = 10000; 529 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs; 530 constexpr float kSpeechProbabilities[] = {1.0f, 0.3f}; 531 constexpr float kEpsilon = 0.0001f; 532 bool all_samples_zero = true; 533 bool all_samples_equal = true; 534 for (int i = 0, j = 0; i < kNumFramesToProcess; ++i, j = 1 - j) { 535 ReadFloatSamplesFromStereoFile(stream_config.num_frames(), 536 stream_config.num_channels(), &input_file, 537 frame); 538 // Apply a fixed gain to the input audio. 539 for (float& x : frame) { 540 x *= gain; 541 } 542 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer); 543 agc2.Process(kSpeechProbabilities[j], /*input_volume_changed=*/false, 544 &audio_buffer); 545 test::CopyVectorToAudioBuffer(stream_config, frame, 546 &audio_buffer_reference); 547 agc2_reference.Process(/*speech_probability=*/std::nullopt, 548 /*input_volume_changed=*/false, 549 &audio_buffer_reference); 550 // Check the output buffers. 551 for (int channel = 0; channel < kStereo; ++channel) { 552 for (int frame_num = 0; 553 frame_num < static_cast<int>(audio_buffer.num_frames()); 554 ++frame_num) { 555 all_samples_zero &= 556 fabs(audio_buffer.channels_const()[channel][frame_num]) < kEpsilon; 557 all_samples_equal &= 558 fabs(audio_buffer.channels_const()[channel][frame_num] - 559 audio_buffer_reference.channels_const()[channel][frame_num]) < 560 kEpsilon; 561 } 562 } 563 } 564 EXPECT_FALSE(all_samples_zero); 565 EXPECT_FALSE(all_samples_equal); 566 } 567 568 // Processes a test audio file and checks that the output is equal when 569 // an injected speech probability from `VoiceActivityDetectorWrapper` and 570 // the speech probability computed by the internal VAD are the same. 571 TEST(GainController2, 572 CheckEqualResultFromInjectedVadProbabilityWithAdaptiveDigitalController) { 573 constexpr int kSampleRateHz = AudioProcessing::kSampleRate48kHz; 574 constexpr int kStereo = 2; 575 576 // Create AGC2 enabling only the adaptive digital controller. 577 const Environment env = CreateEnvironment(); 578 Agc2Config config; 579 config.fixed_digital.gain_db = 0.0f; 580 config.adaptive_digital.enabled = true; 581 GainController2 agc2(env, config, /*input_volume_controller_config=*/{}, 582 kSampleRateHz, kStereo, 583 /*use_internal_vad=*/false); 584 GainController2 agc2_reference(env, config, 585 /*input_volume_controller_config=*/{}, 586 kSampleRateHz, kStereo, 587 /*use_internal_vad=*/true); 588 VoiceActivityDetectorWrapper vad(GetAvailableCpuFeatures(), kSampleRateHz); 589 test::InputAudioFile input_file( 590 test::GetApmCaptureTestVectorFileName(kSampleRateHz), 591 /*loop_at_end=*/true); 592 const StreamConfig stream_config(kSampleRateHz, kStereo); 593 594 // Init buffers. 595 constexpr int kFrameDurationMs = 10; 596 std::vector<float> frame(kStereo * stream_config.num_frames()); 597 AudioBuffer audio_buffer(kSampleRateHz, kStereo, kSampleRateHz, kStereo, 598 kSampleRateHz, kStereo); 599 AudioBuffer audio_buffer_reference(kSampleRateHz, kStereo, kSampleRateHz, 600 kStereo, kSampleRateHz, kStereo); 601 602 // Simulate. 603 constexpr float kGainDb = -6.0f; 604 const float gain = std::pow(10.0f, kGainDb / 20.0f); 605 constexpr int kDurationMs = 10000; 606 constexpr int kNumFramesToProcess = kDurationMs / kFrameDurationMs; 607 for (int i = 0; i < kNumFramesToProcess; ++i) { 608 ReadFloatSamplesFromStereoFile(stream_config.num_frames(), 609 stream_config.num_channels(), &input_file, 610 frame); 611 // Apply a fixed gain to the input audio. 612 for (float& x : frame) { 613 x *= gain; 614 } 615 test::CopyVectorToAudioBuffer(stream_config, frame, 616 &audio_buffer_reference); 617 agc2_reference.Process(std::nullopt, /*input_volume_changed=*/false, 618 &audio_buffer_reference); 619 test::CopyVectorToAudioBuffer(stream_config, frame, &audio_buffer); 620 float speech_probability = vad.Analyze(audio_buffer.view()); 621 agc2.Process(speech_probability, /*input_volume_changed=*/false, 622 &audio_buffer); 623 // Check the output buffer. 624 for (int channel = 0; channel < kStereo; ++channel) { 625 for (int frame_num = 0; 626 frame_num < static_cast<int>(audio_buffer.num_frames()); 627 ++frame_num) { 628 EXPECT_FLOAT_EQ( 629 audio_buffer.channels_const()[channel][frame_num], 630 audio_buffer_reference.channels_const()[channel][frame_num]); 631 } 632 } 633 } 634 } 635 636 } // namespace test 637 } // namespace webrtc