blob: 10c11a2b22e7d7aa77759b316a940e91f182f489 [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
Hanna Silenc69188d2022-09-16 11:38:56 +02001010// Tests that the minimum startup volume is applied at the startup.
1011TEST_P(InputVolumeStartupParameterizedTest,
1012 VerifyStartupMinVolumeAppliedAtStartup) {
1013 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silenc69188d2022-09-16 11:38:56 +02001014 const int expected_volume =
Alessio Bazzica9ea53812022-10-13 17:09:15 +02001015 std::max(applied_startup_input_volume, GetMinVolume());
Hanna Silend4dbe452022-11-30 15:16:21 +01001016 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1017 const bool agc2_input_volume_controller_enabled =
1018 GetAgc2InputVolumeControllerEnabled();
1019 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1020 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001021
1022 const int recommended_input_volume =
1023 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1024
Hanna Silend4dbe452022-11-30 15:16:21 +01001025 if (!agc1_analog_controller_enabled &&
1026 !agc2_input_volume_controller_enabled) {
1027 // No input volume changes if none of the analog controllers is enabled.
1028 ASSERT_EQ(recommended_input_volume, applied_startup_input_volume);
1029 } else {
1030 ASSERT_EQ(recommended_input_volume, expected_volume);
1031 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001032}
1033
1034// Tests that the minimum input volume is applied if the volume is manually
Hanna Silend4dbe452022-11-30 15:16:21 +01001035// adjusted to a non-zero value 1) always for AGC2 input volume controller and
1036// 2) only if "WebRTC-Audio-2ndAgcMinMicLevelExperiment" is enabled for AGC1
1037// analog controller.
Hanna Silenc69188d2022-09-16 11:38:56 +02001038TEST_P(InputVolumeNotZeroParameterizedTest,
1039 VerifyMinVolumeMaybeAppliedAfterManualVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001040 const int applied_startup_input_volume = GetStartupVolume();
1041 const int applied_input_volume = GetVolume();
1042 const int expected_volume = std::max(applied_input_volume, GetMinVolume());
Hanna Silend4dbe452022-11-30 15:16:21 +01001043 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1044 const bool agc2_input_volume_controller_enabled =
1045 GetAgc2InputVolumeControllerEnabled();
1046 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1047 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001048
1049 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1050 const int recommended_input_volume =
1051 ProcessInputVolume(*apm, /*num_frames=*/1, applied_input_volume);
1052
1053 ASSERT_NE(applied_input_volume, 0);
Hanna Silend4dbe452022-11-30 15:16:21 +01001054
1055 if (!agc1_analog_controller_enabled &&
1056 !agc2_input_volume_controller_enabled) {
1057 // No input volume changes if none of the analog controllers is enabled.
Hanna Silenc69188d2022-09-16 11:38:56 +02001058 ASSERT_EQ(recommended_input_volume, applied_input_volume);
Hanna Silend4dbe452022-11-30 15:16:21 +01001059 } else {
1060 if (GetMinMicLevelExperimentEnabled() ||
1061 (!agc1_analog_controller_enabled &&
1062 agc2_input_volume_controller_enabled)) {
1063 ASSERT_EQ(recommended_input_volume, expected_volume);
1064 } else {
1065 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1066 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001067 }
1068}
1069
1070// Tests that the minimum input volume is not applied if the volume is manually
1071// adjusted to zero.
1072TEST_P(InputVolumeZeroParameterizedTest,
1073 VerifyMinVolumeNotAppliedAfterManualVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001074 constexpr int kZeroVolume = 0;
1075 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001076 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1077 const bool agc2_input_volume_controller_enabled =
1078 GetAgc2InputVolumeControllerEnabled();
1079 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1080 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001081
1082 const int recommended_input_volume_after_startup =
1083 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1084 const int recommended_input_volume =
1085 ProcessInputVolume(*apm, /*num_frames=*/1, kZeroVolume);
1086
Hanna Silend4dbe452022-11-30 15:16:21 +01001087 if (!agc1_analog_controller_enabled &&
1088 !agc2_input_volume_controller_enabled) {
1089 // No input volume changes if none of the analog controllers is enabled.
1090 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1091 } else {
1092 ASSERT_NE(recommended_input_volume, recommended_input_volume_after_startup);
1093 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1094 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001095}
1096
1097// Tests that the minimum input volume is applied if the volume is not zero
1098// before it is automatically adjusted.
1099TEST_P(InputVolumeNotZeroParameterizedTest,
1100 VerifyMinVolumeAppliedAfterAutomaticVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001101 const int applied_startup_input_volume = GetStartupVolume();
1102 const int applied_input_volume = GetVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001103 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1104 const bool agc2_input_volume_controller_enabled =
1105 GetAgc2InputVolumeControllerEnabled();
1106 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1107 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001108
1109 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1110 const int recommended_input_volume =
1111 ProcessInputVolume(*apm, /*num_frames=*/400, applied_input_volume);
1112
1113 ASSERT_NE(applied_input_volume, 0);
Hanna Silend4dbe452022-11-30 15:16:21 +01001114
1115 if (!agc1_analog_controller_enabled &&
1116 !agc2_input_volume_controller_enabled) {
1117 // No input volume changes if none of the analog controllers is enabled.
1118 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1119 } else {
1120 if (recommended_input_volume != applied_input_volume) {
1121 ASSERT_GE(recommended_input_volume, GetMinVolume());
1122 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001123 }
1124}
1125
1126// Tests that the minimum input volume is not applied if the volume is zero
1127// before it is automatically adjusted.
1128TEST_P(InputVolumeZeroParameterizedTest,
1129 VerifyMinVolumeNotAppliedAfterAutomaticVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001130 constexpr int kZeroVolume = 0;
1131 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001132 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1133 const bool agc2_input_volume_controller_enabled =
1134 GetAgc2InputVolumeControllerEnabled();
1135 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1136 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001137
1138 const int recommended_input_volume_after_startup =
1139 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1140 const int recommended_input_volume =
1141 ProcessInputVolume(*apm, /*num_frames=*/400, kZeroVolume);
1142
Hanna Silend4dbe452022-11-30 15:16:21 +01001143 if (!agc1_analog_controller_enabled &&
1144 !agc2_input_volume_controller_enabled) {
1145 // No input volume changes if none of the analog controllers is enabled.
1146 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1147 } else {
1148 ASSERT_NE(recommended_input_volume, recommended_input_volume_after_startup);
1149 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1150 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001151}
1152
1153INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1154 InputVolumeStartupParameterizedTest,
Alessio Bazzica9ea53812022-10-13 17:09:15 +02001155 ::testing::Combine(::testing::Values(0, 5, 30),
Hanna Silenc69188d2022-09-16 11:38:56 +02001156 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001157 20),
1158 ::testing::Bool(),
1159 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001160
1161INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1162 InputVolumeNotZeroParameterizedTest,
1163 ::testing::Combine(::testing::Values(0, 5, 15),
1164 ::testing::Values(1, 5, 30),
1165 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001166 20),
1167 ::testing::Bool(),
1168 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001169
1170INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1171 InputVolumeZeroParameterizedTest,
1172 ::testing::Combine(::testing::Values(0, 5, 15),
1173 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001174 20),
1175 ::testing::Bool(),
1176 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001177
Alessio Bazzica79beaa72022-10-31 16:42:34 +01001178// When the input volume is not emulated and no input volume controller is
1179// active, the recommended volume must always be the applied volume.
1180TEST(AudioProcessingImplTest,
1181 RecommendAppliedInputVolumeWithNoAgcWithNoEmulation) {
1182 auto apm = AudioProcessingBuilder()
1183 .SetConfig({.capture_level_adjustment = {.enabled = false},
1184 .gain_controller1 = {.enabled = false}})
1185 .Create();
1186
1187 constexpr int kOneFrame = 1;
1188 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1189 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1190 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1191}
1192
1193// When the input volume is emulated, the recommended volume must always be the
1194// applied volume and at any time it must not be that set in the input volume
1195// emulator.
1196// TODO(bugs.webrtc.org/14581): Enable when APM fixed to let this test pass.
1197TEST(AudioProcessingImplTest,
1198 DISABLED_RecommendAppliedInputVolumeWithNoAgcWithEmulation) {
1199 auto apm =
1200 AudioProcessingBuilder()
1201 .SetConfig({.capture_level_adjustment = {.enabled = true,
1202 .analog_mic_gain_emulation{
1203 .enabled = true,
1204 .initial_level = 255}},
1205 .gain_controller1 = {.enabled = false}})
1206 .Create();
1207
1208 constexpr int kOneFrame = 1;
1209 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1210 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1211 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1212}
1213
1214// Even if there is an enabled input volume controller, when the input volume is
1215// emulated, the recommended volume is always the applied volume because the
1216// active controller must only adjust the internally emulated volume and leave
1217// the externally applied volume unchanged.
1218// TODO(bugs.webrtc.org/14581): Enable when APM fixed to let this test pass.
1219TEST(AudioProcessingImplTest,
1220 DISABLED_RecommendAppliedInputVolumeWithAgcWithEmulation) {
1221 auto apm =
1222 AudioProcessingBuilder()
1223 .SetConfig({.capture_level_adjustment = {.enabled = true,
1224 .analog_mic_gain_emulation{
1225 .enabled = true}},
1226 .gain_controller1 = {.enabled = true,
1227 .analog_gain_controller{
1228 .enabled = true,
1229 }}})
1230 .Create();
1231
1232 constexpr int kOneFrame = 1;
1233 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1234 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1235 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1236}
1237
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001238class GainController2FieldTrialParametrizedTest
1239 : public ::testing::TestWithParam<AudioProcessing::Config> {};
1240
1241TEST_P(GainController2FieldTrialParametrizedTest,
1242 CheckAgc2AdaptiveDigitalOverridesApplied) {
1243 webrtc::test::ScopedFieldTrials field_trials(
1244 "WebRTC-Audio-GainController2/"
1245 "Enabled,"
1246 "enable_clipping_predictor:true,"
1247 "clipped_level_min:20,"
1248 "clipped_level_step:30,"
1249 "clipped_ratio_threshold:0.4,"
1250 "clipped_wait_frames:50,"
1251 "target_range_max_dbfs:-6,"
1252 "target_range_min_dbfs:-70,"
1253 "update_input_volume_wait_frames:80,"
1254 "speech_probability_threshold:0.9,"
1255 "speech_ratio_threshold:1.0,"
1256 "headroom_db:10,"
1257 "max_gain_db:20,"
1258 "initial_gain_db:7,"
1259 "max_gain_change_db_per_second:5,"
1260 "max_output_noise_level_dbfs:-40/");
1261
1262 auto adjusted_config =
1263 AudioProcessingBuilder().SetConfig(GetParam()).Create()->GetConfig();
1264
1265 EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
1266 EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
1267 EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
1268 EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
1269
1270 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital.headroom_db, 10);
1271 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital.max_gain_db, 20);
1272 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital.initial_gain_db,
1273 7);
1274 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital
1275 .max_gain_change_db_per_second,
1276 5);
1277 EXPECT_EQ(adjusted_config.gain_controller2.adaptive_digital
1278 .max_output_noise_level_dbfs,
1279 -40);
1280}
1281
1282INSTANTIATE_TEST_SUITE_P(
1283 AudioProcessingImplTest,
1284 GainController2FieldTrialParametrizedTest,
1285 ::testing::Values(
1286 // Full AGC1.
1287 AudioProcessing::Config{
1288 .gain_controller1 =
1289 {.enabled = true,
1290 .analog_gain_controller = {.enabled = true,
1291 .enable_digital_adaptive = true}},
1292 .gain_controller2 = {.enabled = false}},
1293 // Hybrid AGC.
1294 AudioProcessing::Config{
1295 .gain_controller1 =
1296 {.enabled = true,
1297 .analog_gain_controller = {.enabled = true,
1298 .enable_digital_adaptive = false}},
1299 .gain_controller2 = {.enabled = true,
1300 .adaptive_digital = {.enabled = true}}}));
1301
Hanna Silenca653552022-12-08 17:40:01 +01001302TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001303 ConfigAdjustedWhenExperimentEnabledAndAgc1AnalogEnabled) {
Hanna Silenca653552022-12-08 17:40:01 +01001304 constexpr AudioProcessing::Config::GainController2::AdaptiveDigital
1305 kDefaultAdaptiveDigitalConfig;
Hanna Silena6574902022-11-30 16:59:05 +01001306 webrtc::test::ScopedFieldTrials field_trials(
Hanna Silenca653552022-12-08 17:40:01 +01001307 "WebRTC-Audio-GainController2/"
Hanna Silena6574902022-11-30 16:59:05 +01001308 "Enabled,"
1309 "enable_clipping_predictor:true,"
1310 "clipped_level_min:20,"
1311 "clipped_level_step:30,"
1312 "clipped_ratio_threshold:0.4,"
1313 "clipped_wait_frames:50,"
1314 "target_range_max_dbfs:-6,"
1315 "target_range_min_dbfs:-70,"
1316 "update_input_volume_wait_frames:80,"
1317 "speech_probability_threshold:0.9,"
Hanna Silenca653552022-12-08 17:40:01 +01001318 "speech_ratio_threshold:1.0,"
1319 "headroom_db:10,"
1320 "max_gain_db:20,"
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001321 "initial_gain_db:7,"
Hanna Silenca653552022-12-08 17:40:01 +01001322 "max_gain_change_db_per_second:3,"
1323 "max_output_noise_level_dbfs:-40/");
Hanna Silena6574902022-11-30 16:59:05 +01001324
1325 AudioProcessingBuilderForTesting apm_builder;
1326
1327 // Set a config with analog AGC1 enabled.
1328 AudioProcessing::Config config;
1329 config.gain_controller1.enabled = true;
1330 config.gain_controller1.analog_gain_controller.enabled = true;
1331 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1332 config.gain_controller2.enabled = false;
1333 config.gain_controller1.mode =
1334 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1335
1336 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1337
1338 apm_builder.SetConfig(config);
1339
1340 auto apm = apm_builder.Create();
1341 auto adjusted_config = apm->GetConfig();
1342
1343 // Expect the config to be adjusted.
1344 EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
1345 EXPECT_FALSE(adjusted_config.gain_controller1.analog_gain_controller.enabled);
1346 EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
1347 EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
1348 EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
Hanna Silenca653552022-12-08 17:40:01 +01001349 EXPECT_NE(adjusted_config.gain_controller2.adaptive_digital,
1350 kDefaultAdaptiveDigitalConfig);
Hanna Silena6574902022-11-30 16:59:05 +01001351
1352 // Change config back and compare.
1353 adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
1354 adjusted_config.gain_controller1.analog_gain_controller.enabled =
1355 config.gain_controller1.analog_gain_controller.enabled;
1356 adjusted_config.gain_controller2.enabled = config.gain_controller2.enabled;
1357 adjusted_config.gain_controller2.adaptive_digital.enabled =
1358 config.gain_controller2.adaptive_digital.enabled;
1359 adjusted_config.gain_controller2.input_volume_controller.enabled =
1360 config.gain_controller2.input_volume_controller.enabled;
Hanna Silenca653552022-12-08 17:40:01 +01001361 adjusted_config.gain_controller2.adaptive_digital =
1362 config.gain_controller2.adaptive_digital;
Hanna Silena6574902022-11-30 16:59:05 +01001363
1364 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1365}
1366
Hanna Silenca653552022-12-08 17:40:01 +01001367TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001368 ConfigAdjustedWhenExperimentEnabledAndHybridAgcEnabled) {
Hanna Silenca653552022-12-08 17:40:01 +01001369 constexpr AudioProcessing::Config::GainController2::AdaptiveDigital
1370 kDefaultAdaptiveDigitalConfig;
Hanna Silena6574902022-11-30 16:59:05 +01001371 webrtc::test::ScopedFieldTrials field_trials(
Hanna Silenca653552022-12-08 17:40:01 +01001372 "WebRTC-Audio-GainController2/"
Hanna Silena6574902022-11-30 16:59:05 +01001373 "Enabled,"
1374 "enable_clipping_predictor:true,"
1375 "clipped_level_min:20,"
1376 "clipped_level_step:30,"
1377 "clipped_ratio_threshold:0.4,"
1378 "clipped_wait_frames:50,"
1379 "target_range_max_dbfs:-6,"
1380 "target_range_min_dbfs:-70,"
1381 "update_input_volume_wait_frames:80,"
1382 "speech_probability_threshold:0.9,"
Hanna Silenca653552022-12-08 17:40:01 +01001383 "speech_ratio_threshold:1.0,"
1384 "headroom_db:10,"
1385 "max_gain_db:20,"
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001386 "initial_gain_db:7,"
Hanna Silenca653552022-12-08 17:40:01 +01001387 "max_gain_change_db_per_second:3,"
1388 "max_output_noise_level_dbfs:-40/");
Hanna Silena6574902022-11-30 16:59:05 +01001389
1390 AudioProcessingBuilderForTesting apm_builder;
1391
1392 // Set a config with hybrid AGC enabled.
1393 AudioProcessing::Config config;
1394 config.gain_controller1.enabled = true;
1395 config.gain_controller1.analog_gain_controller.enabled = true;
1396 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1397 false;
1398 config.gain_controller2.enabled = true;
1399 config.gain_controller2.adaptive_digital.enabled = true;
1400 config.gain_controller1.mode =
1401 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1402
1403 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1404
1405 apm_builder.SetConfig(config);
1406
1407 auto apm = apm_builder.Create();
1408 auto adjusted_config = apm->GetConfig();
1409
1410 // Expect the config to be adjusted.
1411 EXPECT_FALSE(adjusted_config.gain_controller1.enabled);
1412 EXPECT_FALSE(adjusted_config.gain_controller1.analog_gain_controller.enabled);
1413 EXPECT_TRUE(adjusted_config.gain_controller2.enabled);
1414 EXPECT_TRUE(adjusted_config.gain_controller2.adaptive_digital.enabled);
1415 EXPECT_TRUE(adjusted_config.gain_controller2.input_volume_controller.enabled);
Hanna Silenca653552022-12-08 17:40:01 +01001416 EXPECT_NE(adjusted_config.gain_controller2.adaptive_digital,
1417 kDefaultAdaptiveDigitalConfig);
Hanna Silena6574902022-11-30 16:59:05 +01001418
1419 // Change config back and compare.
1420 adjusted_config.gain_controller1.enabled = config.gain_controller1.enabled;
1421 adjusted_config.gain_controller1.analog_gain_controller.enabled =
1422 config.gain_controller1.analog_gain_controller.enabled;
1423 adjusted_config.gain_controller2.enabled = config.gain_controller2.enabled;
1424 adjusted_config.gain_controller2.adaptive_digital.enabled =
1425 config.gain_controller2.adaptive_digital.enabled;
1426 adjusted_config.gain_controller2.input_volume_controller.enabled =
1427 config.gain_controller2.input_volume_controller.enabled;
Hanna Silenca653552022-12-08 17:40:01 +01001428 adjusted_config.gain_controller2.adaptive_digital =
1429 config.gain_controller2.adaptive_digital;
Hanna Silena6574902022-11-30 16:59:05 +01001430
1431 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1432}
1433
Hanna Silenca653552022-12-08 17:40:01 +01001434TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001435 ConfigNotAdjustedWhenExperimentEnabledAndAgc1AnalogNotEnabled) {
1436 webrtc::test::ScopedFieldTrials field_trials(
Hanna Silenca653552022-12-08 17:40:01 +01001437 "WebRTC-Audio-GainController2/"
Hanna Silena6574902022-11-30 16:59:05 +01001438 "Enabled,"
1439 "enable_clipping_predictor:true,"
1440 "clipped_level_min:20,"
1441 "clipped_level_step:30,"
1442 "clipped_ratio_threshold:0.4,"
1443 "clipped_wait_frames:50,"
1444 "target_range_max_dbfs:-6,"
1445 "target_range_min_dbfs:-70,"
1446 "update_input_volume_wait_frames:80,"
1447 "speech_probability_threshold:0.9,"
Hanna Silenca653552022-12-08 17:40:01 +01001448 "speech_ratio_threshold:1.0,"
1449 "headroom_db:10,"
1450 "max_gain_db:20,"
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001451 "initial_gain_db:7,"
Hanna Silenca653552022-12-08 17:40:01 +01001452 "max_gain_change_db_per_second:3,"
1453 "max_output_noise_level_dbfs:-40/");
Hanna Silena6574902022-11-30 16:59:05 +01001454
1455 AudioProcessingBuilderForTesting apm_builder;
1456
1457 // Set a config with analog AGC1 not enabled.
1458 AudioProcessing::Config config;
1459 config.gain_controller1.enabled = false;
1460 config.gain_controller1.analog_gain_controller.enabled = true;
1461 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1462 config.gain_controller2.enabled = false;
1463 config.gain_controller1.mode =
1464 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1465
1466 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1467
1468 apm_builder.SetConfig(config);
1469
1470 auto apm = apm_builder.Create();
1471 auto adjusted_config = apm->GetConfig();
1472
1473 EXPECT_EQ(config.gain_controller1.enabled,
1474 adjusted_config.gain_controller1.enabled);
1475 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1476 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1477 EXPECT_EQ(config.gain_controller2.enabled,
1478 adjusted_config.gain_controller2.enabled);
1479 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1480 adjusted_config.gain_controller2.adaptive_digital.enabled);
1481 EXPECT_FALSE(
1482 adjusted_config.gain_controller2.input_volume_controller.enabled);
1483
1484 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1485}
1486
Hanna Silenca653552022-12-08 17:40:01 +01001487TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001488 ConfigNotAdjustedWhenExperimentEnabledAndHybridAgcNotEnabled) {
1489 webrtc::test::ScopedFieldTrials field_trials(
Hanna Silenca653552022-12-08 17:40:01 +01001490 "WebRTC-Audio-GainController2/"
Hanna Silena6574902022-11-30 16:59:05 +01001491 "Enabled,"
1492 "enable_clipping_predictor:true,"
1493 "clipped_level_min:20,"
1494 "clipped_level_step:30,"
1495 "clipped_ratio_threshold:0.4,"
1496 "clipped_wait_frames:50,"
1497 "target_range_max_dbfs:-6,"
1498 "target_range_min_dbfs:-70,"
1499 "update_input_volume_wait_frames:80,"
1500 "speech_probability_threshold:0.9,"
Hanna Silenca653552022-12-08 17:40:01 +01001501 "speech_ratio_threshold:1.0,"
1502 "headroom_db:10,"
1503 "max_gain_db:20,"
Alessio Bazzicadfba28e2022-12-09 10:02:41 +01001504 "initial_gain_db:7,"
Hanna Silenca653552022-12-08 17:40:01 +01001505 "max_gain_change_db_per_second:3,"
1506 "max_output_noise_level_dbfs:-40/");
Hanna Silena6574902022-11-30 16:59:05 +01001507
1508 AudioProcessingBuilderForTesting apm_builder;
1509
1510 // Set a config with hybrid AGC analog not enabled.
1511 AudioProcessing::Config config;
1512 config.gain_controller1.enabled = false;
1513 config.gain_controller1.analog_gain_controller.enabled = true;
1514 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1515 false;
1516 config.gain_controller2.enabled = true;
1517 config.gain_controller2.adaptive_digital.enabled = true;
1518 config.gain_controller1.mode =
1519 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1520
1521 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1522
1523 apm_builder.SetConfig(config);
1524
1525 auto apm = apm_builder.Create();
1526 auto adjusted_config = apm->GetConfig();
1527
1528 EXPECT_EQ(config.gain_controller1.enabled,
1529 adjusted_config.gain_controller1.enabled);
1530 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1531 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1532 EXPECT_EQ(config.gain_controller2.enabled,
1533 adjusted_config.gain_controller2.enabled);
1534 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1535 adjusted_config.gain_controller2.adaptive_digital.enabled);
1536 EXPECT_FALSE(
1537 adjusted_config.gain_controller2.input_volume_controller.enabled);
1538
1539 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1540}
1541
Hanna Silenca653552022-12-08 17:40:01 +01001542TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001543 ConfigNotAdjustedWhenExperimentNotEnabledAndAgc1AnalogEnabled) {
1544 AudioProcessingBuilderForTesting apm_builder;
1545
1546 // Set a config with analog AGC1 analog enabled.
1547 AudioProcessing::Config config;
1548 config.gain_controller1.enabled = true;
1549 config.gain_controller1.analog_gain_controller.enabled = true;
1550 config.gain_controller1.analog_gain_controller.enable_digital_adaptive = true;
1551 config.gain_controller2.enabled = false;
1552 config.gain_controller1.mode =
1553 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1554
1555 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1556
1557 apm_builder.SetConfig(config);
1558
1559 auto apm = apm_builder.Create();
1560 auto adjusted_config = apm->GetConfig();
1561
1562 EXPECT_EQ(config.gain_controller1.enabled,
1563 adjusted_config.gain_controller1.enabled);
1564 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1565 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1566 EXPECT_EQ(config.gain_controller2.enabled,
1567 adjusted_config.gain_controller2.enabled);
1568 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1569 adjusted_config.gain_controller2.adaptive_digital.enabled);
1570 EXPECT_FALSE(
1571 adjusted_config.gain_controller2.input_volume_controller.enabled);
1572
1573 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1574}
1575
Hanna Silenca653552022-12-08 17:40:01 +01001576TEST(AudioProcessingImplGainController2FieldTrialTest,
Hanna Silena6574902022-11-30 16:59:05 +01001577 ConfigNotAdjustedWhenExperimentNotEnabledAndHybridAgcEnabled) {
1578 AudioProcessingBuilderForTesting apm_builder;
1579
1580 // Set a config with hybrid AGC enabled.
1581 AudioProcessing::Config config;
1582 config.gain_controller1.enabled = true;
1583 config.gain_controller1.analog_gain_controller.enabled = true;
1584 config.gain_controller1.analog_gain_controller.enable_digital_adaptive =
1585 false;
1586 config.gain_controller2.enabled = true;
1587 config.gain_controller2.adaptive_digital.enabled = true;
1588 config.gain_controller1.mode =
1589 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
1590
1591 EXPECT_FALSE(config.gain_controller2.input_volume_controller.enabled);
1592
1593 apm_builder.SetConfig(config);
1594
1595 auto apm = apm_builder.Create();
1596 auto adjusted_config = apm->GetConfig();
1597
1598 EXPECT_EQ(config.gain_controller1.enabled,
1599 adjusted_config.gain_controller1.enabled);
1600 EXPECT_EQ(config.gain_controller1.analog_gain_controller.enabled,
1601 adjusted_config.gain_controller1.analog_gain_controller.enabled);
1602 EXPECT_EQ(config.gain_controller2.enabled,
1603 adjusted_config.gain_controller2.enabled);
1604 EXPECT_EQ(config.gain_controller2.adaptive_digital.enabled,
1605 adjusted_config.gain_controller2.adaptive_digital.enabled);
1606 EXPECT_FALSE(
1607 adjusted_config.gain_controller2.input_volume_controller.enabled);
1608
1609 EXPECT_THAT(adjusted_config.ToString(), ::testing::StrEq(config.ToString()));
1610}
1611
andrew@webrtc.org60730cf2014-01-07 17:45:09 +00001612} // namespace webrtc