blob: 65bda71f580bf5728e1eb75b72c3922728dfb859 [file] [log] [blame]
andrew@webrtc.org60730cf2014-01-07 17:45:09 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/audio_processing_impl.h"
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000012
Per Åhgren2507f8c2020-03-19 12:33:29 +010013#include <array>
Alessio Bazzicae4498052018-12-17 09:44:06 +010014#include <memory>
Hanna Silenc69188d2022-09-16 11:38:56 +020015#include <tuple>
Alessio Bazzicae4498052018-12-17 09:44:06 +010016
Hanna Silenc69188d2022-09-16 11:38:56 +020017#include "absl/types/optional.h"
Niels Möller105711e2022-06-14 15:48:26 +020018#include "api/make_ref_counted.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010019#include "api/scoped_refptr.h"
Alessio Bazzicad2b97402018-08-09 14:23:11 +020020#include "modules/audio_processing/include/audio_processing.h"
Sam Zackrissonb37e59d2020-04-27 08:39:33 +020021#include "modules/audio_processing/optionally_built_submodule_creators.h"
Per Åhgrencc73ed32020-04-26 23:56:17 +020022#include "modules/audio_processing/test/audio_processing_builder_for_testing.h"
Sam Zackrissonb37e59d2020-04-27 08:39:33 +020023#include "modules/audio_processing/test/echo_canceller_test_tools.h"
Alessio Bazzicae4498052018-12-17 09:44:06 +010024#include "modules/audio_processing/test/echo_control_mock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/audio_processing/test/test_utils.h"
Alessio Bazzicae4498052018-12-17 09:44:06 +010026#include "rtc_base/checks.h"
Sam Zackrissonb37e59d2020-04-27 08:39:33 +020027#include "rtc_base/random.h"
Hanna Silenc69188d2022-09-16 11:38:56 +020028#include "rtc_base/strings/string_builder.h"
Hanna Silen0c1ad292022-06-16 16:35:45 +020029#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "test/gmock.h"
31#include "test/gtest.h"
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000032
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000033namespace webrtc {
peaha9cc40b2017-06-29 08:32:09 -070034namespace {
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000035
Alessio Bazzicae4498052018-12-17 09:44:06 +010036using ::testing::Invoke;
37using ::testing::NotNull;
38
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000039class MockInitialize : public AudioProcessingImpl {
40 public:
Alessio Bazzicabe1b8982021-09-17 08:26:10 +020041 MockInitialize() : AudioProcessingImpl() {}
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000042
Per Åhgren0ade9832020-09-01 23:57:20 +020043 MOCK_METHOD(void, InitializeLocked, (), (override));
Niels Möller5b747232021-07-26 17:16:25 +020044 void RealInitializeLocked() {
45 AssertLockedForTest();
Per Åhgren0ade9832020-09-01 23:57:20 +020046 AudioProcessingImpl::InitializeLocked();
pbos@webrtc.org788acd12014-12-15 09:41:24 +000047 }
peaha9cc40b2017-06-29 08:32:09 -070048
Danil Chapovalov704fb552020-05-18 15:10:15 +020049 MOCK_METHOD(void, AddRef, (), (const, override));
50 MOCK_METHOD(rtc::RefCountReleaseStatus, Release, (), (const, override));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000051};
52
Alessio Bazzicae4498052018-12-17 09:44:06 +010053// 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.
60class MockEchoControlFactory : public EchoControlFactory {
61 public:
Mirko Bonadei317a1f02019-09-17 17:06:18 +020062 MockEchoControlFactory() : next_mock_(std::make_unique<MockEchoControl>()) {}
Alessio Bazzicae4498052018-12-17 09:44:06 +010063 // Returns a pointer to the next MockEchoControl that this factory creates.
64 MockEchoControl* GetNext() const { return next_mock_.get(); }
Per Åhgren4e5c7092019-11-01 20:44:11 +010065 std::unique_ptr<EchoControl> Create(int sample_rate_hz,
66 int num_render_channels,
67 int num_capture_channels) override {
Alessio Bazzicae4498052018-12-17 09:44:06 +010068 std::unique_ptr<EchoControl> mock = std::move(next_mock_);
Mirko Bonadei317a1f02019-09-17 17:06:18 +020069 next_mock_ = std::make_unique<MockEchoControl>();
Alessio Bazzicae4498052018-12-17 09:44:06 +010070 return mock;
71 }
72
73 private:
74 std::unique_ptr<MockEchoControl> next_mock_;
75};
76
Alessio Bazzicad2b97402018-08-09 14:23:11 +020077// 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.
80class TestEchoDetector : public EchoDetector {
81 public:
82 TestEchoDetector()
83 : analyze_render_audio_called_(false),
84 last_render_audio_first_sample_(0.f) {}
85 ~TestEchoDetector() override = default;
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 }
90 void AnalyzeCaptureAudio(rtc::ArrayView<const float> capture_audio) override {
91 }
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 {}
96 EchoDetector::Metrics GetMetrics() const override { return {}; }
97 // Returns true if AnalyzeRenderAudio() has been called at least once.
98 bool analyze_render_audio_called() const {
99 return analyze_render_audio_called_;
100 }
101 // Returns the first sample of the last analyzed render frame.
102 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.
114class TestRenderPreProcessor : public CustomProcessing {
115 public:
116 TestRenderPreProcessor() = default;
117 ~TestRenderPreProcessor() = default;
118 void Initialize(int sample_rate_hz, int num_channels) override {}
119 void Process(AudioBuffer* audio) override {
120 for (size_t k = 0; k < audio->num_channels(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200121 rtc::ArrayView<float> channel_view(audio->channels()[k],
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200122 audio->num_frames());
123 std::transform(channel_view.begin(), channel_view.end(),
124 channel_view.begin(), ProcessSample);
125 }
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100126 }
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200127 std::string ToString() const override { return "TestRenderPreProcessor"; }
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.
131 static constexpr float ProcessSample(float x) { return 2.f * x; }
132};
133
Hanna Silenc69188d2022-09-16 11:38:56 +0200134// Creates a simple `AudioProcessing` instance for APM input volume testing
Hanna Silend4dbe452022-11-30 15:16:21 +0100135// with AGC1 analog and/or AGC2 input volume controller enabled and AGC2
136// digital controller enabled.
137rtc::scoped_refptr<AudioProcessing> CreateApmForInputVolumeTest(
138 bool agc1_analog_gain_controller_enabled,
139 bool agc2_input_volume_controller_enabled) {
Hanna Silenc69188d2022-09-16 11:38:56 +0200140 webrtc::AudioProcessing::Config config;
Hanna Silend4dbe452022-11-30 15:16:21 +0100141 // 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.
Alessio Bazzica9ea53812022-10-13 17:09:15 +0200149 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
150 false;
Hanna Silenc69188d2022-09-16 11:38:56 +0200151 config.gain_controller2.enabled = true;
152 config.gain_controller2.adaptive_digital.enabled = true;
153
154 auto apm(AudioProcessingBuilder().Create());
155 apm->ApplyConfig(config);
Hanna Silend4dbe452022-11-30 15:16:21 +0100156
Hanna Silenc69188d2022-09-16 11:38:56 +0200157 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.
164int 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
186constexpr char kMinMicLevelFieldTrial[] =
187 "WebRTC-Audio-2ndAgcMinMicLevelExperiment";
Hanna Silend4dbe452022-11-30 15:16:21 +0100188constexpr char kMinInputVolumeFieldTrial[] = "WebRTC-Audio-Agc2-MinInputVolume";
Hanna Silenc69188d2022-09-16 11:38:56 +0200189constexpr int kMinInputVolume = 12;
190
191std::string GetMinMicLevelExperimentFieldTrial(absl::optional<int> value) {
Hanna Silend4dbe452022-11-30 15:16:21 +0100192 char field_trial_buffer[128];
Hanna Silenc69188d2022-09-16 11:38:56 +0200193 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 << "/";
Hanna Silend4dbe452022-11-30 15:16:21 +0100198 builder << kMinInputVolumeFieldTrial << "/Enabled-" << *value << "/";
Hanna Silenc69188d2022-09-16 11:38:56 +0200199 } else {
200 builder << kMinMicLevelFieldTrial << "/Disabled/";
Hanna Silend4dbe452022-11-30 15:16:21 +0100201 builder << kMinInputVolumeFieldTrial << "/Disabled/";
Hanna Silenc69188d2022-09-16 11:38:56 +0200202 }
203 return builder.str();
204}
205
206// TODO(webrtc:7494): Remove the fieldtrial from the input volume tests when
Hanna Silend4dbe452022-11-30 15:16:21 +0100207// "WebRTC-Audio-2ndAgcMinMicLevelExperiment" and
208// "WebRTC-Audio-Agc2-MinInputVolume" are removed.
Hanna Silenc69188d2022-09-16 11:38:56 +0200209class InputVolumeStartupParameterizedTest
Hanna Silend4dbe452022-11-30 15:16:21 +0100210 : public ::testing::TestWithParam<
211 std::tuple<int, absl::optional<int>, bool, bool>> {
Hanna Silenc69188d2022-09-16 11:38:56 +0200212 protected:
213 InputVolumeStartupParameterizedTest()
214 : field_trials_(
Alessio Bazzica9ea53812022-10-13 17:09:15 +0200215 GetMinMicLevelExperimentFieldTrial(std::get<1>(GetParam()))) {}
216 int GetStartupVolume() const { return std::get<0>(GetParam()); }
Hanna Silenc69188d2022-09-16 11:38:56 +0200217 int GetMinVolume() const {
Alessio Bazzica9ea53812022-10-13 17:09:15 +0200218 return std::get<1>(GetParam()).value_or(kMinInputVolume);
Hanna Silenc69188d2022-09-16 11:38:56 +0200219 }
Hanna Silend4dbe452022-11-30 15:16:21 +0100220 bool GetAgc1AnalogControllerEnabled() const {
221 return std::get<2>(GetParam());
222 }
223 bool GetAgc2InputVolumeControllerEnabled() const {
224 return std::get<3>(GetParam());
225 }
Hanna Silenc69188d2022-09-16 11:38:56 +0200226
227 private:
228 test::ScopedFieldTrials field_trials_;
229};
230
231class InputVolumeNotZeroParameterizedTest
232 : public ::testing::TestWithParam<
Hanna Silend4dbe452022-11-30 15:16:21 +0100233 std::tuple<int, int, absl::optional<int>, bool, bool>> {
Hanna Silenc69188d2022-09-16 11:38:56 +0200234 protected:
235 InputVolumeNotZeroParameterizedTest()
236 : field_trials_(
237 GetMinMicLevelExperimentFieldTrial(std::get<2>(GetParam()))) {}
238 int GetStartupVolume() const { return std::get<0>(GetParam()); }
239 int GetVolume() const { return std::get<1>(GetParam()); }
240 int GetMinVolume() const {
241 return std::get<2>(GetParam()).value_or(kMinInputVolume);
242 }
243 bool GetMinMicLevelExperimentEnabled() {
244 return std::get<2>(GetParam()).has_value();
245 }
Hanna Silend4dbe452022-11-30 15:16:21 +0100246 bool GetAgc1AnalogControllerEnabled() const {
247 return std::get<3>(GetParam());
248 }
249 bool GetAgc2InputVolumeControllerEnabled() const {
250 return std::get<4>(GetParam());
251 }
Hanna Silenc69188d2022-09-16 11:38:56 +0200252
253 private:
254 test::ScopedFieldTrials field_trials_;
255};
256
257class InputVolumeZeroParameterizedTest
Hanna Silend4dbe452022-11-30 15:16:21 +0100258 : public ::testing::TestWithParam<
259 std::tuple<int, absl::optional<int>, bool, bool>> {
Hanna Silenc69188d2022-09-16 11:38:56 +0200260 protected:
261 InputVolumeZeroParameterizedTest()
262 : field_trials_(
263 GetMinMicLevelExperimentFieldTrial(std::get<1>(GetParam()))) {}
264 int GetStartupVolume() const { return std::get<0>(GetParam()); }
265 int GetMinVolume() const {
266 return std::get<1>(GetParam()).value_or(kMinInputVolume);
267 }
Hanna Silend4dbe452022-11-30 15:16:21 +0100268 bool GetAgc1AnalogControllerEnabled() const {
269 return std::get<2>(GetParam());
270 }
271 bool GetAgc2InputVolumeControllerEnabled() const {
272 return std::get<3>(GetParam());
273 }
Hanna Silenc69188d2022-09-16 11:38:56 +0200274
275 private:
276 test::ScopedFieldTrials field_trials_;
277};
278
peaha9cc40b2017-06-29 08:32:09 -0700279} // namespace
280
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000281TEST(AudioProcessingImplTest, AudioParameterChangeTriggersInit) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200282 MockInitialize mock;
283 ON_CALL(mock, InitializeLocked)
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000284 .WillByDefault(Invoke(&mock, &MockInitialize::RealInitializeLocked));
285
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200286 EXPECT_CALL(mock, InitializeLocked).Times(1);
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000287 mock.Initialize();
288
Per Åhgren2507f8c2020-03-19 12:33:29 +0100289 constexpr size_t kMaxSampleRateHz = 32000;
290 constexpr size_t kMaxNumChannels = 2;
291 std::array<int16_t, kMaxNumChannels * kMaxSampleRateHz / 100> frame;
292 frame.fill(0);
Henrik Lundin64253a92022-02-04 09:02:48 +0000293 StreamConfig config(16000, 1);
peah2ace3f92016-09-10 04:42:27 -0700294 // Call with the default parameters; there should be an init.
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200295 EXPECT_CALL(mock, InitializeLocked).Times(0);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100296 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
Per Åhgren2507f8c2020-03-19 12:33:29 +0100297 EXPECT_NOERR(
298 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000299
300 // New sample rate. (Only impacts ProcessStream).
Henrik Lundin64253a92022-02-04 09:02:48 +0000301 config = StreamConfig(32000, 1);
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200302 EXPECT_CALL(mock, InitializeLocked).Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100303 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000304
305 // New number of channels.
Henrik Lundin64253a92022-02-04 09:02:48 +0000306 config = StreamConfig(32000, 2);
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200307 EXPECT_CALL(mock, InitializeLocked).Times(2);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100308 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
Per Åhgren2507f8c2020-03-19 12:33:29 +0100309 EXPECT_NOERR(
310 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000311
aluebsb0319552016-03-17 20:39:53 -0700312 // A new sample rate passed to ProcessReverseStream should cause an init.
Henrik Lundin64253a92022-02-04 09:02:48 +0000313 config = StreamConfig(16000, 2);
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200314 EXPECT_CALL(mock, InitializeLocked).Times(1);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100315 EXPECT_NOERR(
316 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000317}
318
Alessio Bazzicac054e782018-04-16 12:10:09 +0200319TEST(AudioProcessingImplTest, UpdateCapturePreGainRuntimeSetting) {
Niels Möller4f776ac2021-07-02 11:30:54 +0200320 rtc::scoped_refptr<AudioProcessing> apm =
321 AudioProcessingBuilderForTesting().Create();
Alex Loikob5c9a792018-04-16 16:31:22 +0200322 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
Per Åhgren2507f8c2020-03-19 12:33:29 +0100327 constexpr int kSampleRateHz = 48000;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200328 constexpr int16_t kAudioLevel = 10000;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200329 constexpr size_t kNumChannels = 2;
Alex Loikob5c9a792018-04-16 16:31:22 +0200330
Per Åhgren2507f8c2020-03-19 12:33:29 +0100331 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000332 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100333 frame.fill(kAudioLevel);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100334 apm->ProcessStream(frame.data(), config, config, frame.data());
Per Åhgren2507f8c2020-03-19 12:33:29 +0100335 EXPECT_EQ(frame[100], kAudioLevel)
Alex Loikob5c9a792018-04-16 16:31:22 +0200336 << "With factor 1, frame shouldn't be modified.";
337
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200338 constexpr float kGainFactor = 2.f;
Alex Loikob5c9a792018-04-16 16:31:22 +0200339 apm->SetRuntimeSetting(
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200340 AudioProcessing::RuntimeSetting::CreateCapturePreGain(kGainFactor));
Alex Loikob5c9a792018-04-16 16:31:22 +0200341
342 // Process for two frames to have time to ramp up gain.
343 for (int i = 0; i < 2; ++i) {
Per Åhgren2507f8c2020-03-19 12:33:29 +0100344 frame.fill(kAudioLevel);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100345 apm->ProcessStream(frame.data(), config, config, frame.data());
Alex Loikob5c9a792018-04-16 16:31:22 +0200346 }
Per Åhgren2507f8c2020-03-19 12:33:29 +0100347 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
Alex Loikob5c9a792018-04-16 16:31:22 +0200348 << "Frame should be amplified.";
Alessio Bazzicac054e782018-04-16 12:10:09 +0200349}
350
Per Åhgrendb5d7282021-03-15 16:31:04 +0000351TEST(AudioProcessingImplTest,
352 LevelAdjustmentUpdateCapturePreGainRuntimeSetting) {
Niels Möller4f776ac2021-07-02 11:30:54 +0200353 rtc::scoped_refptr<AudioProcessing> apm =
354 AudioProcessingBuilderForTesting().Create();
Per Åhgrendb5d7282021-03-15 16:31:04 +0000355 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;
Henrik Lundin64253a92022-02-04 09:02:48 +0000365 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgrendb5d7282021-03-15 16:31:04 +0000366 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
384TEST(AudioProcessingImplTest,
385 LevelAdjustmentUpdateCapturePostGainRuntimeSetting) {
Niels Möller4f776ac2021-07-02 11:30:54 +0200386 rtc::scoped_refptr<AudioProcessing> apm =
387 AudioProcessingBuilderForTesting().Create();
Per Åhgrendb5d7282021-03-15 16:31:04 +0000388 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;
Henrik Lundin64253a92022-02-04 09:02:48 +0000398 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgrendb5d7282021-03-15 16:31:04 +0000399 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
Per Åhgren652ada52021-03-03 10:52:44 +0000417TEST(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
Niels Möller4f776ac2021-07-02 11:30:54 +0200424 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgren652ada52021-03-03 10:52:44 +0000425 AudioProcessingBuilderForTesting()
426 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200427 .Create();
Per Åhgren652ada52021-03-03 10:52:44 +0000428
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;
Henrik Lundin64253a92022-02-04 09:02:48 +0000433 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgren652ada52021-03-03 10:52:44 +0000434 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
Alessio Bazzicae4498052018-12-17 09:44:06 +0100499TEST(AudioProcessingImplTest,
500 EchoControllerObservesPreAmplifierEchoPathGainChange) {
501 // Tests that the echo controller observes an echo path gain change when the
502 // pre-amplifier submodule changes the gain.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200503 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Alessio Bazzicae4498052018-12-17 09:44:06 +0100504 const auto* echo_control_factory_ptr = echo_control_factory.get();
505
Niels Möller4f776ac2021-07-02 11:30:54 +0200506 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200507 AudioProcessingBuilderForTesting()
Alessio Bazzicae4498052018-12-17 09:44:06 +0100508 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200509 .Create();
Sam Zackrisson41478c72019-10-15 10:10:26 +0200510 // Disable AGC.
Alessio Bazzicae4498052018-12-17 09:44:06 +0100511 webrtc::AudioProcessing::Config apm_config;
Sam Zackrisson41478c72019-10-15 10:10:26 +0200512 apm_config.gain_controller1.enabled = false;
Alessio Bazzicae4498052018-12-17 09:44:06 +0100513 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
Alessio Bazzicae4498052018-12-17 09:44:06 +0100518 constexpr int16_t kAudioLevel = 10000;
519 constexpr size_t kSampleRateHz = 48000;
520 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100521 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000522 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100523 frame.fill(kAudioLevel);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100524
525 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
526
Per Åhgren0aefbf02019-08-23 21:29:17 +0200527 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200528 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100529 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200530 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100531 apm->ProcessStream(frame.data(), config, config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100532
Per Åhgren0aefbf02019-08-23 21:29:17 +0200533 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200534 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100535 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200536 .Times(1);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100537 apm->SetRuntimeSetting(
538 AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100539 apm->ProcessStream(frame.data(), config, config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100540}
541
542TEST(AudioProcessingImplTest,
Per Åhgrendb5d7282021-03-15 16:31:04 +0000543 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
Niels Möller4f776ac2021-07-02 11:30:54 +0200549 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrendb5d7282021-03-15 16:31:04 +0000550 AudioProcessingBuilderForTesting()
551 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200552 .Create();
Per Åhgrendb5d7282021-03-15 16:31:04 +0000553 // 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;
Henrik Lundin64253a92022-02-04 09:02:48 +0000565 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgrendb5d7282021-03-15 16:31:04 +0000566 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
585TEST(AudioProcessingImplTest,
Alessio Bazzicae4498052018-12-17 09:44:06 +0100586 EchoControllerObservesAnalogAgc1EchoPathGainChange) {
587 // Tests that the echo controller observes an echo path gain change when the
588 // AGC1 analog adaptive submodule changes the analog gain.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200589 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Alessio Bazzicae4498052018-12-17 09:44:06 +0100590 const auto* echo_control_factory_ptr = echo_control_factory.get();
591
Niels Möller4f776ac2021-07-02 11:30:54 +0200592 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200593 AudioProcessingBuilderForTesting()
Alessio Bazzicae4498052018-12-17 09:44:06 +0100594 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200595 .Create();
Alessio Bazzicae4498052018-12-17 09:44:06 +0100596 webrtc::AudioProcessing::Config apm_config;
Sam Zackrisson41478c72019-10-15 10:10:26 +0200597 // Enable AGC1.
598 apm_config.gain_controller1.enabled = true;
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200599 apm_config.gain_controller1.analog_gain_controller.enabled = true;
Alessio Bazzicae4498052018-12-17 09:44:06 +0100600 apm_config.gain_controller2.enabled = false;
601 apm_config.pre_amplifier.enabled = false;
602 apm->ApplyConfig(apm_config);
603
Alessio Bazzicae4498052018-12-17 09:44:06 +0100604 constexpr int16_t kAudioLevel = 1000;
605 constexpr size_t kSampleRateHz = 48000;
606 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100607 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000608 StreamConfig stream_config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100609 frame.fill(kAudioLevel);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100610
611 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
612
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200613 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.
Per Åhgren0aefbf02019-08-23 21:29:17 +0200618 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200619 EXPECT_CALL(*echo_control_mock,
620 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100621 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100622 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100623
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200624 // 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++;
Alessio Bazzicae4498052018-12-17 09:44:06 +0100629 }
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200630 apm->set_stream_analog_level(recommended_analog_level);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100631
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200632 // After the first fame and with a stream analog level change, the echo path
633 // gain change must be detected.
Per Åhgren0aefbf02019-08-23 21:29:17 +0200634 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200635 EXPECT_CALL(*echo_control_mock,
636 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100637 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100638 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100639}
640
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200641// 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.
Hanna Silen0c1ad292022-06-16 16:35:45 +0200644TEST(AudioProcessingImplTest,
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200645 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);
Hanna Silen0c1ad292022-06-16 16:35:45 +0200650 webrtc::AudioProcessing::Config apm_config;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200651 apm_config.gain_controller1.enabled = false;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200652 apm_config.gain_controller2.enabled = true;
653 apm_config.gain_controller2.adaptive_digital.enabled = true;
Alessio Bazzica17e14fd2022-12-07 17:08:45 +0100654 apm_config.transient_suppression.enabled = true;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200655 apm->ApplyConfig(apm_config);
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200656 constexpr int kSampleRateHz = 48000;
657 constexpr int kNumChannels = 1;
658 std::array<float, kSampleRateHz / 100> buffer;
659 float* channel_pointers[] = {buffer.data()};
660 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
661 /*num_channels=*/kNumChannels);
662 Random random_generator(2341U);
663 constexpr int kFramesToProcess = 10;
664 for (int i = 0; i < kFramesToProcess; ++i) {
665 RandomizeSampleVector(&random_generator, buffer);
666 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
667 channel_pointers),
668 kNoErr);
669 }
Hanna Silen0c1ad292022-06-16 16:35:45 +0200670}
671
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200672// Tests that a stream is successfully processed when AGC2 adaptive digital is
673// used and when the field trial
674// `WebRTC-Audio-TransientSuppressorVadMode/Enabled-RnnVad/` is set.
675TEST(AudioProcessingImplTest,
676 ProcessWithAgc2AndTransientSuppressorVadModeRnnVad) {
Hanna Silen0c1ad292022-06-16 16:35:45 +0200677 webrtc::test::ScopedFieldTrials field_trials(
678 "WebRTC-Audio-TransientSuppressorVadMode/Enabled-RnnVad/");
679 rtc::scoped_refptr<AudioProcessing> apm = AudioProcessingBuilder().Create();
680 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
681 webrtc::AudioProcessing::Config apm_config;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200682 apm_config.gain_controller1.enabled = false;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200683 apm_config.gain_controller2.enabled = true;
684 apm_config.gain_controller2.adaptive_digital.enabled = true;
Alessio Bazzica17e14fd2022-12-07 17:08:45 +0100685 apm_config.transient_suppression.enabled = true;
Hanna Silen0c1ad292022-06-16 16:35:45 +0200686 apm->ApplyConfig(apm_config);
687 constexpr int kSampleRateHz = 48000;
688 constexpr int kNumChannels = 1;
689 std::array<float, kSampleRateHz / 100> buffer;
690 float* channel_pointers[] = {buffer.data()};
691 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
692 /*num_channels=*/kNumChannels);
693 Random random_generator(2341U);
694 constexpr int kFramesToProcess = 10;
695 for (int i = 0; i < kFramesToProcess; ++i) {
696 RandomizeSampleVector(&random_generator, buffer);
697 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
698 channel_pointers),
699 kNoErr);
700 }
701}
702
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200703TEST(AudioProcessingImplTest, EchoControllerObservesPlayoutVolumeChange) {
704 // Tests that the echo controller observes an echo path gain change when a
705 // playout volume change is reported.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200706 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200707 const auto* echo_control_factory_ptr = echo_control_factory.get();
708
Niels Möller4f776ac2021-07-02 11:30:54 +0200709 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200710 AudioProcessingBuilderForTesting()
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200711 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200712 .Create();
Sam Zackrisson41478c72019-10-15 10:10:26 +0200713 // Disable AGC.
714 webrtc::AudioProcessing::Config apm_config;
715 apm_config.gain_controller1.enabled = false;
716 apm_config.gain_controller2.enabled = false;
717 apm->ApplyConfig(apm_config);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200718
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200719 constexpr int16_t kAudioLevel = 10000;
720 constexpr size_t kSampleRateHz = 48000;
721 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100722 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000723 StreamConfig stream_config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100724 frame.fill(kAudioLevel);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200725
726 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
727
Per Åhgren0aefbf02019-08-23 21:29:17 +0200728 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200729 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100730 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200731 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100732 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200733
Per Åhgren0aefbf02019-08-23 21:29:17 +0200734 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200735 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100736 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200737 .Times(1);
738 apm->SetRuntimeSetting(
739 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100740 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200741
Per Åhgren0aefbf02019-08-23 21:29:17 +0200742 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200743 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100744 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200745 .Times(1);
746 apm->SetRuntimeSetting(
747 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100748 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200749
Per Åhgren0aefbf02019-08-23 21:29:17 +0200750 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200751 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100752 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200753 .Times(1);
754 apm->SetRuntimeSetting(
755 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(100));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100756 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200757}
758
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200759TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
760 // Make sure that signal changes caused by a render pre-processing sub-module
761 // take place before any echo detector analysis.
Tommi87f70902021-04-27 14:43:08 +0200762 auto test_echo_detector = rtc::make_ref_counted<TestEchoDetector>();
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200763 std::unique_ptr<CustomProcessing> test_render_pre_processor(
764 new TestRenderPreProcessor());
765 // Create APM injecting the test echo detector and render pre-processor.
Niels Möller4f776ac2021-07-02 11:30:54 +0200766 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200767 AudioProcessingBuilderForTesting()
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200768 .SetEchoDetector(test_echo_detector)
769 .SetRenderPreProcessing(std::move(test_render_pre_processor))
Niels Möller4f776ac2021-07-02 11:30:54 +0200770 .Create();
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200771 webrtc::AudioProcessing::Config apm_config;
772 apm_config.pre_amplifier.enabled = true;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200773 apm->ApplyConfig(apm_config);
774
775 constexpr int16_t kAudioLevel = 1000;
776 constexpr int kSampleRateHz = 16000;
777 constexpr size_t kNumChannels = 1;
Sam Zackrisson12e319a2020-01-03 14:54:20 +0100778 // Explicitly initialize APM to ensure no render frames are discarded.
779 const ProcessingConfig processing_config = {{
Henrik Lundin64253a92022-02-04 09:02:48 +0000780 {kSampleRateHz, kNumChannels},
781 {kSampleRateHz, kNumChannels},
782 {kSampleRateHz, kNumChannels},
783 {kSampleRateHz, kNumChannels},
Sam Zackrisson12e319a2020-01-03 14:54:20 +0100784 }};
785 apm->Initialize(processing_config);
786
Per Åhgren2507f8c2020-03-19 12:33:29 +0100787 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000788 StreamConfig stream_config(kSampleRateHz, kNumChannels);
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200789
790 constexpr float kAudioLevelFloat = static_cast<float>(kAudioLevel);
791 constexpr float kExpectedPreprocessedAudioLevel =
792 TestRenderPreProcessor::ProcessSample(kAudioLevelFloat);
793 ASSERT_NE(kAudioLevelFloat, kExpectedPreprocessedAudioLevel);
794
795 // Analyze a render stream frame.
Per Åhgren2507f8c2020-03-19 12:33:29 +0100796 frame.fill(kAudioLevel);
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200797 ASSERT_EQ(AudioProcessing::Error::kNoError,
Per Åhgren2507f8c2020-03-19 12:33:29 +0100798 apm->ProcessReverseStream(frame.data(), stream_config,
799 stream_config, frame.data()));
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200800 // Trigger a call to in EchoDetector::AnalyzeRenderAudio() via
801 // ProcessStream().
Per Åhgren2507f8c2020-03-19 12:33:29 +0100802 frame.fill(kAudioLevel);
803 ASSERT_EQ(AudioProcessing::Error::kNoError,
804 apm->ProcessStream(frame.data(), stream_config, stream_config,
Per Åhgrendc5522b2020-03-19 14:55:58 +0100805 frame.data()));
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200806 // Regardless of how the call to in EchoDetector::AnalyzeRenderAudio() is
807 // triggered, the line below checks that the call has occurred. If not, the
808 // APM implementation may have changed and this test might need to be adapted.
809 ASSERT_TRUE(test_echo_detector->analyze_render_audio_called());
810 // Check that the data read in EchoDetector::AnalyzeRenderAudio() is that
811 // produced by the render pre-processor.
812 EXPECT_EQ(kExpectedPreprocessedAudioLevel,
813 test_echo_detector->last_render_audio_first_sample());
814}
815
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200816// Disabling build-optional submodules and trying to enable them via the APM
817// config should be bit-exact with running APM with said submodules disabled.
818// This mainly tests that SetCreateOptionalSubmodulesForTesting has an effect.
819TEST(ApmWithSubmodulesExcludedTest, BitexactWithDisabledModules) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200820 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200821 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
822
823 ApmSubmoduleCreationOverrides overrides;
824 overrides.transient_suppression = true;
825 apm->OverrideSubmoduleCreationForTesting(overrides);
826
827 AudioProcessing::Config apm_config = apm->GetConfig();
828 apm_config.transient_suppression.enabled = true;
829 apm->ApplyConfig(apm_config);
830
831 rtc::scoped_refptr<AudioProcessing> apm_reference =
832 AudioProcessingBuilder().Create();
833 apm_config = apm_reference->GetConfig();
834 apm_config.transient_suppression.enabled = false;
835 apm_reference->ApplyConfig(apm_config);
836
837 constexpr int kSampleRateHz = 16000;
838 constexpr int kNumChannels = 1;
839 std::array<float, kSampleRateHz / 100> buffer;
840 std::array<float, kSampleRateHz / 100> buffer_reference;
841 float* channel_pointers[] = {buffer.data()};
842 float* channel_pointers_reference[] = {buffer_reference.data()};
843 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
Henrik Lundin64253a92022-02-04 09:02:48 +0000844 /*num_channels=*/kNumChannels);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200845 Random random_generator(2341U);
846 constexpr int kFramesToProcessPerConfiguration = 10;
847
848 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
849 RandomizeSampleVector(&random_generator, buffer);
850 std::copy(buffer.begin(), buffer.end(), buffer_reference.begin());
851 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
852 channel_pointers),
853 kNoErr);
854 ASSERT_EQ(
855 apm_reference->ProcessStream(channel_pointers_reference, stream_config,
856 stream_config, channel_pointers_reference),
857 kNoErr);
858 for (int j = 0; j < kSampleRateHz / 100; ++j) {
859 EXPECT_EQ(buffer[j], buffer_reference[j]);
860 }
861 }
862}
863
864// Disable transient suppressor creation and run APM in ways that should trigger
865// calls to the transient suppressor API.
866TEST(ApmWithSubmodulesExcludedTest, ReinitializeTransientSuppressor) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200867 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200868 ASSERT_EQ(apm->Initialize(), kNoErr);
869
870 ApmSubmoduleCreationOverrides overrides;
871 overrides.transient_suppression = true;
872 apm->OverrideSubmoduleCreationForTesting(overrides);
873
874 AudioProcessing::Config config = apm->GetConfig();
875 config.transient_suppression.enabled = true;
876 apm->ApplyConfig(config);
877 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
878 float buffer[960];
879 float* channel_pointers[] = {&buffer[0], &buffer[480]};
880 Random random_generator(2341U);
881 constexpr int kFramesToProcessPerConfiguration = 3;
882
883 StreamConfig initial_stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000884 /*num_channels=*/1);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200885 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
886 RandomizeSampleVector(&random_generator, buffer);
887 EXPECT_EQ(apm->ProcessStream(channel_pointers, initial_stream_config,
888 initial_stream_config, channel_pointers),
889 kNoErr);
890 }
891
892 StreamConfig stereo_stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000893 /*num_channels=*/2);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200894 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
895 RandomizeSampleVector(&random_generator, buffer);
896 EXPECT_EQ(apm->ProcessStream(channel_pointers, stereo_stream_config,
897 stereo_stream_config, channel_pointers),
898 kNoErr);
899 }
900
901 StreamConfig high_sample_rate_stream_config(/*sample_rate_hz=*/48000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000902 /*num_channels=*/2);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200903 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
904 RandomizeSampleVector(&random_generator, buffer);
905 EXPECT_EQ(
906 apm->ProcessStream(channel_pointers, high_sample_rate_stream_config,
907 high_sample_rate_stream_config, channel_pointers),
908 kNoErr);
909 }
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200910}
911
912// Disable transient suppressor creation and run APM in ways that should trigger
913// calls to the transient suppressor API.
914TEST(ApmWithSubmodulesExcludedTest, ToggleTransientSuppressor) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200915 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200916 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
917
918 ApmSubmoduleCreationOverrides overrides;
919 overrides.transient_suppression = true;
920 apm->OverrideSubmoduleCreationForTesting(overrides);
921
922 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
923 float buffer[960];
924 float* channel_pointers[] = {&buffer[0], &buffer[480]};
925 Random random_generator(2341U);
926 constexpr int kFramesToProcessPerConfiguration = 3;
927 StreamConfig stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000928 /*num_channels=*/1);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200929
930 AudioProcessing::Config config = apm->GetConfig();
931 config.transient_suppression.enabled = true;
932 apm->ApplyConfig(config);
933 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
934 RandomizeSampleVector(&random_generator, buffer);
935 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
936 channel_pointers),
937 kNoErr);
938 }
939
940 config = apm->GetConfig();
941 config.transient_suppression.enabled = false;
942 apm->ApplyConfig(config);
943 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
944 RandomizeSampleVector(&random_generator, buffer);
945 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
946 channel_pointers),
947 kNoErr);
948 }
949
950 config = apm->GetConfig();
951 config.transient_suppression.enabled = true;
952 apm->ApplyConfig(config);
953 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
954 RandomizeSampleVector(&random_generator, buffer);
955 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
956 channel_pointers),
957 kNoErr);
958 }
959}
Hanna Silenc69188d2022-09-16 11:38:56 +0200960
Alessio Bazzica352f38c2022-12-07 16:13:35 +0100961TEST(AudioProcessingImplTest, CanDisableTransientSuppressor) {
962 // Do not explicitly disable "WebRTC-ApmTransientSuppressorKillSwitch" since
963 // to check that, by default, it is disabled.
964 auto apm = AudioProcessingBuilder()
965 .SetConfig({.transient_suppression = {.enabled = false}})
966 .Create();
967 EXPECT_FALSE(apm->GetConfig().transient_suppression.enabled);
968}
969
970TEST(AudioProcessingImplTest, CanEnableTransientSuppressor) {
971 // Do not explicitly disable "WebRTC-ApmTransientSuppressorKillSwitch" since
972 // to check that, by default, it is disabled.
973 auto apm = AudioProcessingBuilder()
974 .SetConfig({.transient_suppression = {.enabled = true}})
975 .Create();
976 EXPECT_TRUE(apm->GetConfig().transient_suppression.enabled);
977}
978
979TEST(AudioProcessingImplTest, CanDisableTransientSuppressorIfUsageAllowed) {
980 // Disable the field trial that disallows to enable transient suppression.
981 test::ScopedFieldTrials field_trials(
982 "WebRTC-ApmTransientSuppressorKillSwitch/Disabled/");
983 auto apm = AudioProcessingBuilder()
984 .SetConfig({.transient_suppression = {.enabled = false}})
985 .Create();
986 EXPECT_FALSE(apm->GetConfig().transient_suppression.enabled);
987}
988
989TEST(AudioProcessingImplTest, CanEnableTransientSuppressorIfUsageAllowed) {
990 // Disable the field trial that disallows to enable transient suppression.
991 test::ScopedFieldTrials field_trials(
992 "WebRTC-ApmTransientSuppressorKillSwitch/Disabled/");
993 auto apm = AudioProcessingBuilder()
994 .SetConfig({.transient_suppression = {.enabled = true}})
995 .Create();
996 EXPECT_TRUE(apm->GetConfig().transient_suppression.enabled);
997}
998
999TEST(AudioProcessingImplTest,
1000 CannotEnableTransientSuppressorIfUsageDisallowed) {
1001 // Enable the field trial that disallows to enable transient suppression.
1002 test::ScopedFieldTrials field_trials(
1003 "WebRTC-ApmTransientSuppressorKillSwitch/Enabled/");
1004 auto apm = AudioProcessingBuilder()
1005 .SetConfig({.transient_suppression = {.enabled = true}})
1006 .Create();
1007 EXPECT_FALSE(apm->GetConfig().transient_suppression.enabled);
1008}
1009
Alessio Bazzica2bfa7672022-12-09 14:16:30 +01001010// TODO(bugs.webrtc.org/7494): Test AGCs with different multi-channel configs.
1011
Hanna Silenc69188d2022-09-16 11:38:56 +02001012// Tests that the minimum startup volume is applied at the startup.
1013TEST_P(InputVolumeStartupParameterizedTest,
1014 VerifyStartupMinVolumeAppliedAtStartup) {
1015 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silenc69188d2022-09-16 11:38:56 +02001016 const int expected_volume =
Alessio Bazzica9ea53812022-10-13 17:09:15 +02001017 std::max(applied_startup_input_volume, GetMinVolume());
Hanna Silend4dbe452022-11-30 15:16:21 +01001018 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1019 const bool agc2_input_volume_controller_enabled =
1020 GetAgc2InputVolumeControllerEnabled();
1021 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1022 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001023
1024 const int recommended_input_volume =
1025 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1026
Hanna Silend4dbe452022-11-30 15:16:21 +01001027 if (!agc1_analog_controller_enabled &&
1028 !agc2_input_volume_controller_enabled) {
1029 // No input volume changes if none of the analog controllers is enabled.
1030 ASSERT_EQ(recommended_input_volume, applied_startup_input_volume);
1031 } else {
1032 ASSERT_EQ(recommended_input_volume, expected_volume);
1033 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001034}
1035
1036// Tests that the minimum input volume is applied if the volume is manually
Hanna Silend4dbe452022-11-30 15:16:21 +01001037// adjusted to a non-zero value 1) always for AGC2 input volume controller and
1038// 2) only if "WebRTC-Audio-2ndAgcMinMicLevelExperiment" is enabled for AGC1
1039// analog controller.
Hanna Silenc69188d2022-09-16 11:38:56 +02001040TEST_P(InputVolumeNotZeroParameterizedTest,
1041 VerifyMinVolumeMaybeAppliedAfterManualVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001042 const int applied_startup_input_volume = GetStartupVolume();
1043 const int applied_input_volume = GetVolume();
1044 const int expected_volume = std::max(applied_input_volume, GetMinVolume());
Hanna Silend4dbe452022-11-30 15:16:21 +01001045 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1046 const bool agc2_input_volume_controller_enabled =
1047 GetAgc2InputVolumeControllerEnabled();
1048 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1049 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001050
1051 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1052 const int recommended_input_volume =
1053 ProcessInputVolume(*apm, /*num_frames=*/1, applied_input_volume);
1054
1055 ASSERT_NE(applied_input_volume, 0);
Hanna Silend4dbe452022-11-30 15:16:21 +01001056
1057 if (!agc1_analog_controller_enabled &&
1058 !agc2_input_volume_controller_enabled) {
1059 // No input volume changes if none of the analog controllers is enabled.
Hanna Silenc69188d2022-09-16 11:38:56 +02001060 ASSERT_EQ(recommended_input_volume, applied_input_volume);
Hanna Silend4dbe452022-11-30 15:16:21 +01001061 } else {
1062 if (GetMinMicLevelExperimentEnabled() ||
1063 (!agc1_analog_controller_enabled &&
1064 agc2_input_volume_controller_enabled)) {
1065 ASSERT_EQ(recommended_input_volume, expected_volume);
1066 } else {
1067 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1068 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001069 }
1070}
1071
1072// Tests that the minimum input volume is not applied if the volume is manually
1073// adjusted to zero.
1074TEST_P(InputVolumeZeroParameterizedTest,
1075 VerifyMinVolumeNotAppliedAfterManualVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001076 constexpr int kZeroVolume = 0;
1077 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001078 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1079 const bool agc2_input_volume_controller_enabled =
1080 GetAgc2InputVolumeControllerEnabled();
1081 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1082 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001083
1084 const int recommended_input_volume_after_startup =
1085 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1086 const int recommended_input_volume =
1087 ProcessInputVolume(*apm, /*num_frames=*/1, kZeroVolume);
1088
Hanna Silend4dbe452022-11-30 15:16:21 +01001089 if (!agc1_analog_controller_enabled &&
1090 !agc2_input_volume_controller_enabled) {
1091 // No input volume changes if none of the analog controllers is enabled.
1092 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1093 } else {
1094 ASSERT_NE(recommended_input_volume, recommended_input_volume_after_startup);
1095 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1096 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001097}
1098
1099// Tests that the minimum input volume is applied if the volume is not zero
1100// before it is automatically adjusted.
1101TEST_P(InputVolumeNotZeroParameterizedTest,
1102 VerifyMinVolumeAppliedAfterAutomaticVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001103 const int applied_startup_input_volume = GetStartupVolume();
1104 const int applied_input_volume = GetVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001105 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1106 const bool agc2_input_volume_controller_enabled =
1107 GetAgc2InputVolumeControllerEnabled();
1108 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1109 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001110
1111 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1112 const int recommended_input_volume =
1113 ProcessInputVolume(*apm, /*num_frames=*/400, applied_input_volume);
1114
1115 ASSERT_NE(applied_input_volume, 0);
Hanna Silend4dbe452022-11-30 15:16:21 +01001116
1117 if (!agc1_analog_controller_enabled &&
1118 !agc2_input_volume_controller_enabled) {
1119 // No input volume changes if none of the analog controllers is enabled.
1120 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1121 } else {
1122 if (recommended_input_volume != applied_input_volume) {
1123 ASSERT_GE(recommended_input_volume, GetMinVolume());
1124 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001125 }
1126}
1127
1128// Tests that the minimum input volume is not applied if the volume is zero
1129// before it is automatically adjusted.
1130TEST_P(InputVolumeZeroParameterizedTest,
1131 VerifyMinVolumeNotAppliedAfterAutomaticVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001132 constexpr int kZeroVolume = 0;
1133 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001134 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1135 const bool agc2_input_volume_controller_enabled =
1136 GetAgc2InputVolumeControllerEnabled();
1137 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1138 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001139
1140 const int recommended_input_volume_after_startup =
1141 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1142 const int recommended_input_volume =
1143 ProcessInputVolume(*apm, /*num_frames=*/400, kZeroVolume);
1144
Hanna Silend4dbe452022-11-30 15:16:21 +01001145 if (!agc1_analog_controller_enabled &&
1146 !agc2_input_volume_controller_enabled) {
1147 // No input volume changes if none of the analog controllers is enabled.
1148 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1149 } else {
1150 ASSERT_NE(recommended_input_volume, recommended_input_volume_after_startup);
1151 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1152 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001153}
1154
1155INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1156 InputVolumeStartupParameterizedTest,
Alessio Bazzica9ea53812022-10-13 17:09:15 +02001157 ::testing::Combine(::testing::Values(0, 5, 30),
Hanna Silenc69188d2022-09-16 11:38:56 +02001158 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001159 20),
1160 ::testing::Bool(),
1161 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001162
1163INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1164 InputVolumeNotZeroParameterizedTest,
1165 ::testing::Combine(::testing::Values(0, 5, 15),
1166 ::testing::Values(1, 5, 30),
1167 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001168 20),
1169 ::testing::Bool(),
1170 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001171
1172INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1173 InputVolumeZeroParameterizedTest,
1174 ::testing::Combine(::testing::Values(0, 5, 15),
1175 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001176 20),
1177 ::testing::Bool(),
1178 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001179
Alessio Bazzica79beaa72022-10-31 16:42:34 +01001180// When the input volume is not emulated and no input volume controller is
1181// active, the recommended volume must always be the applied volume.
1182TEST(AudioProcessingImplTest,
1183 RecommendAppliedInputVolumeWithNoAgcWithNoEmulation) {
1184 auto apm = AudioProcessingBuilder()
1185 .SetConfig({.capture_level_adjustment = {.enabled = false},
1186 .gain_controller1 = {.enabled = false}})
1187 .Create();
1188
1189 constexpr int kOneFrame = 1;
1190 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1191 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1192 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1193}
1194
1195// When the input volume is emulated, the recommended volume must always be the
1196// applied volume and at any time it must not be that set in the input volume
1197// emulator.
1198// TODO(bugs.webrtc.org/14581): Enable when APM fixed to let this test pass.
1199TEST(AudioProcessingImplTest,
1200 DISABLED_RecommendAppliedInputVolumeWithNoAgcWithEmulation) {
1201 auto apm =
1202 AudioProcessingBuilder()
1203 .SetConfig({.capture_level_adjustment = {.enabled = true,
1204 .analog_mic_gain_emulation{
1205 .enabled = true,
1206 .initial_level = 255}},
1207 .gain_controller1 = {.enabled = false}})
1208 .Create();
1209
1210 constexpr int kOneFrame = 1;
1211 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1212 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1213 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1214}
1215
1216// Even if there is an enabled input volume controller, when the input volume is
1217// emulated, the recommended volume is always the applied volume because the
1218// active controller must only adjust the internally emulated volume and leave
1219// the externally applied volume unchanged.
1220// TODO(bugs.webrtc.org/14581): Enable when APM fixed to let this test pass.
1221TEST(AudioProcessingImplTest,
1222 DISABLED_RecommendAppliedInputVolumeWithAgcWithEmulation) {
1223 auto apm =
1224 AudioProcessingBuilder()
1225 .SetConfig({.capture_level_adjustment = {.enabled = true,
1226 .analog_mic_gain_emulation{
1227 .enabled = true}},
1228 .gain_controller1 = {.enabled = true,
1229 .analog_gain_controller{
1230 .enabled = true,
1231 }}})
1232 .Create();
1233
1234 constexpr int kOneFrame = 1;
1235 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1236 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1237 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1238}
1239
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001240class GainController2FieldTrialParametrizedTest
1241 : public ::testing::TestWithParam<AudioProcessing::Config> {};
1242
1243TEST_P(GainController2FieldTrialParametrizedTest,
1244 CheckAgc2AdaptiveDigitalOverridesApplied) {
1245 webrtc::test::ScopedFieldTrials field_trials(
1246 "WebRTC-Audio-GainController2/"
1247 "Enabled,"
1248 "enable_clipping_predictor:true,"
1249 "clipped_level_min:20,"
1250 "clipped_level_step:30,"
1251 "clipped_ratio_threshold:0.4,"
1252 "clipped_wait_frames:50,"
1253 "target_range_max_dbfs:-6,"
1254 "target_range_min_dbfs:-70,"
1255 "update_input_volume_wait_frames:80,"
1256 "speech_probability_threshold:0.9,"
1257 "speech_ratio_threshold:1.0,"
1258 "headroom_db:10,"
1259 "max_gain_db:20,"
1260 "initial_gain_db:7,"
1261 "max_gain_change_db_per_second:5,"
1262 "max_output_noise_level_dbfs:-40/");
1263
1264 auto adjusted_config =
1265 AudioProcessingBuilder().SetConfig(GetParam()).Create()->GetConfig();
1266
1267 EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
1268 EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
1269 EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
1270 EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
1271
1272 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital.headroom_db, 10);
1273 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital.max_gain_db, 20);
1274 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital.initial_gain_db,
1275 7);
1276 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital
1277 .max_gain_change_db_per_second,
1278 5);
1279 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital
1280 .max_output_noise_level_dbfs,
1281 -40);
1282}
1283
1284INSTANTIATE_TEST_SUITE_P(
1285 AudioProcessingImplTest,
1286 GainController2FieldTrialParametrizedTest,
1287 ::testing::Values(
1288 // Full AGC1.
1289 AudioProcessing::Config{
1290 .gain_controller1 =
1291 {.enabled = true,
1292 .analog_gain_controller = {.enabled = true,
1293 .enable_digital_adaptive = true}},
1294 .gain_controller2 = {.enabled = false}},
1295 // Hybrid AGC.
1296 AudioProcessing::Config{
1297 .gain_controller1 =
1298 {.enabled = true,
1299 .analog_gain_controller = {.enabled = true,
1300 .enable_digital_adaptive = false}},
1301 .gain_controller2 = {.enabled = true,
1302 .adaptive_digital = {.enabled = true}}}));
1303
Hanna Silenca653552022-12-08 17:40:01 +01001304TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001305 ConfigAdjustedWhenExperimentEnabledAndAgc1AnalogEnabled) {
Hanna Silenca653552022-12-08 17:40:01 +01001306 constexpr AudioProcessing::Config::GainController2::AdaptiveDigital
1307 kDefaultAdaptiveDigitalConfig;
Hanna Silena6574902022-11-30 16:59:05 +01001308 webrtc::test::ScopedFieldTrials field_trials(
Hanna Silenca653552022-12-08 17:40:01 +01001309 "WebRTC-Audio-GainController2/"
Hanna Silena6574902022-11-30 16:59:05 +01001310 "Enabled,"
1311 "enable_clipping_predictor:true,"
1312 "clipped_level_min:20,"
1313 "clipped_level_step:30,"
1314 "clipped_ratio_threshold:0.4,"
1315 "clipped_wait_frames:50,"
1316 "target_range_max_dbfs:-6,"
1317 "target_range_min_dbfs:-70,"
1318 "update_input_volume_wait_frames:80,"
1319 "speech_probability_threshold:0.9,"
Hanna Silenca653552022-12-08 17:40:01 +01001320 "speech_ratio_threshold:1.0,"
1321 "headroom_db:10,"
1322 "max_gain_db:20,"
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001323 "initial_gain_db:7,"
Hanna Silenca653552022-12-08 17:40:01 +01001324 "max_gain_change_db_per_second:3,"
1325 "max_output_noise_level_dbfs:-40/");
Hanna Silena6574902022-11-30 16:59:05 +01001326
1327 AudioProcessingBuilderForTesting apm_builder;
1328
1329 // Set a config with analog AGC1 enabled.
1330 AudioProcessing::Config config;
1331 config.gain_controller1.enabled = true;
1332 config.gain_controller1.analog_gain_controller.enabled = true;
1333 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1334 config.gain_controller2.enabled = false;
1335 config.gain_controller1.mode =
1336 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1337
1338 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1339
1340 apm_builder.SetConfig(config);
1341
1342 auto apm = apm_builder.Create();
1343 auto adjusted_config = apm->GetConfig();
1344
1345 // Expect the config to be adjusted.
1346 EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
1347 EXPECT_FALSE(adjusted_config.gain_controller1.analog_gain_controller.enabled);
1348 EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
1349 EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
1350 EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
Hanna Silenca653552022-12-08 17:40:01 +01001351 EXPECT_NE(adjusted_config.gain_controller2.adaptive_digital,
1352 kDefaultAdaptiveDigitalConfig);
Hanna Silena6574902022-11-30 16:59:05 +01001353
1354 // Change config back and compare.
1355 adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
1356 adjusted_config.gain_controller1.analog_gain_controller.enabled =
1357 config.gain_controller1.analog_gain_controller.enabled;
1358 adjusted_config.gain_controller2.enabled = config.gain_controller2.enabled;
1359 adjusted_config.gain_controller2.adaptive_digital.enabled =
1360 config.gain_controller2.adaptive_digital.enabled;
1361 adjusted_config.gain_controller2.input_volume_controller.enabled =
1362 config.gain_controller2.input_volume_controller.enabled;
Hanna Silenca653552022-12-08 17:40:01 +01001363 adjusted_config.gain_controller2.adaptive_digital =
1364 config.gain_controller2.adaptive_digital;
Hanna Silena6574902022-11-30 16:59:05 +01001365
1366 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1367}
1368
Hanna Silenca653552022-12-08 17:40:01 +01001369TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001370 ConfigAdjustedWhenExperimentEnabledAndHybridAgcEnabled) {
Hanna Silenca653552022-12-08 17:40:01 +01001371 constexpr AudioProcessing::Config::GainController2::AdaptiveDigital
1372 kDefaultAdaptiveDigitalConfig;
Hanna Silena6574902022-11-30 16:59:05 +01001373 webrtc::test::ScopedFieldTrials field_trials(
Hanna Silenca653552022-12-08 17:40:01 +01001374 "WebRTC-Audio-GainController2/"
Hanna Silena6574902022-11-30 16:59:05 +01001375 "Enabled,"
1376 "enable_clipping_predictor:true,"
1377 "clipped_level_min:20,"
1378 "clipped_level_step:30,"
1379 "clipped_ratio_threshold:0.4,"
1380 "clipped_wait_frames:50,"
1381 "target_range_max_dbfs:-6,"
1382 "target_range_min_dbfs:-70,"
1383 "update_input_volume_wait_frames:80,"
1384 "speech_probability_threshold:0.9,"
Hanna Silenca653552022-12-08 17:40:01 +01001385 "speech_ratio_threshold:1.0,"
1386 "headroom_db:10,"
1387 "max_gain_db:20,"
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001388 "initial_gain_db:7,"
Hanna Silenca653552022-12-08 17:40:01 +01001389 "max_gain_change_db_per_second:3,"
1390 "max_output_noise_level_dbfs:-40/");
Hanna Silena6574902022-11-30 16:59:05 +01001391
1392 AudioProcessingBuilderForTesting apm_builder;
1393
1394 // Set a config with hybrid AGC enabled.
1395 AudioProcessing::Config config;
1396 config.gain_controller1.enabled = true;
1397 config.gain_controller1.analog_gain_controller.enabled = true;
1398 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1399 false;
1400 config.gain_controller2.enabled = true;
1401 config.gain_controller2.adaptive_digital.enabled = true;
1402 config.gain_controller1.mode =
1403 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1404
1405 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1406
1407 apm_builder.SetConfig(config);
1408
1409 auto apm = apm_builder.Create();
1410 auto adjusted_config = apm->GetConfig();
1411
1412 // Expect the config to be adjusted.
1413 EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
1414 EXPECT_FALSE(adjusted_config.gain_controller1.analog_gain_controller.enabled);
1415 EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
1416 EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
1417 EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
Hanna Silenca653552022-12-08 17:40:01 +01001418 EXPECT_NE(adjusted_config.gain_controller2.adaptive_digital,
1419 kDefaultAdaptiveDigitalConfig);
Hanna Silena6574902022-11-30 16:59:05 +01001420
1421 // Change config back and compare.
1422 adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
1423 adjusted_config.gain_controller1.analog_gain_controller.enabled =
1424 config.gain_controller1.analog_gain_controller.enabled;
1425 adjusted_config.gain_controller2.enabled = config.gain_controller2.enabled;
1426 adjusted_config.gain_controller2.adaptive_digital.enabled =
1427 config.gain_controller2.adaptive_digital.enabled;
1428 adjusted_config.gain_controller2.input_volume_controller.enabled =
1429 config.gain_controller2.input_volume_controller.enabled;
Hanna Silenca653552022-12-08 17:40:01 +01001430 adjusted_config.gain_controller2.adaptive_digital =
1431 config.gain_controller2.adaptive_digital;
Hanna Silena6574902022-11-30 16:59:05 +01001432
1433 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1434}
1435
Hanna Silenca653552022-12-08 17:40:01 +01001436TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001437 ConfigNotAdjustedWhenExperimentEnabledAndAgc1AnalogNotEnabled) {
1438 webrtc::test::ScopedFieldTrials field_trials(
Hanna Silenca653552022-12-08 17:40:01 +01001439 "WebRTC-Audio-GainController2/"
Hanna Silena6574902022-11-30 16:59:05 +01001440 "Enabled,"
1441 "enable_clipping_predictor:true,"
1442 "clipped_level_min:20,"
1443 "clipped_level_step:30,"
1444 "clipped_ratio_threshold:0.4,"
1445 "clipped_wait_frames:50,"
1446 "target_range_max_dbfs:-6,"
1447 "target_range_min_dbfs:-70,"
1448 "update_input_volume_wait_frames:80,"
1449 "speech_probability_threshold:0.9,"
Hanna Silenca653552022-12-08 17:40:01 +01001450 "speech_ratio_threshold:1.0,"
1451 "headroom_db:10,"
1452 "max_gain_db:20,"
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001453 "initial_gain_db:7,"
Hanna Silenca653552022-12-08 17:40:01 +01001454 "max_gain_change_db_per_second:3,"
1455 "max_output_noise_level_dbfs:-40/");
Hanna Silena6574902022-11-30 16:59:05 +01001456
1457 AudioProcessingBuilderForTesting apm_builder;
1458
1459 // Set a config with analog AGC1 not enabled.
1460 AudioProcessing::Config config;
1461 config.gain_controller1.enabled = false;
1462 config.gain_controller1.analog_gain_controller.enabled = true;
1463 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1464 config.gain_controller2.enabled = false;
1465 config.gain_controller1.mode =
1466 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1467
1468 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1469
1470 apm_builder.SetConfig(config);
1471
1472 auto apm = apm_builder.Create();
1473 auto adjusted_config = apm->GetConfig();
1474
1475 EXPECT_EQ(config.gain_controller1.enabled,
1476 adjusted_config.gain_controller1.enabled);
1477 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1478 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1479 EXPECT_EQ(config.gain_controller2.enabled,
1480 adjusted_config.gain_controller2.enabled);
1481 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1482 adjusted_config.gain_controller2.adaptive_digital.enabled);
1483 EXPECT_FALSE(
1484 adjusted_config.gain_controller2.input_volume_controller.enabled);
1485
1486 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1487}
1488
Hanna Silenca653552022-12-08 17:40:01 +01001489TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001490 ConfigNotAdjustedWhenExperimentEnabledAndHybridAgcNotEnabled) {
1491 webrtc::test::ScopedFieldTrials field_trials(
Hanna Silenca653552022-12-08 17:40:01 +01001492 "WebRTC-Audio-GainController2/"
Hanna Silena6574902022-11-30 16:59:05 +01001493 "Enabled,"
1494 "enable_clipping_predictor:true,"
1495 "clipped_level_min:20,"
1496 "clipped_level_step:30,"
1497 "clipped_ratio_threshold:0.4,"
1498 "clipped_wait_frames:50,"
1499 "target_range_max_dbfs:-6,"
1500 "target_range_min_dbfs:-70,"
1501 "update_input_volume_wait_frames:80,"
1502 "speech_probability_threshold:0.9,"
Hanna Silenca653552022-12-08 17:40:01 +01001503 "speech_ratio_threshold:1.0,"
1504 "headroom_db:10,"
1505 "max_gain_db:20,"
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001506 "initial_gain_db:7,"
Hanna Silenca653552022-12-08 17:40:01 +01001507 "max_gain_change_db_per_second:3,"
1508 "max_output_noise_level_dbfs:-40/");
Hanna Silena6574902022-11-30 16:59:05 +01001509
1510 AudioProcessingBuilderForTesting apm_builder;
1511
1512 // Set a config with hybrid AGC analog not enabled.
1513 AudioProcessing::Config config;
1514 config.gain_controller1.enabled = false;
1515 config.gain_controller1.analog_gain_controller.enabled = true;
1516 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1517 false;
1518 config.gain_controller2.enabled = true;
1519 config.gain_controller2.adaptive_digital.enabled = true;
1520 config.gain_controller1.mode =
1521 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1522
1523 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1524
1525 apm_builder.SetConfig(config);
1526
1527 auto apm = apm_builder.Create();
1528 auto adjusted_config = apm->GetConfig();
1529
1530 EXPECT_EQ(config.gain_controller1.enabled,
1531 adjusted_config.gain_controller1.enabled);
1532 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1533 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1534 EXPECT_EQ(config.gain_controller2.enabled,
1535 adjusted_config.gain_controller2.enabled);
1536 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1537 adjusted_config.gain_controller2.adaptive_digital.enabled);
1538 EXPECT_FALSE(
1539 adjusted_config.gain_controller2.input_volume_controller.enabled);
1540
1541 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1542}
1543
Hanna Silenca653552022-12-08 17:40:01 +01001544TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001545 ConfigNotAdjustedWhenExperimentNotEnabledAndAgc1AnalogEnabled) {
1546 AudioProcessingBuilderForTesting apm_builder;
1547
1548 // Set a config with analog AGC1 analog enabled.
1549 AudioProcessing::Config config;
1550 config.gain_controller1.enabled = true;
1551 config.gain_controller1.analog_gain_controller.enabled = true;
1552 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1553 config.gain_controller2.enabled = false;
1554 config.gain_controller1.mode =
1555 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1556
1557 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1558
1559 apm_builder.SetConfig(config);
1560
1561 auto apm = apm_builder.Create();
1562 auto adjusted_config = apm->GetConfig();
1563
1564 EXPECT_EQ(config.gain_controller1.enabled,
1565 adjusted_config.gain_controller1.enabled);
1566 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1567 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1568 EXPECT_EQ(config.gain_controller2.enabled,
1569 adjusted_config.gain_controller2.enabled);
1570 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1571 adjusted_config.gain_controller2.adaptive_digital.enabled);
1572 EXPECT_FALSE(
1573 adjusted_config.gain_controller2.input_volume_controller.enabled);
1574
1575 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1576}
1577
Hanna Silenca653552022-12-08 17:40:01 +01001578TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001579 ConfigNotAdjustedWhenExperimentNotEnabledAndHybridAgcEnabled) {
1580 AudioProcessingBuilderForTesting apm_builder;
1581
1582 // Set a config with hybrid AGC enabled.
1583 AudioProcessing::Config config;
1584 config.gain_controller1.enabled = true;
1585 config.gain_controller1.analog_gain_controller.enabled = true;
1586 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1587 false;
1588 config.gain_controller2.enabled = true;
1589 config.gain_controller2.adaptive_digital.enabled = true;
1590 config.gain_controller1.mode =
1591 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1592
1593 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1594
1595 apm_builder.SetConfig(config);
1596
1597 auto apm = apm_builder.Create();
1598 auto adjusted_config = apm->GetConfig();
1599
1600 EXPECT_EQ(config.gain_controller1.enabled,
1601 adjusted_config.gain_controller1.enabled);
1602 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1603 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1604 EXPECT_EQ(config.gain_controller2.enabled,
1605 adjusted_config.gain_controller2.enabled);
1606 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1607 adjusted_config.gain_controller2.adaptive_digital.enabled);
1608 EXPECT_FALSE(
1609 adjusted_config.gain_controller2.input_volume_controller.enabled);
1610
1611 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1612}
1613
andrew@webrtc.org60730cf2014-01-07 17:45:09 +00001614} // namespace webrtc