1 /*
2 * Copyright (c) 2014 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/audio_processing_impl.h"
12
13 #include <array>
14 #include <memory>
15 #include <tuple>
16
17 #include "absl/types/optional.h"
18 #include "api/make_ref_counted.h"
19 #include "api/scoped_refptr.h"
20 #include "modules/audio_processing/include/audio_processing.h"
21 #include "modules/audio_processing/optionally_built_submodule_creators.h"
22 #include "modules/audio_processing/test/audio_processing_builder_for_testing.h"
23 #include "modules/audio_processing/test/echo_canceller_test_tools.h"
24 #include "modules/audio_processing/test/echo_control_mock.h"
25 #include "modules/audio_processing/test/test_utils.h"
26 #include "rtc_base/checks.h"
27 #include "rtc_base/random.h"
28 #include "rtc_base/strings/string_builder.h"
29 #include "test/field_trial.h"
30 #include "test/gmock.h"
31 #include "test/gtest.h"
32
33 namespace webrtc {
34 namespace {
35
36 using ::testing::Invoke;
37 using ::testing::NotNull;
38
39 class MockInitialize : public AudioProcessingImpl {
40 public:
MockInitialize()41 MockInitialize() : AudioProcessingImpl() {}
42
43 MOCK_METHOD(void, InitializeLocked, (), (override));
RealInitializeLocked()44 void RealInitializeLocked() {
45 AssertLockedForTest();
46 AudioProcessingImpl::InitializeLocked();
47 }
48
49 MOCK_METHOD(void, AddRef, (), (const, override));
50 MOCK_METHOD(rtc::RefCountReleaseStatus, Release, (), (const, override));
51 };
52
53 // Creates MockEchoControl instances and provides a raw pointer access to
54 // the next created one. The raw pointer is meant to be used with gmock.
55 // Returning a pointer of the next created MockEchoControl instance is necessary
56 // for the following reasons: (i) gmock expectations must be set before any call
57 // occurs, (ii) APM is initialized the first time that
58 // AudioProcessingImpl::ProcessStream() is called and the initialization leads
59 // to the creation of a new EchoControl object.
60 class MockEchoControlFactory : public EchoControlFactory {
61 public:
MockEchoControlFactory()62 MockEchoControlFactory() : next_mock_(std::make_unique<MockEchoControl>()) {}
63 // Returns a pointer to the next MockEchoControl that this factory creates.
GetNext() const64 MockEchoControl* GetNext() const { return next_mock_.get(); }
Create(int sample_rate_hz,int num_render_channels,int num_capture_channels)65 std::unique_ptr<EchoControl> Create(int sample_rate_hz,
66 int num_render_channels,
67 int num_capture_channels) override {
68 std::unique_ptr<EchoControl> mock = std::move(next_mock_);
69 next_mock_ = std::make_unique<MockEchoControl>();
70 return mock;
71 }
72
73 private:
74 std::unique_ptr<MockEchoControl> next_mock_;
75 };
76
77 // Mocks EchoDetector and records the first samples of the last analyzed render
78 // stream frame. Used to check what data is read by an EchoDetector
79 // implementation injected into an APM.
80 class TestEchoDetector : public EchoDetector {
81 public:
TestEchoDetector()82 TestEchoDetector()
83 : analyze_render_audio_called_(false),
84 last_render_audio_first_sample_(0.f) {}
85 ~TestEchoDetector() override = default;
AnalyzeRenderAudio(rtc::ArrayView<const float> render_audio)86 void AnalyzeRenderAudio(rtc::ArrayView<const float> render_audio) override {
87 last_render_audio_first_sample_ = render_audio[0];
88 analyze_render_audio_called_ = true;
89 }
AnalyzeCaptureAudio(rtc::ArrayView<const float> capture_audio)90 void AnalyzeCaptureAudio(rtc::ArrayView<const float> capture_audio) override {
91 }
Initialize(int capture_sample_rate_hz,int num_capture_channels,int render_sample_rate_hz,int num_render_channels)92 void Initialize(int capture_sample_rate_hz,
93 int num_capture_channels,
94 int render_sample_rate_hz,
95 int num_render_channels) override {}
GetMetrics() const96 EchoDetector::Metrics GetMetrics() const override { return {}; }
97 // Returns true if AnalyzeRenderAudio() has been called at least once.
analyze_render_audio_called() const98 bool analyze_render_audio_called() const {
99 return analyze_render_audio_called_;
100 }
101 // Returns the first sample of the last analyzed render frame.
last_render_audio_first_sample() const102 float last_render_audio_first_sample() const {
103 return last_render_audio_first_sample_;
104 }
105
106 private:
107 bool analyze_render_audio_called_;
108 float last_render_audio_first_sample_;
109 };
110
111 // Mocks CustomProcessing and applies ProcessSample() to all the samples.
112 // Meant to be injected into an APM to modify samples in a known and detectable
113 // way.
114 class TestRenderPreProcessor : public CustomProcessing {
115 public:
116 TestRenderPreProcessor() = default;
117 ~TestRenderPreProcessor() = default;
Initialize(int sample_rate_hz,int num_channels)118 void Initialize(int sample_rate_hz, int num_channels) override {}
Process(AudioBuffer * audio)119 void Process(AudioBuffer* audio) override {
120 for (size_t k = 0; k < audio->num_channels(); ++k) {
121 rtc::ArrayView<float> channel_view(audio->channels()[k],
122 audio->num_frames());
123 std::transform(channel_view.begin(), channel_view.end(),
124 channel_view.begin(), ProcessSample);
125 }
126 }
ToString() const127 std::string ToString() const override { return "TestRenderPreProcessor"; }
SetRuntimeSetting(AudioProcessing::RuntimeSetting setting)128 void SetRuntimeSetting(AudioProcessing::RuntimeSetting setting) override {}
129 // Modifies a sample. This member is used in Process() to modify a frame and
130 // it is publicly visible to enable tests.
ProcessSample(float x)131 static constexpr float ProcessSample(float x) { return 2.f * x; }
132 };
133
134 // Creates a simple `AudioProcessing` instance for APM input volume testing
135 // with AGC1 analog and/or AGC2 input volume controller enabled and AGC2
136 // digital controller enabled.
CreateApmForInputVolumeTest(bool agc1_analog_gain_controller_enabled,bool agc2_input_volume_controller_enabled)137 rtc::scoped_refptr<AudioProcessing> CreateApmForInputVolumeTest(
138 bool agc1_analog_gain_controller_enabled,
139 bool agc2_input_volume_controller_enabled) {
140 webrtc::AudioProcessing::Config config;
141 // Enable AGC1 analog controller.
142 config.gain_controller1.enabled = agc1_analog_gain_controller_enabled;
143 config.gain_controller1.analog_gain_controller.enabled =
144 agc1_analog_gain_controller_enabled;
145 // Enable AG2 input volume controller
146 config.gain_controller2.input_volume_controller.enabled =
147 agc2_input_volume_controller_enabled;
148 // Enable AGC2 adaptive digital controller.
149 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
150 false;
151 config.gain_controller2.enabled = true;
152 config.gain_controller2.adaptive_digital.enabled = true;
153
154 auto apm(AudioProcessingBuilder().Create());
155 apm->ApplyConfig(config);
156
157 return apm;
158 }
159
160 // Runs `apm` input processing for volume adjustments for `num_frames` random
161 // frames starting from the volume `initial_volume`. This includes three steps:
162 // 1) Set the input volume 2) Process the stream 3) Set the new recommended
163 // input volume. Returns the new recommended input volume.
ProcessInputVolume(AudioProcessing & apm,int num_frames,int initial_volume)164 int ProcessInputVolume(AudioProcessing& apm,
165 int num_frames,
166 int initial_volume) {
167 constexpr int kSampleRateHz = 48000;
168 constexpr int kNumChannels = 1;
169 std::array<float, kSampleRateHz / 100> buffer;
170 float* channel_pointers[] = {buffer.data()};
171 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
172 /*num_channels=*/kNumChannels);
173 int recommended_input_volume = initial_volume;
174 for (int i = 0; i < num_frames; ++i) {
175 Random random_generator(2341U);
176 RandomizeSampleVector(&random_generator, buffer);
177
178 apm.set_stream_analog_level(recommended_input_volume);
179 apm.ProcessStream(channel_pointers, stream_config, stream_config,
180 channel_pointers);
181 recommended_input_volume = apm.recommended_stream_analog_level();
182 }
183 return recommended_input_volume;
184 }
185
186 constexpr char kMinMicLevelFieldTrial[] =
187 "WebRTC-Audio-2ndAgcMinMicLevelExperiment";
188 constexpr char kMinInputVolumeFieldTrial[] = "WebRTC-Audio-Agc2-MinInputVolume";
189 constexpr int kMinInputVolume = 12;
190
GetMinMicLevelExperimentFieldTrial(absl::optional<int> value)191 std::string GetMinMicLevelExperimentFieldTrial(absl::optional<int> value) {
192 char field_trial_buffer[128];
193 rtc::SimpleStringBuilder builder(field_trial_buffer);
194 if (value.has_value()) {
195 RTC_DCHECK_GE(*value, 0);
196 RTC_DCHECK_LE(*value, 255);
197 builder << kMinMicLevelFieldTrial << "/Enabled-" << *value << "/";
198 builder << kMinInputVolumeFieldTrial << "/Enabled-" << *value << "/";
199 } else {
200 builder << kMinMicLevelFieldTrial << "/Disabled/";
201 builder << kMinInputVolumeFieldTrial << "/Disabled/";
202 }
203 return builder.str();
204 }
205
206 // TODO(webrtc:7494): Remove the fieldtrial from the input volume tests when
207 // "WebRTC-Audio-2ndAgcMinMicLevelExperiment" and
208 // "WebRTC-Audio-Agc2-MinInputVolume" are removed.
209 class InputVolumeStartupParameterizedTest
210 : public ::testing::TestWithParam<
211 std::tuple<int, absl::optional<int>, bool, bool>> {
212 protected:
InputVolumeStartupParameterizedTest()213 InputVolumeStartupParameterizedTest()
214 : field_trials_(
215 GetMinMicLevelExperimentFieldTrial(std::get<1>(GetParam()))) {}
GetStartupVolume() const216 int GetStartupVolume() const { return std::get<0>(GetParam()); }
GetMinVolume() const217 int GetMinVolume() const {
218 return std::get<1>(GetParam()).value_or(kMinInputVolume);
219 }
GetAgc1AnalogControllerEnabled() const220 bool GetAgc1AnalogControllerEnabled() const {
221 return std::get<2>(GetParam());
222 }
GetAgc2InputVolumeControllerEnabled() const223 bool GetAgc2InputVolumeControllerEnabled() const {
224 return std::get<3>(GetParam());
225 }
226
227 private:
228 test::ScopedFieldTrials field_trials_;
229 };
230
231 class InputVolumeNotZeroParameterizedTest
232 : public ::testing::TestWithParam<
233 std::tuple<int, int, absl::optional<int>, bool, bool>> {
234 protected:
InputVolumeNotZeroParameterizedTest()235 InputVolumeNotZeroParameterizedTest()
236 : field_trials_(
237 GetMinMicLevelExperimentFieldTrial(std::get<2>(GetParam()))) {}
GetStartupVolume() const238 int GetStartupVolume() const { return std::get<0>(GetParam()); }
GetVolume() const239 int GetVolume() const { return std::get<1>(GetParam()); }
GetMinVolume() const240 int GetMinVolume() const {
241 return std::get<2>(GetParam()).value_or(kMinInputVolume);
242 }
GetMinMicLevelExperimentEnabled()243 bool GetMinMicLevelExperimentEnabled() {
244 return std::get<2>(GetParam()).has_value();
245 }
GetAgc1AnalogControllerEnabled() const246 bool GetAgc1AnalogControllerEnabled() const {
247 return std::get<3>(GetParam());
248 }
GetAgc2InputVolumeControllerEnabled() const249 bool GetAgc2InputVolumeControllerEnabled() const {
250 return std::get<4>(GetParam());
251 }
252
253 private:
254 test::ScopedFieldTrials field_trials_;
255 };
256
257 class InputVolumeZeroParameterizedTest
258 : public ::testing::TestWithParam<
259 std::tuple<int, absl::optional<int>, bool, bool>> {
260 protected:
InputVolumeZeroParameterizedTest()261 InputVolumeZeroParameterizedTest()
262 : field_trials_(
263 GetMinMicLevelExperimentFieldTrial(std::get<1>(GetParam()))) {}
GetStartupVolume() const264 int GetStartupVolume() const { return std::get<0>(GetParam()); }
GetMinVolume() const265 int GetMinVolume() const {
266 return std::get<1>(GetParam()).value_or(kMinInputVolume);
267 }
GetAgc1AnalogControllerEnabled() const268 bool GetAgc1AnalogControllerEnabled() const {
269 return std::get<2>(GetParam());
270 }
GetAgc2InputVolumeControllerEnabled() const271 bool GetAgc2InputVolumeControllerEnabled() const {
272 return std::get<3>(GetParam());
273 }
274
275 private:
276 test::ScopedFieldTrials field_trials_;
277 };
278
279 } // namespace
280
TEST(AudioProcessingImplTest,AudioParameterChangeTriggersInit)281 TEST(AudioProcessingImplTest, AudioParameterChangeTriggersInit) {
282 MockInitialize mock;
283 ON_CALL(mock, InitializeLocked)
284 .WillByDefault(Invoke(&mock, &MockInitialize::RealInitializeLocked));
285
286 EXPECT_CALL(mock, InitializeLocked).Times(1);
287 mock.Initialize();
288
289 constexpr size_t kMaxSampleRateHz = 32000;
290 constexpr size_t kMaxNumChannels = 2;
291 std::array<int16_t, kMaxNumChannels * kMaxSampleRateHz / 100> frame;
292 frame.fill(0);
293 StreamConfig config(16000, 1);
294 // Call with the default parameters; there should be an init.
295 EXPECT_CALL(mock, InitializeLocked).Times(0);
296 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
297 EXPECT_NOERR(
298 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
299
300 // New sample rate. (Only impacts ProcessStream).
301 config = StreamConfig(32000, 1);
302 EXPECT_CALL(mock, InitializeLocked).Times(1);
303 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
304
305 // New number of channels.
306 config = StreamConfig(32000, 2);
307 EXPECT_CALL(mock, InitializeLocked).Times(2);
308 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
309 EXPECT_NOERR(
310 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
311
312 // A new sample rate passed to ProcessReverseStream should cause an init.
313 config = StreamConfig(16000, 2);
314 EXPECT_CALL(mock, InitializeLocked).Times(1);
315 EXPECT_NOERR(
316 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
317 }
318
TEST(AudioProcessingImplTest,UpdateCapturePreGainRuntimeSetting)319 TEST(AudioProcessingImplTest, UpdateCapturePreGainRuntimeSetting) {
320 rtc::scoped_refptr<AudioProcessing> apm =
321 AudioProcessingBuilderForTesting().Create();
322 webrtc::AudioProcessing::Config apm_config;
323 apm_config.pre_amplifier.enabled = true;
324 apm_config.pre_amplifier.fixed_gain_factor = 1.f;
325 apm->ApplyConfig(apm_config);
326
327 constexpr int kSampleRateHz = 48000;
328 constexpr int16_t kAudioLevel = 10000;
329 constexpr size_t kNumChannels = 2;
330
331 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
332 StreamConfig config(kSampleRateHz, kNumChannels);
333 frame.fill(kAudioLevel);
334 apm->ProcessStream(frame.data(), config, config, frame.data());
335 EXPECT_EQ(frame[100], kAudioLevel)
336 << "With factor 1, frame shouldn't be modified.";
337
338 constexpr float kGainFactor = 2.f;
339 apm->SetRuntimeSetting(
340 AudioProcessing::RuntimeSetting::CreateCapturePreGain(kGainFactor));
341
342 // Process for two frames to have time to ramp up gain.
343 for (int i = 0; i < 2; ++i) {
344 frame.fill(kAudioLevel);
345 apm->ProcessStream(frame.data(), config, config, frame.data());
346 }
347 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
348 << "Frame should be amplified.";
349 }
350
TEST(AudioProcessingImplTest,LevelAdjustmentUpdateCapturePreGainRuntimeSetting)351 TEST(AudioProcessingImplTest,
352 LevelAdjustmentUpdateCapturePreGainRuntimeSetting) {
353 rtc::scoped_refptr<AudioProcessing> apm =
354 AudioProcessingBuilderForTesting().Create();
355 webrtc::AudioProcessing::Config apm_config;
356 apm_config.capture_level_adjustment.enabled = true;
357 apm_config.capture_level_adjustment.pre_gain_factor = 1.f;
358 apm->ApplyConfig(apm_config);
359
360 constexpr int kSampleRateHz = 48000;
361 constexpr int16_t kAudioLevel = 10000;
362 constexpr size_t kNumChannels = 2;
363
364 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
365 StreamConfig config(kSampleRateHz, kNumChannels);
366 frame.fill(kAudioLevel);
367 apm->ProcessStream(frame.data(), config, config, frame.data());
368 EXPECT_EQ(frame[100], kAudioLevel)
369 << "With factor 1, frame shouldn't be modified.";
370
371 constexpr float kGainFactor = 2.f;
372 apm->SetRuntimeSetting(
373 AudioProcessing::RuntimeSetting::CreateCapturePreGain(kGainFactor));
374
375 // Process for two frames to have time to ramp up gain.
376 for (int i = 0; i < 2; ++i) {
377 frame.fill(kAudioLevel);
378 apm->ProcessStream(frame.data(), config, config, frame.data());
379 }
380 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
381 << "Frame should be amplified.";
382 }
383
TEST(AudioProcessingImplTest,LevelAdjustmentUpdateCapturePostGainRuntimeSetting)384 TEST(AudioProcessingImplTest,
385 LevelAdjustmentUpdateCapturePostGainRuntimeSetting) {
386 rtc::scoped_refptr<AudioProcessing> apm =
387 AudioProcessingBuilderForTesting().Create();
388 webrtc::AudioProcessing::Config apm_config;
389 apm_config.capture_level_adjustment.enabled = true;
390 apm_config.capture_level_adjustment.post_gain_factor = 1.f;
391 apm->ApplyConfig(apm_config);
392
393 constexpr int kSampleRateHz = 48000;
394 constexpr int16_t kAudioLevel = 10000;
395 constexpr size_t kNumChannels = 2;
396
397 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
398 StreamConfig config(kSampleRateHz, kNumChannels);
399 frame.fill(kAudioLevel);
400 apm->ProcessStream(frame.data(), config, config, frame.data());
401 EXPECT_EQ(frame[100], kAudioLevel)
402 << "With factor 1, frame shouldn't be modified.";
403
404 constexpr float kGainFactor = 2.f;
405 apm->SetRuntimeSetting(
406 AudioProcessing::RuntimeSetting::CreateCapturePostGain(kGainFactor));
407
408 // Process for two frames to have time to ramp up gain.
409 for (int i = 0; i < 2; ++i) {
410 frame.fill(kAudioLevel);
411 apm->ProcessStream(frame.data(), config, config, frame.data());
412 }
413 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
414 << "Frame should be amplified.";
415 }
416
TEST(AudioProcessingImplTest,EchoControllerObservesSetCaptureUsageChange)417 TEST(AudioProcessingImplTest, EchoControllerObservesSetCaptureUsageChange) {
418 // Tests that the echo controller observes that the capture usage has been
419 // updated.
420 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
421 const MockEchoControlFactory* echo_control_factory_ptr =
422 echo_control_factory.get();
423
424 rtc::scoped_refptr<AudioProcessing> apm =
425 AudioProcessingBuilderForTesting()
426 .SetEchoControlFactory(std::move(echo_control_factory))
427 .Create();
428
429 constexpr int16_t kAudioLevel = 10000;
430 constexpr int kSampleRateHz = 48000;
431 constexpr int kNumChannels = 2;
432 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
433 StreamConfig config(kSampleRateHz, kNumChannels);
434 frame.fill(kAudioLevel);
435
436 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
437
438 // Ensure that SetCaptureOutputUsage is not called when no runtime settings
439 // are passed.
440 EXPECT_CALL(*echo_control_mock, SetCaptureOutputUsage(testing::_)).Times(0);
441 apm->ProcessStream(frame.data(), config, config, frame.data());
442
443 // Ensure that SetCaptureOutputUsage is called with the right information when
444 // a runtime setting is passed.
445 EXPECT_CALL(*echo_control_mock,
446 SetCaptureOutputUsage(/*capture_output_used=*/false))
447 .Times(1);
448 EXPECT_TRUE(apm->PostRuntimeSetting(
449 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
450 /*capture_output_used=*/false)));
451 apm->ProcessStream(frame.data(), config, config, frame.data());
452
453 EXPECT_CALL(*echo_control_mock,
454 SetCaptureOutputUsage(/*capture_output_used=*/true))
455 .Times(1);
456 EXPECT_TRUE(apm->PostRuntimeSetting(
457 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
458 /*capture_output_used=*/true)));
459 apm->ProcessStream(frame.data(), config, config, frame.data());
460
461 // The number of positions to place items in the queue is equal to the queue
462 // size minus 1.
463 constexpr int kNumSlotsInQueue = RuntimeSettingQueueSize();
464
465 // Ensure that SetCaptureOutputUsage is called with the right information when
466 // many runtime settings are passed.
467 for (int k = 0; k < kNumSlotsInQueue - 1; ++k) {
468 EXPECT_TRUE(apm->PostRuntimeSetting(
469 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
470 /*capture_output_used=*/false)));
471 }
472 EXPECT_CALL(*echo_control_mock,
473 SetCaptureOutputUsage(/*capture_output_used=*/false))
474 .Times(kNumSlotsInQueue - 1);
475 apm->ProcessStream(frame.data(), config, config, frame.data());
476
477 // Ensure that SetCaptureOutputUsage is properly called with the fallback
478 // value when the runtime settings queue becomes full.
479 for (int k = 0; k < kNumSlotsInQueue; ++k) {
480 EXPECT_TRUE(apm->PostRuntimeSetting(
481 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
482 /*capture_output_used=*/false)));
483 }
484 EXPECT_FALSE(apm->PostRuntimeSetting(
485 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
486 /*capture_output_used=*/false)));
487 EXPECT_FALSE(apm->PostRuntimeSetting(
488 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
489 /*capture_output_used=*/false)));
490 EXPECT_CALL(*echo_control_mock,
491 SetCaptureOutputUsage(/*capture_output_used=*/false))
492 .Times(kNumSlotsInQueue);
493 EXPECT_CALL(*echo_control_mock,
494 SetCaptureOutputUsage(/*capture_output_used=*/true))
495 .Times(1);
496 apm->ProcessStream(frame.data(), config, config, frame.data());
497 }
498
TEST(AudioProcessingImplTest,EchoControllerObservesPreAmplifierEchoPathGainChange)499 TEST(AudioProcessingImplTest,
500 EchoControllerObservesPreAmplifierEchoPathGainChange) {
501 // Tests that the echo controller observes an echo path gain change when the
502 // pre-amplifier submodule changes the gain.
503 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
504 const auto* echo_control_factory_ptr = echo_control_factory.get();
505
506 rtc::scoped_refptr<AudioProcessing> apm =
507 AudioProcessingBuilderForTesting()
508 .SetEchoControlFactory(std::move(echo_control_factory))
509 .Create();
510 // Disable AGC.
511 webrtc::AudioProcessing::Config apm_config;
512 apm_config.gain_controller1.enabled = false;
513 apm_config.gain_controller2.enabled = false;
514 apm_config.pre_amplifier.enabled = true;
515 apm_config.pre_amplifier.fixed_gain_factor = 1.f;
516 apm->ApplyConfig(apm_config);
517
518 constexpr int16_t kAudioLevel = 10000;
519 constexpr size_t kSampleRateHz = 48000;
520 constexpr size_t kNumChannels = 2;
521 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
522 StreamConfig config(kSampleRateHz, kNumChannels);
523 frame.fill(kAudioLevel);
524
525 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
526
527 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
528 EXPECT_CALL(*echo_control_mock,
529 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
530 .Times(1);
531 apm->ProcessStream(frame.data(), config, config, frame.data());
532
533 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
534 EXPECT_CALL(*echo_control_mock,
535 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
536 .Times(1);
537 apm->SetRuntimeSetting(
538 AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
539 apm->ProcessStream(frame.data(), config, config, frame.data());
540 }
541
TEST(AudioProcessingImplTest,EchoControllerObservesLevelAdjustmentPreGainEchoPathGainChange)542 TEST(AudioProcessingImplTest,
543 EchoControllerObservesLevelAdjustmentPreGainEchoPathGainChange) {
544 // Tests that the echo controller observes an echo path gain change when the
545 // pre-amplifier submodule changes the gain.
546 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
547 const auto* echo_control_factory_ptr = echo_control_factory.get();
548
549 rtc::scoped_refptr<AudioProcessing> apm =
550 AudioProcessingBuilderForTesting()
551 .SetEchoControlFactory(std::move(echo_control_factory))
552 .Create();
553 // Disable AGC.
554 webrtc::AudioProcessing::Config apm_config;
555 apm_config.gain_controller1.enabled = false;
556 apm_config.gain_controller2.enabled = false;
557 apm_config.capture_level_adjustment.enabled = true;
558 apm_config.capture_level_adjustment.pre_gain_factor = 1.f;
559 apm->ApplyConfig(apm_config);
560
561 constexpr int16_t kAudioLevel = 10000;
562 constexpr size_t kSampleRateHz = 48000;
563 constexpr size_t kNumChannels = 2;
564 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
565 StreamConfig config(kSampleRateHz, kNumChannels);
566 frame.fill(kAudioLevel);
567
568 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
569
570 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
571 EXPECT_CALL(*echo_control_mock,
572 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
573 .Times(1);
574 apm->ProcessStream(frame.data(), config, config, frame.data());
575
576 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
577 EXPECT_CALL(*echo_control_mock,
578 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
579 .Times(1);
580 apm->SetRuntimeSetting(
581 AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
582 apm->ProcessStream(frame.data(), config, config, frame.data());
583 }
584
TEST(AudioProcessingImplTest,EchoControllerObservesAnalogAgc1EchoPathGainChange)585 TEST(AudioProcessingImplTest,
586 EchoControllerObservesAnalogAgc1EchoPathGainChange) {
587 // Tests that the echo controller observes an echo path gain change when the
588 // AGC1 analog adaptive submodule changes the analog gain.
589 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
590 const auto* echo_control_factory_ptr = echo_control_factory.get();
591
592 rtc::scoped_refptr<AudioProcessing> apm =
593 AudioProcessingBuilderForTesting()
594 .SetEchoControlFactory(std::move(echo_control_factory))
595 .Create();
596 webrtc::AudioProcessing::Config apm_config;
597 // Enable AGC1.
598 apm_config.gain_controller1.enabled = true;
599 apm_config.gain_controller1.analog_gain_controller.enabled = true;
600 apm_config.gain_controller2.enabled = false;
601 apm_config.pre_amplifier.enabled = false;
602 apm->ApplyConfig(apm_config);
603
604 constexpr int16_t kAudioLevel = 1000;
605 constexpr size_t kSampleRateHz = 48000;
606 constexpr size_t kNumChannels = 2;
607 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
608 StreamConfig stream_config(kSampleRateHz, kNumChannels);
609 frame.fill(kAudioLevel);
610
611 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
612
613 constexpr int kInitialStreamAnalogLevel = 123;
614 apm->set_stream_analog_level(kInitialStreamAnalogLevel);
615
616 // When the first fame is processed, no echo path gain change must be
617 // detected.
618 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
619 EXPECT_CALL(*echo_control_mock,
620 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
621 .Times(1);
622 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
623
624 // Simulate the application of the recommended analog level.
625 int recommended_analog_level = apm->recommended_stream_analog_level();
626 if (recommended_analog_level == kInitialStreamAnalogLevel) {
627 // Force an analog gain change if it did not happen.
628 recommended_analog_level++;
629 }
630 apm->set_stream_analog_level(recommended_analog_level);
631
632 // After the first fame and with a stream analog level change, the echo path
633 // gain change must be detected.
634 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
635 EXPECT_CALL(*echo_control_mock,
636 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
637 .Times(1);
638 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
639 }
640
641 // Tests that a stream is successfully processed when AGC2 adaptive digital is
642 // used and when the field trial
643 // `WebRTC-Audio-TransientSuppressorVadMode/Enabled-Default/` is set.
TEST(AudioProcessingImplTest,ProcessWithAgc2AndTransientSuppressorVadModeDefault)644 TEST(AudioProcessingImplTest,
645 ProcessWithAgc2AndTransientSuppressorVadModeDefault) {
646 webrtc::test::ScopedFieldTrials field_trials(
647 "WebRTC-Audio-TransientSuppressorVadMode/Enabled-Default/");
648 rtc::scoped_refptr<AudioProcessing> apm = AudioProcessingBuilder().Create();
649 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
650 webrtc::AudioProcessing::Config apm_config;
651 // Disable AGC1 analog.
652 apm_config.gain_controller1.enabled = false;
653 // Enable AGC2 digital.
654 apm_config.gain_controller2.enabled = true;
655 apm_config.gain_controller2.adaptive_digital.enabled = true;
656 apm->ApplyConfig(apm_config);
657 constexpr int kSampleRateHz = 48000;
658 constexpr int kNumChannels = 1;
659 std::array<float, kSampleRateHz / 100> buffer;
660 float* channel_pointers[] = {buffer.data()};
661 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
662 /*num_channels=*/kNumChannels);
663 Random random_generator(2341U);
664 constexpr int kFramesToProcess = 10;
665 for (int i = 0; i < kFramesToProcess; ++i) {
666 RandomizeSampleVector(&random_generator, buffer);
667 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
668 channel_pointers),
669 kNoErr);
670 }
671 }
672
673 // Tests that a stream is successfully processed when AGC2 adaptive digital is
674 // used and when the field trial
675 // `WebRTC-Audio-TransientSuppressorVadMode/Enabled-RnnVad/` is set.
TEST(AudioProcessingImplTest,ProcessWithAgc2AndTransientSuppressorVadModeRnnVad)676 TEST(AudioProcessingImplTest,
677 ProcessWithAgc2AndTransientSuppressorVadModeRnnVad) {
678 webrtc::test::ScopedFieldTrials field_trials(
679 "WebRTC-Audio-TransientSuppressorVadMode/Enabled-RnnVad/");
680 rtc::scoped_refptr<AudioProcessing> apm = AudioProcessingBuilder().Create();
681 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
682 webrtc::AudioProcessing::Config apm_config;
683 // Disable AGC1 analog.
684 apm_config.gain_controller1.enabled = false;
685 // Enable AGC2 digital.
686 apm_config.gain_controller2.enabled = true;
687 apm_config.gain_controller2.adaptive_digital.enabled = true;
688 apm->ApplyConfig(apm_config);
689 constexpr int kSampleRateHz = 48000;
690 constexpr int kNumChannels = 1;
691 std::array<float, kSampleRateHz / 100> buffer;
692 float* channel_pointers[] = {buffer.data()};
693 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
694 /*num_channels=*/kNumChannels);
695 Random random_generator(2341U);
696 constexpr int kFramesToProcess = 10;
697 for (int i = 0; i < kFramesToProcess; ++i) {
698 RandomizeSampleVector(&random_generator, buffer);
699 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
700 channel_pointers),
701 kNoErr);
702 }
703 }
704
TEST(AudioProcessingImplTest,EchoControllerObservesPlayoutVolumeChange)705 TEST(AudioProcessingImplTest, EchoControllerObservesPlayoutVolumeChange) {
706 // Tests that the echo controller observes an echo path gain change when a
707 // playout volume change is reported.
708 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
709 const auto* echo_control_factory_ptr = echo_control_factory.get();
710
711 rtc::scoped_refptr<AudioProcessing> apm =
712 AudioProcessingBuilderForTesting()
713 .SetEchoControlFactory(std::move(echo_control_factory))
714 .Create();
715 // Disable AGC.
716 webrtc::AudioProcessing::Config apm_config;
717 apm_config.gain_controller1.enabled = false;
718 apm_config.gain_controller2.enabled = false;
719 apm->ApplyConfig(apm_config);
720
721 constexpr int16_t kAudioLevel = 10000;
722 constexpr size_t kSampleRateHz = 48000;
723 constexpr size_t kNumChannels = 2;
724 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
725 StreamConfig stream_config(kSampleRateHz, kNumChannels);
726 frame.fill(kAudioLevel);
727
728 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
729
730 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
731 EXPECT_CALL(*echo_control_mock,
732 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
733 .Times(1);
734 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
735
736 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
737 EXPECT_CALL(*echo_control_mock,
738 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
739 .Times(1);
740 apm->SetRuntimeSetting(
741 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
742 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
743
744 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
745 EXPECT_CALL(*echo_control_mock,
746 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
747 .Times(1);
748 apm->SetRuntimeSetting(
749 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
750 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
751
752 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
753 EXPECT_CALL(*echo_control_mock,
754 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
755 .Times(1);
756 apm->SetRuntimeSetting(
757 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(100));
758 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
759 }
760
TEST(AudioProcessingImplTest,RenderPreProcessorBeforeEchoDetector)761 TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
762 // Make sure that signal changes caused by a render pre-processing sub-module
763 // take place before any echo detector analysis.
764 auto test_echo_detector = rtc::make_ref_counted<TestEchoDetector>();
765 std::unique_ptr<CustomProcessing> test_render_pre_processor(
766 new TestRenderPreProcessor());
767 // Create APM injecting the test echo detector and render pre-processor.
768 rtc::scoped_refptr<AudioProcessing> apm =
769 AudioProcessingBuilderForTesting()
770 .SetEchoDetector(test_echo_detector)
771 .SetRenderPreProcessing(std::move(test_render_pre_processor))
772 .Create();
773 webrtc::AudioProcessing::Config apm_config;
774 apm_config.pre_amplifier.enabled = true;
775 apm->ApplyConfig(apm_config);
776
777 constexpr int16_t kAudioLevel = 1000;
778 constexpr int kSampleRateHz = 16000;
779 constexpr size_t kNumChannels = 1;
780 // Explicitly initialize APM to ensure no render frames are discarded.
781 const ProcessingConfig processing_config = {{
782 {kSampleRateHz, kNumChannels},
783 {kSampleRateHz, kNumChannels},
784 {kSampleRateHz, kNumChannels},
785 {kSampleRateHz, kNumChannels},
786 }};
787 apm->Initialize(processing_config);
788
789 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
790 StreamConfig stream_config(kSampleRateHz, kNumChannels);
791
792 constexpr float kAudioLevelFloat = static_cast<float>(kAudioLevel);
793 constexpr float kExpectedPreprocessedAudioLevel =
794 TestRenderPreProcessor::ProcessSample(kAudioLevelFloat);
795 ASSERT_NE(kAudioLevelFloat, kExpectedPreprocessedAudioLevel);
796
797 // Analyze a render stream frame.
798 frame.fill(kAudioLevel);
799 ASSERT_EQ(AudioProcessing::Error::kNoError,
800 apm->ProcessReverseStream(frame.data(), stream_config,
801 stream_config, frame.data()));
802 // Trigger a call to in EchoDetector::AnalyzeRenderAudio() via
803 // ProcessStream().
804 frame.fill(kAudioLevel);
805 ASSERT_EQ(AudioProcessing::Error::kNoError,
806 apm->ProcessStream(frame.data(), stream_config, stream_config,
807 frame.data()));
808 // Regardless of how the call to in EchoDetector::AnalyzeRenderAudio() is
809 // triggered, the line below checks that the call has occurred. If not, the
810 // APM implementation may have changed and this test might need to be adapted.
811 ASSERT_TRUE(test_echo_detector->analyze_render_audio_called());
812 // Check that the data read in EchoDetector::AnalyzeRenderAudio() is that
813 // produced by the render pre-processor.
814 EXPECT_EQ(kExpectedPreprocessedAudioLevel,
815 test_echo_detector->last_render_audio_first_sample());
816 }
817
818 // Disabling build-optional submodules and trying to enable them via the APM
819 // config should be bit-exact with running APM with said submodules disabled.
820 // This mainly tests that SetCreateOptionalSubmodulesForTesting has an effect.
TEST(ApmWithSubmodulesExcludedTest,BitexactWithDisabledModules)821 TEST(ApmWithSubmodulesExcludedTest, BitexactWithDisabledModules) {
822 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
823 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
824
825 ApmSubmoduleCreationOverrides overrides;
826 overrides.transient_suppression = true;
827 apm->OverrideSubmoduleCreationForTesting(overrides);
828
829 AudioProcessing::Config apm_config = apm->GetConfig();
830 apm_config.transient_suppression.enabled = true;
831 apm->ApplyConfig(apm_config);
832
833 rtc::scoped_refptr<AudioProcessing> apm_reference =
834 AudioProcessingBuilder().Create();
835 apm_config = apm_reference->GetConfig();
836 apm_config.transient_suppression.enabled = false;
837 apm_reference->ApplyConfig(apm_config);
838
839 constexpr int kSampleRateHz = 16000;
840 constexpr int kNumChannels = 1;
841 std::array<float, kSampleRateHz / 100> buffer;
842 std::array<float, kSampleRateHz / 100> buffer_reference;
843 float* channel_pointers[] = {buffer.data()};
844 float* channel_pointers_reference[] = {buffer_reference.data()};
845 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
846 /*num_channels=*/kNumChannels);
847 Random random_generator(2341U);
848 constexpr int kFramesToProcessPerConfiguration = 10;
849
850 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
851 RandomizeSampleVector(&random_generator, buffer);
852 std::copy(buffer.begin(), buffer.end(), buffer_reference.begin());
853 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
854 channel_pointers),
855 kNoErr);
856 ASSERT_EQ(
857 apm_reference->ProcessStream(channel_pointers_reference, stream_config,
858 stream_config, channel_pointers_reference),
859 kNoErr);
860 for (int j = 0; j < kSampleRateHz / 100; ++j) {
861 EXPECT_EQ(buffer[j], buffer_reference[j]);
862 }
863 }
864 }
865
866 // Disable transient suppressor creation and run APM in ways that should trigger
867 // calls to the transient suppressor API.
TEST(ApmWithSubmodulesExcludedTest,ReinitializeTransientSuppressor)868 TEST(ApmWithSubmodulesExcludedTest, ReinitializeTransientSuppressor) {
869 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
870 ASSERT_EQ(apm->Initialize(), kNoErr);
871
872 ApmSubmoduleCreationOverrides overrides;
873 overrides.transient_suppression = true;
874 apm->OverrideSubmoduleCreationForTesting(overrides);
875
876 AudioProcessing::Config config = apm->GetConfig();
877 config.transient_suppression.enabled = true;
878 apm->ApplyConfig(config);
879 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
880 float buffer[960];
881 float* channel_pointers[] = {&buffer[0], &buffer[480]};
882 Random random_generator(2341U);
883 constexpr int kFramesToProcessPerConfiguration = 3;
884
885 StreamConfig initial_stream_config(/*sample_rate_hz=*/16000,
886 /*num_channels=*/1);
887 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
888 RandomizeSampleVector(&random_generator, buffer);
889 EXPECT_EQ(apm->ProcessStream(channel_pointers, initial_stream_config,
890 initial_stream_config, channel_pointers),
891 kNoErr);
892 }
893
894 StreamConfig stereo_stream_config(/*sample_rate_hz=*/16000,
895 /*num_channels=*/2);
896 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
897 RandomizeSampleVector(&random_generator, buffer);
898 EXPECT_EQ(apm->ProcessStream(channel_pointers, stereo_stream_config,
899 stereo_stream_config, channel_pointers),
900 kNoErr);
901 }
902
903 StreamConfig high_sample_rate_stream_config(/*sample_rate_hz=*/48000,
904 /*num_channels=*/2);
905 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
906 RandomizeSampleVector(&random_generator, buffer);
907 EXPECT_EQ(
908 apm->ProcessStream(channel_pointers, high_sample_rate_stream_config,
909 high_sample_rate_stream_config, channel_pointers),
910 kNoErr);
911 }
912 }
913
914 // Disable transient suppressor creation and run APM in ways that should trigger
915 // calls to the transient suppressor API.
TEST(ApmWithSubmodulesExcludedTest,ToggleTransientSuppressor)916 TEST(ApmWithSubmodulesExcludedTest, ToggleTransientSuppressor) {
917 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
918 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
919
920 ApmSubmoduleCreationOverrides overrides;
921 overrides.transient_suppression = true;
922 apm->OverrideSubmoduleCreationForTesting(overrides);
923
924 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
925 float buffer[960];
926 float* channel_pointers[] = {&buffer[0], &buffer[480]};
927 Random random_generator(2341U);
928 constexpr int kFramesToProcessPerConfiguration = 3;
929 StreamConfig stream_config(/*sample_rate_hz=*/16000,
930 /*num_channels=*/1);
931
932 AudioProcessing::Config config = apm->GetConfig();
933 config.transient_suppression.enabled = true;
934 apm->ApplyConfig(config);
935 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
936 RandomizeSampleVector(&random_generator, buffer);
937 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
938 channel_pointers),
939 kNoErr);
940 }
941
942 config = apm->GetConfig();
943 config.transient_suppression.enabled = false;
944 apm->ApplyConfig(config);
945 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
946 RandomizeSampleVector(&random_generator, buffer);
947 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
948 channel_pointers),
949 kNoErr);
950 }
951
952 config = apm->GetConfig();
953 config.transient_suppression.enabled = true;
954 apm->ApplyConfig(config);
955 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
956 RandomizeSampleVector(&random_generator, buffer);
957 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
958 channel_pointers),
959 kNoErr);
960 }
961 }
962
963 // Tests that the minimum startup volume is applied at the startup.
TEST_P(InputVolumeStartupParameterizedTest,VerifyStartupMinVolumeAppliedAtStartup)964 TEST_P(InputVolumeStartupParameterizedTest,
965 VerifyStartupMinVolumeAppliedAtStartup) {
966 const int applied_startup_input_volume = GetStartupVolume();
967 const int expected_volume =
968 std::max(applied_startup_input_volume, GetMinVolume());
969 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
970 const bool agc2_input_volume_controller_enabled =
971 GetAgc2InputVolumeControllerEnabled();
972 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
973 agc2_input_volume_controller_enabled);
974
975 const int recommended_input_volume =
976 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
977
978 if (!agc1_analog_controller_enabled &&
979 !agc2_input_volume_controller_enabled) {
980 // No input volume changes if none of the analog controllers is enabled.
981 ASSERT_EQ(recommended_input_volume, applied_startup_input_volume);
982 } else {
983 ASSERT_EQ(recommended_input_volume, expected_volume);
984 }
985 }
986
987 // Tests that the minimum input volume is applied if the volume is manually
988 // adjusted to a non-zero value 1) always for AGC2 input volume controller and
989 // 2) only if "WebRTC-Audio-2ndAgcMinMicLevelExperiment" is enabled for AGC1
990 // analog controller.
TEST_P(InputVolumeNotZeroParameterizedTest,VerifyMinVolumeMaybeAppliedAfterManualVolumeAdjustments)991 TEST_P(InputVolumeNotZeroParameterizedTest,
992 VerifyMinVolumeMaybeAppliedAfterManualVolumeAdjustments) {
993 const int applied_startup_input_volume = GetStartupVolume();
994 const int applied_input_volume = GetVolume();
995 const int expected_volume = std::max(applied_input_volume, GetMinVolume());
996 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
997 const bool agc2_input_volume_controller_enabled =
998 GetAgc2InputVolumeControllerEnabled();
999 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1000 agc2_input_volume_controller_enabled);
1001
1002 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1003 const int recommended_input_volume =
1004 ProcessInputVolume(*apm, /*num_frames=*/1, applied_input_volume);
1005
1006 ASSERT_NE(applied_input_volume, 0);
1007
1008 if (!agc1_analog_controller_enabled &&
1009 !agc2_input_volume_controller_enabled) {
1010 // No input volume changes if none of the analog controllers is enabled.
1011 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1012 } else {
1013 if (GetMinMicLevelExperimentEnabled() ||
1014 (!agc1_analog_controller_enabled &&
1015 agc2_input_volume_controller_enabled)) {
1016 ASSERT_EQ(recommended_input_volume, expected_volume);
1017 } else {
1018 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1019 }
1020 }
1021 }
1022
1023 // Tests that the minimum input volume is not applied if the volume is manually
1024 // adjusted to zero.
TEST_P(InputVolumeZeroParameterizedTest,VerifyMinVolumeNotAppliedAfterManualVolumeAdjustments)1025 TEST_P(InputVolumeZeroParameterizedTest,
1026 VerifyMinVolumeNotAppliedAfterManualVolumeAdjustments) {
1027 constexpr int kZeroVolume = 0;
1028 const int applied_startup_input_volume = GetStartupVolume();
1029 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1030 const bool agc2_input_volume_controller_enabled =
1031 GetAgc2InputVolumeControllerEnabled();
1032 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1033 agc2_input_volume_controller_enabled);
1034
1035 const int recommended_input_volume_after_startup =
1036 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1037 const int recommended_input_volume =
1038 ProcessInputVolume(*apm, /*num_frames=*/1, kZeroVolume);
1039
1040 if (!agc1_analog_controller_enabled &&
1041 !agc2_input_volume_controller_enabled) {
1042 // No input volume changes if none of the analog controllers is enabled.
1043 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1044 } else {
1045 ASSERT_NE(recommended_input_volume, recommended_input_volume_after_startup);
1046 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1047 }
1048 }
1049
1050 // Tests that the minimum input volume is applied if the volume is not zero
1051 // before it is automatically adjusted.
TEST_P(InputVolumeNotZeroParameterizedTest,VerifyMinVolumeAppliedAfterAutomaticVolumeAdjustments)1052 TEST_P(InputVolumeNotZeroParameterizedTest,
1053 VerifyMinVolumeAppliedAfterAutomaticVolumeAdjustments) {
1054 const int applied_startup_input_volume = GetStartupVolume();
1055 const int applied_input_volume = GetVolume();
1056 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1057 const bool agc2_input_volume_controller_enabled =
1058 GetAgc2InputVolumeControllerEnabled();
1059 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1060 agc2_input_volume_controller_enabled);
1061
1062 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1063 const int recommended_input_volume =
1064 ProcessInputVolume(*apm, /*num_frames=*/400, applied_input_volume);
1065
1066 ASSERT_NE(applied_input_volume, 0);
1067
1068 if (!agc1_analog_controller_enabled &&
1069 !agc2_input_volume_controller_enabled) {
1070 // No input volume changes if none of the analog controllers is enabled.
1071 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1072 } else {
1073 if (recommended_input_volume != applied_input_volume) {
1074 ASSERT_GE(recommended_input_volume, GetMinVolume());
1075 }
1076 }
1077 }
1078
1079 // Tests that the minimum input volume is not applied if the volume is zero
1080 // before it is automatically adjusted.
TEST_P(InputVolumeZeroParameterizedTest,VerifyMinVolumeNotAppliedAfterAutomaticVolumeAdjustments)1081 TEST_P(InputVolumeZeroParameterizedTest,
1082 VerifyMinVolumeNotAppliedAfterAutomaticVolumeAdjustments) {
1083 constexpr int kZeroVolume = 0;
1084 const int applied_startup_input_volume = GetStartupVolume();
1085 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1086 const bool agc2_input_volume_controller_enabled =
1087 GetAgc2InputVolumeControllerEnabled();
1088 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1089 agc2_input_volume_controller_enabled);
1090
1091 const int recommended_input_volume_after_startup =
1092 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1093 const int recommended_input_volume =
1094 ProcessInputVolume(*apm, /*num_frames=*/400, kZeroVolume);
1095
1096 if (!agc1_analog_controller_enabled &&
1097 !agc2_input_volume_controller_enabled) {
1098 // No input volume changes if none of the analog controllers is enabled.
1099 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1100 } else {
1101 ASSERT_NE(recommended_input_volume, recommended_input_volume_after_startup);
1102 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1103 }
1104 }
1105
1106 INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1107 InputVolumeStartupParameterizedTest,
1108 ::testing::Combine(::testing::Values(0, 5, 30),
1109 ::testing::Values(absl::nullopt,
1110 20),
1111 ::testing::Bool(),
1112 ::testing::Bool()));
1113
1114 INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1115 InputVolumeNotZeroParameterizedTest,
1116 ::testing::Combine(::testing::Values(0, 5, 15),
1117 ::testing::Values(1, 5, 30),
1118 ::testing::Values(absl::nullopt,
1119 20),
1120 ::testing::Bool(),
1121 ::testing::Bool()));
1122
1123 INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1124 InputVolumeZeroParameterizedTest,
1125 ::testing::Combine(::testing::Values(0, 5, 15),
1126 ::testing::Values(absl::nullopt,
1127 20),
1128 ::testing::Bool(),
1129 ::testing::Bool()));
1130
1131 // When the input volume is not emulated and no input volume controller is
1132 // active, the recommended volume must always be the applied volume.
TEST(AudioProcessingImplTest,RecommendAppliedInputVolumeWithNoAgcWithNoEmulation)1133 TEST(AudioProcessingImplTest,
1134 RecommendAppliedInputVolumeWithNoAgcWithNoEmulation) {
1135 auto apm = AudioProcessingBuilder()
1136 .SetConfig({.capture_level_adjustment = {.enabled = false},
1137 .gain_controller1 = {.enabled = false}})
1138 .Create();
1139
1140 constexpr int kOneFrame = 1;
1141 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1142 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1143 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1144 }
1145
1146 // When the input volume is emulated, the recommended volume must always be the
1147 // applied volume and at any time it must not be that set in the input volume
1148 // emulator.
1149 // TODO(bugs.webrtc.org/14581): Enable when APM fixed to let this test pass.
TEST(AudioProcessingImplTest,DISABLED_RecommendAppliedInputVolumeWithNoAgcWithEmulation)1150 TEST(AudioProcessingImplTest,
1151 DISABLED_RecommendAppliedInputVolumeWithNoAgcWithEmulation) {
1152 auto apm =
1153 AudioProcessingBuilder()
1154 .SetConfig({.capture_level_adjustment = {.enabled = true,
1155 .analog_mic_gain_emulation{
1156 .enabled = true,
1157 .initial_level = 255}},
1158 .gain_controller1 = {.enabled = false}})
1159 .Create();
1160
1161 constexpr int kOneFrame = 1;
1162 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1163 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1164 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1165 }
1166
1167 // Even if there is an enabled input volume controller, when the input volume is
1168 // emulated, the recommended volume is always the applied volume because the
1169 // active controller must only adjust the internally emulated volume and leave
1170 // the externally applied volume unchanged.
1171 // TODO(bugs.webrtc.org/14581): Enable when APM fixed to let this test pass.
TEST(AudioProcessingImplTest,DISABLED_RecommendAppliedInputVolumeWithAgcWithEmulation)1172 TEST(AudioProcessingImplTest,
1173 DISABLED_RecommendAppliedInputVolumeWithAgcWithEmulation) {
1174 auto apm =
1175 AudioProcessingBuilder()
1176 .SetConfig({.capture_level_adjustment = {.enabled = true,
1177 .analog_mic_gain_emulation{
1178 .enabled = true}},
1179 .gain_controller1 = {.enabled = true,
1180 .analog_gain_controller{
1181 .enabled = true,
1182 }}})
1183 .Create();
1184
1185 constexpr int kOneFrame = 1;
1186 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1187 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1188 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1189 }
1190
TEST(AudioProcessingImplInputVolumeControllerExperimentTest,ConfigAdjustedWhenExperimentEnabledAndAgc1AnalogEnabled)1191 TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
1192 ConfigAdjustedWhenExperimentEnabledAndAgc1AnalogEnabled) {
1193 webrtc::test::ScopedFieldTrials field_trials(
1194 "WebRTC-Audio-InputVolumeControllerExperiment/"
1195 "Enabled,"
1196 "enable_clipping_predictor:true,"
1197 "clipped_level_min:20,"
1198 "clipped_level_step:30,"
1199 "clipped_ratio_threshold:0.4,"
1200 "clipped_wait_frames:50,"
1201 "target_range_max_dbfs:-6,"
1202 "target_range_min_dbfs:-70,"
1203 "update_input_volume_wait_frames:80,"
1204 "speech_probability_threshold:0.9,"
1205 "speech_ratio_threshold:1.0/");
1206
1207 AudioProcessingBuilderForTesting apm_builder;
1208
1209 // Set a config with analog AGC1 enabled.
1210 AudioProcessing::Config config;
1211 config.gain_controller1.enabled = true;
1212 config.gain_controller1.analog_gain_controller.enabled = true;
1213 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1214 config.gain_controller2.enabled = false;
1215 config.gain_controller1.mode =
1216 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1217
1218 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1219
1220 apm_builder.SetConfig(config);
1221
1222 auto apm = apm_builder.Create();
1223 auto adjusted_config = apm->GetConfig();
1224
1225 // Expect the config to be adjusted.
1226 EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
1227 EXPECT_FALSE(adjusted_config.gain_controller1.analog_gain_controller.enabled);
1228 EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
1229 EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
1230 EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
1231
1232 // Change config back and compare.
1233 adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
1234 adjusted_config.gain_controller1.analog_gain_controller.enabled =
1235 config.gain_controller1.analog_gain_controller.enabled;
1236 adjusted_config.gain_controller2.enabled = config.gain_controller2.enabled;
1237 adjusted_config.gain_controller2.adaptive_digital.enabled =
1238 config.gain_controller2.adaptive_digital.enabled;
1239 adjusted_config.gain_controller2.input_volume_controller.enabled =
1240 config.gain_controller2.input_volume_controller.enabled;
1241
1242 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1243 }
1244
TEST(AudioProcessingImplInputVolumeControllerExperimentTest,ConfigAdjustedWhenExperimentEnabledAndHybridAgcEnabled)1245 TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
1246 ConfigAdjustedWhenExperimentEnabledAndHybridAgcEnabled) {
1247 webrtc::test::ScopedFieldTrials field_trials(
1248 "WebRTC-Audio-InputVolumeControllerExperiment/"
1249 "Enabled,"
1250 "enable_clipping_predictor:true,"
1251 "clipped_level_min:20,"
1252 "clipped_level_step:30,"
1253 "clipped_ratio_threshold:0.4,"
1254 "clipped_wait_frames:50,"
1255 "target_range_max_dbfs:-6,"
1256 "target_range_min_dbfs:-70,"
1257 "update_input_volume_wait_frames:80,"
1258 "speech_probability_threshold:0.9,"
1259 "speech_ratio_threshold:1.0/");
1260
1261 AudioProcessingBuilderForTesting apm_builder;
1262
1263 // Set a config with hybrid AGC enabled.
1264 AudioProcessing::Config config;
1265 config.gain_controller1.enabled = true;
1266 config.gain_controller1.analog_gain_controller.enabled = true;
1267 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1268 false;
1269 config.gain_controller2.enabled = true;
1270 config.gain_controller2.adaptive_digital.enabled = true;
1271 config.gain_controller1.mode =
1272 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1273
1274 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1275
1276 apm_builder.SetConfig(config);
1277
1278 auto apm = apm_builder.Create();
1279 auto adjusted_config = apm->GetConfig();
1280
1281 // Expect the config to be adjusted.
1282 EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
1283 EXPECT_FALSE(adjusted_config.gain_controller1.analog_gain_controller.enabled);
1284 EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
1285 EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
1286 EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
1287
1288 // Change config back and compare.
1289 adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
1290 adjusted_config.gain_controller1.analog_gain_controller.enabled =
1291 config.gain_controller1.analog_gain_controller.enabled;
1292 adjusted_config.gain_controller2.enabled = config.gain_controller2.enabled;
1293 adjusted_config.gain_controller2.adaptive_digital.enabled =
1294 config.gain_controller2.adaptive_digital.enabled;
1295 adjusted_config.gain_controller2.input_volume_controller.enabled =
1296 config.gain_controller2.input_volume_controller.enabled;
1297
1298 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1299 }
1300
TEST(AudioProcessingImplInputVolumeControllerExperimentTest,ConfigNotAdjustedWhenExperimentEnabledAndAgc1AnalogNotEnabled)1301 TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
1302 ConfigNotAdjustedWhenExperimentEnabledAndAgc1AnalogNotEnabled) {
1303 webrtc::test::ScopedFieldTrials field_trials(
1304 "WebRTC-Audio-InputVolumeControllerExperiment/"
1305 "Enabled,"
1306 "enable_clipping_predictor:true,"
1307 "clipped_level_min:20,"
1308 "clipped_level_step:30,"
1309 "clipped_ratio_threshold:0.4,"
1310 "clipped_wait_frames:50,"
1311 "target_range_max_dbfs:-6,"
1312 "target_range_min_dbfs:-70,"
1313 "update_input_volume_wait_frames:80,"
1314 "speech_probability_threshold:0.9,"
1315 "speech_ratio_threshold:1.0/");
1316
1317 AudioProcessingBuilderForTesting apm_builder;
1318
1319 // Set a config with analog AGC1 not enabled.
1320 AudioProcessing::Config config;
1321 config.gain_controller1.enabled = false;
1322 config.gain_controller1.analog_gain_controller.enabled = true;
1323 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1324 config.gain_controller2.enabled = false;
1325 config.gain_controller1.mode =
1326 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1327
1328 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1329
1330 apm_builder.SetConfig(config);
1331
1332 auto apm = apm_builder.Create();
1333 auto adjusted_config = apm->GetConfig();
1334
1335 EXPECT_EQ(config.gain_controller1.enabled,
1336 adjusted_config.gain_controller1.enabled);
1337 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1338 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1339 EXPECT_EQ(config.gain_controller2.enabled,
1340 adjusted_config.gain_controller2.enabled);
1341 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1342 adjusted_config.gain_controller2.adaptive_digital.enabled);
1343 EXPECT_FALSE(
1344 adjusted_config.gain_controller2.input_volume_controller.enabled);
1345
1346 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1347 }
1348
TEST(AudioProcessingImplInputVolumeControllerExperimentTest,ConfigNotAdjustedWhenExperimentEnabledAndHybridAgcNotEnabled)1349 TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
1350 ConfigNotAdjustedWhenExperimentEnabledAndHybridAgcNotEnabled) {
1351 webrtc::test::ScopedFieldTrials field_trials(
1352 "WebRTC-Audio-InputVolumeControllerExperiment/"
1353 "Enabled,"
1354 "enable_clipping_predictor:true,"
1355 "clipped_level_min:20,"
1356 "clipped_level_step:30,"
1357 "clipped_ratio_threshold:0.4,"
1358 "clipped_wait_frames:50,"
1359 "target_range_max_dbfs:-6,"
1360 "target_range_min_dbfs:-70,"
1361 "update_input_volume_wait_frames:80,"
1362 "speech_probability_threshold:0.9,"
1363 "speech_ratio_threshold:1.0/");
1364
1365 AudioProcessingBuilderForTesting apm_builder;
1366
1367 // Set a config with hybrid AGC analog not enabled.
1368 AudioProcessing::Config config;
1369 config.gain_controller1.enabled = false;
1370 config.gain_controller1.analog_gain_controller.enabled = true;
1371 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1372 false;
1373 config.gain_controller2.enabled = true;
1374 config.gain_controller2.adaptive_digital.enabled = true;
1375 config.gain_controller1.mode =
1376 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1377
1378 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1379
1380 apm_builder.SetConfig(config);
1381
1382 auto apm = apm_builder.Create();
1383 auto adjusted_config = apm->GetConfig();
1384
1385 EXPECT_EQ(config.gain_controller1.enabled,
1386 adjusted_config.gain_controller1.enabled);
1387 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1388 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1389 EXPECT_EQ(config.gain_controller2.enabled,
1390 adjusted_config.gain_controller2.enabled);
1391 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1392 adjusted_config.gain_controller2.adaptive_digital.enabled);
1393 EXPECT_FALSE(
1394 adjusted_config.gain_controller2.input_volume_controller.enabled);
1395
1396 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1397 }
1398
TEST(AudioProcessingImplInputVolumeControllerExperimentTest,ConfigNotAdjustedWhenExperimentNotEnabledAndAgc1AnalogEnabled)1399 TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
1400 ConfigNotAdjustedWhenExperimentNotEnabledAndAgc1AnalogEnabled) {
1401 AudioProcessingBuilderForTesting apm_builder;
1402
1403 // Set a config with analog AGC1 analog enabled.
1404 AudioProcessing::Config config;
1405 config.gain_controller1.enabled = true;
1406 config.gain_controller1.analog_gain_controller.enabled = true;
1407 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1408 config.gain_controller2.enabled = false;
1409 config.gain_controller1.mode =
1410 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1411
1412 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1413
1414 apm_builder.SetConfig(config);
1415
1416 auto apm = apm_builder.Create();
1417 auto adjusted_config = apm->GetConfig();
1418
1419 EXPECT_EQ(config.gain_controller1.enabled,
1420 adjusted_config.gain_controller1.enabled);
1421 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1422 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1423 EXPECT_EQ(config.gain_controller2.enabled,
1424 adjusted_config.gain_controller2.enabled);
1425 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1426 adjusted_config.gain_controller2.adaptive_digital.enabled);
1427 EXPECT_FALSE(
1428 adjusted_config.gain_controller2.input_volume_controller.enabled);
1429
1430 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1431 }
1432
TEST(AudioProcessingImplInputVolumeControllerExperimentTest,ConfigNotAdjustedWhenExperimentNotEnabledAndHybridAgcEnabled)1433 TEST(AudioProcessingImplInputVolumeControllerExperimentTest,
1434 ConfigNotAdjustedWhenExperimentNotEnabledAndHybridAgcEnabled) {
1435 AudioProcessingBuilderForTesting apm_builder;
1436
1437 // Set a config with hybrid AGC enabled.
1438 AudioProcessing::Config config;
1439 config.gain_controller1.enabled = true;
1440 config.gain_controller1.analog_gain_controller.enabled = true;
1441 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1442 false;
1443 config.gain_controller2.enabled = true;
1444 config.gain_controller2.adaptive_digital.enabled = true;
1445 config.gain_controller1.mode =
1446 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1447
1448 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1449
1450 apm_builder.SetConfig(config);
1451
1452 auto apm = apm_builder.Create();
1453 auto adjusted_config = apm->GetConfig();
1454
1455 EXPECT_EQ(config.gain_controller1.enabled,
1456 adjusted_config.gain_controller1.enabled);
1457 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1458 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1459 EXPECT_EQ(config.gain_controller2.enabled,
1460 adjusted_config.gain_controller2.enabled);
1461 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1462 adjusted_config.gain_controller2.adaptive_digital.enabled);
1463 EXPECT_FALSE(
1464 adjusted_config.gain_controller2.input_volume_controller.enabled);
1465
1466 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1467 }
1468
1469 } // namespace webrtc
1470