blob: fea7a8c74eaf0d034218b83a89cf1941274e9bd7 [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;
651 // Disable AGC1 analog.
652 apm_config.gain_controller1.enabled = false;
653 // Enable AGC2 digital.
654 apm_config.gain_controller2.enabled = true;
655 apm_config.gain_controller2.adaptive_digital.enabled = true;
656 apm->ApplyConfig(apm_config);
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200657 constexpr int kSampleRateHz = 48000;
658 constexpr int kNumChannels = 1;
659 std::array<float, kSampleRateHz / 100> buffer;
660 float* channel_pointers[] = {buffer.data()};
661 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
662 /*num_channels=*/kNumChannels);
663 Random random_generator(2341U);
664 constexpr int kFramesToProcess = 10;
665 for (int i = 0; i < kFramesToProcess; ++i) {
666 RandomizeSampleVector(&random_generator, buffer);
667 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
668 channel_pointers),
669 kNoErr);
670 }
Hanna Silen0c1ad292022-06-16 16:35:45 +0200671}
672
Alessio Bazzicaa5aaedb2022-09-06 16:39:07 +0200673// Tests that a stream is successfully processed when AGC2 adaptive digital is
674// used and when the field trial
675// `WebRTC-Audio-TransientSuppressorVadMode/Enabled-RnnVad/` is set.
676TEST(AudioProcessingImplTest,
677 ProcessWithAgc2AndTransientSuppressorVadModeRnnVad) {
Hanna Silen0c1ad292022-06-16 16:35:45 +0200678 webrtc::test::ScopedFieldTrials field_trials(
679 "WebRTC-Audio-TransientSuppressorVadMode/Enabled-RnnVad/");
680 rtc::scoped_refptr<AudioProcessing> apm = AudioProcessingBuilder().Create();
681 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
682 webrtc::AudioProcessing::Config apm_config;
683 // Disable AGC1 analog.
684 apm_config.gain_controller1.enabled = false;
685 // Enable AGC2 digital.
686 apm_config.gain_controller2.enabled = true;
687 apm_config.gain_controller2.adaptive_digital.enabled = true;
688 apm->ApplyConfig(apm_config);
689 constexpr int kSampleRateHz = 48000;
690 constexpr int kNumChannels = 1;
691 std::array<float, kSampleRateHz / 100> buffer;
692 float* channel_pointers[] = {buffer.data()};
693 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
694 /*num_channels=*/kNumChannels);
695 Random random_generator(2341U);
696 constexpr int kFramesToProcess = 10;
697 for (int i = 0; i < kFramesToProcess; ++i) {
698 RandomizeSampleVector(&random_generator, buffer);
699 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
700 channel_pointers),
701 kNoErr);
702 }
703}
704
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200705TEST(AudioProcessingImplTest, EchoControllerObservesPlayoutVolumeChange) {
706 // Tests that the echo controller observes an echo path gain change when a
707 // playout volume change is reported.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200708 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200709 const auto* echo_control_factory_ptr = echo_control_factory.get();
710
Niels Möller4f776ac2021-07-02 11:30:54 +0200711 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200712 AudioProcessingBuilderForTesting()
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200713 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200714 .Create();
Sam Zackrisson41478c72019-10-15 10:10:26 +0200715 // Disable AGC.
716 webrtc::AudioProcessing::Config apm_config;
717 apm_config.gain_controller1.enabled = false;
718 apm_config.gain_controller2.enabled = false;
719 apm->ApplyConfig(apm_config);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200720
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200721 constexpr int16_t kAudioLevel = 10000;
722 constexpr size_t kSampleRateHz = 48000;
723 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100724 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000725 StreamConfig stream_config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100726 frame.fill(kAudioLevel);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200727
728 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
729
Per Åhgren0aefbf02019-08-23 21:29:17 +0200730 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200731 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100732 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200733 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100734 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200735
Per Åhgren0aefbf02019-08-23 21:29:17 +0200736 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200737 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100738 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200739 .Times(1);
740 apm->SetRuntimeSetting(
741 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100742 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200743
Per Åhgren0aefbf02019-08-23 21:29:17 +0200744 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200745 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100746 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200747 .Times(1);
748 apm->SetRuntimeSetting(
749 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100750 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200751
Per Åhgren0aefbf02019-08-23 21:29:17 +0200752 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200753 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100754 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200755 .Times(1);
756 apm->SetRuntimeSetting(
757 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(100));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100758 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200759}
760
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200761TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
762 // Make sure that signal changes caused by a render pre-processing sub-module
763 // take place before any echo detector analysis.
Tommi87f70902021-04-27 14:43:08 +0200764 auto test_echo_detector = rtc::make_ref_counted<TestEchoDetector>();
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200765 std::unique_ptr<CustomProcessing> test_render_pre_processor(
766 new TestRenderPreProcessor());
767 // Create APM injecting the test echo detector and render pre-processor.
Niels Möller4f776ac2021-07-02 11:30:54 +0200768 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200769 AudioProcessingBuilderForTesting()
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200770 .SetEchoDetector(test_echo_detector)
771 .SetRenderPreProcessing(std::move(test_render_pre_processor))
Niels Möller4f776ac2021-07-02 11:30:54 +0200772 .Create();
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200773 webrtc::AudioProcessing::Config apm_config;
774 apm_config.pre_amplifier.enabled = true;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200775 apm->ApplyConfig(apm_config);
776
777 constexpr int16_t kAudioLevel = 1000;
778 constexpr int kSampleRateHz = 16000;
779 constexpr size_t kNumChannels = 1;
Sam Zackrisson12e319a2020-01-03 14:54:20 +0100780 // Explicitly initialize APM to ensure no render frames are discarded.
781 const ProcessingConfig processing_config = {{
Henrik Lundin64253a92022-02-04 09:02:48 +0000782 {kSampleRateHz, kNumChannels},
783 {kSampleRateHz, kNumChannels},
784 {kSampleRateHz, kNumChannels},
785 {kSampleRateHz, kNumChannels},
Sam Zackrisson12e319a2020-01-03 14:54:20 +0100786 }};
787 apm->Initialize(processing_config);
788
Per Åhgren2507f8c2020-03-19 12:33:29 +0100789 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000790 StreamConfig stream_config(kSampleRateHz, kNumChannels);
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200791
792 constexpr float kAudioLevelFloat = static_cast<float>(kAudioLevel);
793 constexpr float kExpectedPreprocessedAudioLevel =
794 TestRenderPreProcessor::ProcessSample(kAudioLevelFloat);
795 ASSERT_NE(kAudioLevelFloat, kExpectedPreprocessedAudioLevel);
796
797 // Analyze a render stream frame.
Per Åhgren2507f8c2020-03-19 12:33:29 +0100798 frame.fill(kAudioLevel);
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200799 ASSERT_EQ(AudioProcessing::Error::kNoError,
Per Åhgren2507f8c2020-03-19 12:33:29 +0100800 apm->ProcessReverseStream(frame.data(), stream_config,
801 stream_config, frame.data()));
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200802 // Trigger a call to in EchoDetector::AnalyzeRenderAudio() via
803 // ProcessStream().
Per Åhgren2507f8c2020-03-19 12:33:29 +0100804 frame.fill(kAudioLevel);
805 ASSERT_EQ(AudioProcessing::Error::kNoError,
806 apm->ProcessStream(frame.data(), stream_config, stream_config,
Per Åhgrendc5522b2020-03-19 14:55:58 +0100807 frame.data()));
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200808 // Regardless of how the call to in EchoDetector::AnalyzeRenderAudio() is
809 // triggered, the line below checks that the call has occurred. If not, the
810 // APM implementation may have changed and this test might need to be adapted.
811 ASSERT_TRUE(test_echo_detector->analyze_render_audio_called());
812 // Check that the data read in EchoDetector::AnalyzeRenderAudio() is that
813 // produced by the render pre-processor.
814 EXPECT_EQ(kExpectedPreprocessedAudioLevel,
815 test_echo_detector->last_render_audio_first_sample());
816}
817
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200818// Disabling build-optional submodules and trying to enable them via the APM
819// config should be bit-exact with running APM with said submodules disabled.
820// This mainly tests that SetCreateOptionalSubmodulesForTesting has an effect.
821TEST(ApmWithSubmodulesExcludedTest, BitexactWithDisabledModules) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200822 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200823 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
824
825 ApmSubmoduleCreationOverrides overrides;
826 overrides.transient_suppression = true;
827 apm->OverrideSubmoduleCreationForTesting(overrides);
828
829 AudioProcessing::Config apm_config = apm->GetConfig();
830 apm_config.transient_suppression.enabled = true;
831 apm->ApplyConfig(apm_config);
832
833 rtc::scoped_refptr<AudioProcessing> apm_reference =
834 AudioProcessingBuilder().Create();
835 apm_config = apm_reference->GetConfig();
836 apm_config.transient_suppression.enabled = false;
837 apm_reference->ApplyConfig(apm_config);
838
839 constexpr int kSampleRateHz = 16000;
840 constexpr int kNumChannels = 1;
841 std::array<float, kSampleRateHz / 100> buffer;
842 std::array<float, kSampleRateHz / 100> buffer_reference;
843 float* channel_pointers[] = {buffer.data()};
844 float* channel_pointers_reference[] = {buffer_reference.data()};
845 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
Henrik Lundin64253a92022-02-04 09:02:48 +0000846 /*num_channels=*/kNumChannels);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200847 Random random_generator(2341U);
848 constexpr int kFramesToProcessPerConfiguration = 10;
849
850 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
851 RandomizeSampleVector(&random_generator, buffer);
852 std::copy(buffer.begin(), buffer.end(), buffer_reference.begin());
853 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
854 channel_pointers),
855 kNoErr);
856 ASSERT_EQ(
857 apm_reference->ProcessStream(channel_pointers_reference, stream_config,
858 stream_config, channel_pointers_reference),
859 kNoErr);
860 for (int j = 0; j < kSampleRateHz / 100; ++j) {
861 EXPECT_EQ(buffer[j], buffer_reference[j]);
862 }
863 }
864}
865
866// Disable transient suppressor creation and run APM in ways that should trigger
867// calls to the transient suppressor API.
868TEST(ApmWithSubmodulesExcludedTest, ReinitializeTransientSuppressor) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200869 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200870 ASSERT_EQ(apm->Initialize(), kNoErr);
871
872 ApmSubmoduleCreationOverrides overrides;
873 overrides.transient_suppression = true;
874 apm->OverrideSubmoduleCreationForTesting(overrides);
875
876 AudioProcessing::Config config = apm->GetConfig();
877 config.transient_suppression.enabled = true;
878 apm->ApplyConfig(config);
879 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
880 float buffer[960];
881 float* channel_pointers[] = {&buffer[0], &buffer[480]};
882 Random random_generator(2341U);
883 constexpr int kFramesToProcessPerConfiguration = 3;
884
885 StreamConfig initial_stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000886 /*num_channels=*/1);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200887 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
888 RandomizeSampleVector(&random_generator, buffer);
889 EXPECT_EQ(apm->ProcessStream(channel_pointers, initial_stream_config,
890 initial_stream_config, channel_pointers),
891 kNoErr);
892 }
893
894 StreamConfig stereo_stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000895 /*num_channels=*/2);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200896 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
897 RandomizeSampleVector(&random_generator, buffer);
898 EXPECT_EQ(apm->ProcessStream(channel_pointers, stereo_stream_config,
899 stereo_stream_config, channel_pointers),
900 kNoErr);
901 }
902
903 StreamConfig high_sample_rate_stream_config(/*sample_rate_hz=*/48000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000904 /*num_channels=*/2);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200905 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
906 RandomizeSampleVector(&random_generator, buffer);
907 EXPECT_EQ(
908 apm->ProcessStream(channel_pointers, high_sample_rate_stream_config,
909 high_sample_rate_stream_config, channel_pointers),
910 kNoErr);
911 }
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200912}
913
914// Disable transient suppressor creation and run APM in ways that should trigger
915// calls to the transient suppressor API.
916TEST(ApmWithSubmodulesExcludedTest, ToggleTransientSuppressor) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200917 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200918 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
919
920 ApmSubmoduleCreationOverrides overrides;
921 overrides.transient_suppression = true;
922 apm->OverrideSubmoduleCreationForTesting(overrides);
923
924 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
925 float buffer[960];
926 float* channel_pointers[] = {&buffer[0], &buffer[480]};
927 Random random_generator(2341U);
928 constexpr int kFramesToProcessPerConfiguration = 3;
929 StreamConfig stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000930 /*num_channels=*/1);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200931
932 AudioProcessing::Config config = apm->GetConfig();
933 config.transient_suppression.enabled = true;
934 apm->ApplyConfig(config);
935 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
936 RandomizeSampleVector(&random_generator, buffer);
937 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
938 channel_pointers),
939 kNoErr);
940 }
941
942 config = apm->GetConfig();
943 config.transient_suppression.enabled = false;
944 apm->ApplyConfig(config);
945 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
946 RandomizeSampleVector(&random_generator, buffer);
947 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
948 channel_pointers),
949 kNoErr);
950 }
951
952 config = apm->GetConfig();
953 config.transient_suppression.enabled = true;
954 apm->ApplyConfig(config);
955 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
956 RandomizeSampleVector(&random_generator, buffer);
957 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
958 channel_pointers),
959 kNoErr);
960 }
961}
Hanna Silenc69188d2022-09-16 11:38:56 +0200962
963// Tests that the minimum startup volume is applied at the startup.
964TEST_P(InputVolumeStartupParameterizedTest,
965 VerifyStartupMinVolumeAppliedAtStartup) {
966 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silenc69188d2022-09-16 11:38:56 +0200967 const int expected_volume =
Alessio Bazzica9ea53812022-10-13 17:09:15 +0200968 std::max(applied_startup_input_volume, GetMinVolume());
Hanna Silend4dbe452022-11-30 15:16:21 +0100969 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
970 const bool agc2_input_volume_controller_enabled =
971 GetAgc2InputVolumeControllerEnabled();
972 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
973 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +0200974
975 const int recommended_input_volume =
976 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
977
Hanna Silend4dbe452022-11-30 15:16:21 +0100978 if (!agc1_analog_controller_enabled &&
979 !agc2_input_volume_controller_enabled) {
980 // No input volume changes if none of the analog controllers is enabled.
981 ASSERT_EQ(recommended_input_volume, applied_startup_input_volume);
982 } else {
983 ASSERT_EQ(recommended_input_volume, expected_volume);
984 }
Hanna Silenc69188d2022-09-16 11:38:56 +0200985}
986
987// Tests that the minimum input volume is applied if the volume is manually
Hanna Silend4dbe452022-11-30 15:16:21 +0100988// adjusted to a non-zero value 1) always for AGC2 input volume controller and
989// 2) only if "WebRTC-Audio-2ndAgcMinMicLevelExperiment" is enabled for AGC1
990// analog controller.
Hanna Silenc69188d2022-09-16 11:38:56 +0200991TEST_P(InputVolumeNotZeroParameterizedTest,
992 VerifyMinVolumeMaybeAppliedAfterManualVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +0200993 const int applied_startup_input_volume = GetStartupVolume();
994 const int applied_input_volume = GetVolume();
995 const int expected_volume = std::max(applied_input_volume, GetMinVolume());
Hanna Silend4dbe452022-11-30 15:16:21 +0100996 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
997 const bool agc2_input_volume_controller_enabled =
998 GetAgc2InputVolumeControllerEnabled();
999 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1000 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001001
1002 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1003 const int recommended_input_volume =
1004 ProcessInputVolume(*apm, /*num_frames=*/1, applied_input_volume);
1005
1006 ASSERT_NE(applied_input_volume, 0);
Hanna Silend4dbe452022-11-30 15:16:21 +01001007
1008 if (!agc1_analog_controller_enabled &&
1009 !agc2_input_volume_controller_enabled) {
1010 // No input volume changes if none of the analog controllers is enabled.
Hanna Silenc69188d2022-09-16 11:38:56 +02001011 ASSERT_EQ(recommended_input_volume, applied_input_volume);
Hanna Silend4dbe452022-11-30 15:16:21 +01001012 } else {
1013 if (GetMinMicLevelExperimentEnabled() ||
1014 (!agc1_analog_controller_enabled &&
1015 agc2_input_volume_controller_enabled)) {
1016 ASSERT_EQ(recommended_input_volume, expected_volume);
1017 } else {
1018 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1019 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001020 }
1021}
1022
1023// Tests that the minimum input volume is not applied if the volume is manually
1024// adjusted to zero.
1025TEST_P(InputVolumeZeroParameterizedTest,
1026 VerifyMinVolumeNotAppliedAfterManualVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001027 constexpr int kZeroVolume = 0;
1028 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001029 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1030 const bool agc2_input_volume_controller_enabled =
1031 GetAgc2InputVolumeControllerEnabled();
1032 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1033 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001034
1035 const int recommended_input_volume_after_startup =
1036 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1037 const int recommended_input_volume =
1038 ProcessInputVolume(*apm, /*num_frames=*/1, kZeroVolume);
1039
Hanna Silend4dbe452022-11-30 15:16:21 +01001040 if (!agc1_analog_controller_enabled &&
1041 !agc2_input_volume_controller_enabled) {
1042 // No input volume changes if none of the analog controllers is enabled.
1043 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1044 } else {
1045 ASSERT_NE(recommended_input_volume, recommended_input_volume_after_startup);
1046 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1047 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001048}
1049
1050// Tests that the minimum input volume is applied if the volume is not zero
1051// before it is automatically adjusted.
1052TEST_P(InputVolumeNotZeroParameterizedTest,
1053 VerifyMinVolumeAppliedAfterAutomaticVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001054 const int applied_startup_input_volume = GetStartupVolume();
1055 const int applied_input_volume = GetVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001056 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1057 const bool agc2_input_volume_controller_enabled =
1058 GetAgc2InputVolumeControllerEnabled();
1059 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1060 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001061
1062 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1063 const int recommended_input_volume =
1064 ProcessInputVolume(*apm, /*num_frames=*/400, applied_input_volume);
1065
1066 ASSERT_NE(applied_input_volume, 0);
Hanna Silend4dbe452022-11-30 15:16:21 +01001067
1068 if (!agc1_analog_controller_enabled &&
1069 !agc2_input_volume_controller_enabled) {
1070 // No input volume changes if none of the analog controllers is enabled.
1071 ASSERT_EQ(recommended_input_volume, applied_input_volume);
1072 } else {
1073 if (recommended_input_volume != applied_input_volume) {
1074 ASSERT_GE(recommended_input_volume, GetMinVolume());
1075 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001076 }
1077}
1078
1079// Tests that the minimum input volume is not applied if the volume is zero
1080// before it is automatically adjusted.
1081TEST_P(InputVolumeZeroParameterizedTest,
1082 VerifyMinVolumeNotAppliedAfterAutomaticVolumeAdjustments) {
Hanna Silenc69188d2022-09-16 11:38:56 +02001083 constexpr int kZeroVolume = 0;
1084 const int applied_startup_input_volume = GetStartupVolume();
Hanna Silend4dbe452022-11-30 15:16:21 +01001085 const bool agc1_analog_controller_enabled = GetAgc1AnalogControllerEnabled();
1086 const bool agc2_input_volume_controller_enabled =
1087 GetAgc2InputVolumeControllerEnabled();
1088 auto apm = CreateApmForInputVolumeTest(agc1_analog_controller_enabled,
1089 agc2_input_volume_controller_enabled);
Hanna Silenc69188d2022-09-16 11:38:56 +02001090
1091 const int recommended_input_volume_after_startup =
1092 ProcessInputVolume(*apm, /*num_frames=*/1, applied_startup_input_volume);
1093 const int recommended_input_volume =
1094 ProcessInputVolume(*apm, /*num_frames=*/400, kZeroVolume);
1095
Hanna Silend4dbe452022-11-30 15:16:21 +01001096 if (!agc1_analog_controller_enabled &&
1097 !agc2_input_volume_controller_enabled) {
1098 // No input volume changes if none of the analog controllers is enabled.
1099 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1100 } else {
1101 ASSERT_NE(recommended_input_volume, recommended_input_volume_after_startup);
1102 ASSERT_EQ(recommended_input_volume, kZeroVolume);
1103 }
Hanna Silenc69188d2022-09-16 11:38:56 +02001104}
1105
1106INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1107 InputVolumeStartupParameterizedTest,
Alessio Bazzica9ea53812022-10-13 17:09:15 +02001108 ::testing::Combine(::testing::Values(0, 5, 30),
Hanna Silenc69188d2022-09-16 11:38:56 +02001109 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001110 20),
1111 ::testing::Bool(),
1112 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001113
1114INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1115 InputVolumeNotZeroParameterizedTest,
1116 ::testing::Combine(::testing::Values(0, 5, 15),
1117 ::testing::Values(1, 5, 30),
1118 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001119 20),
1120 ::testing::Bool(),
1121 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001122
1123INSTANTIATE_TEST_SUITE_P(AudioProcessingImplTest,
1124 InputVolumeZeroParameterizedTest,
1125 ::testing::Combine(::testing::Values(0, 5, 15),
1126 ::testing::Values(absl::nullopt,
Hanna Silend4dbe452022-11-30 15:16:21 +01001127 20),
1128 ::testing::Bool(),
1129 ::testing::Bool()));
Hanna Silenc69188d2022-09-16 11:38:56 +02001130
Alessio Bazzica79beaa72022-10-31 16:42:34 +01001131// When the input volume is not emulated and no input volume controller is
1132// active, the recommended volume must always be the applied volume.
1133TEST(AudioProcessingImplTest,
1134 RecommendAppliedInputVolumeWithNoAgcWithNoEmulation) {
1135 auto apm = AudioProcessingBuilder()
1136 .SetConfig({.capture_level_adjustment = {.enabled = false},
1137 .gain_controller1 = {.enabled = false}})
1138 .Create();
1139
1140 constexpr int kOneFrame = 1;
1141 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1142 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1143 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1144}
1145
1146// When the input volume is emulated, the recommended volume must always be the
1147// applied volume and at any time it must not be that set in the input volume
1148// emulator.
1149// TODO(bugs.webrtc.org/14581): Enable when APM fixed to let this test pass.
1150TEST(AudioProcessingImplTest,
1151 DISABLED_RecommendAppliedInputVolumeWithNoAgcWithEmulation) {
1152 auto apm =
1153 AudioProcessingBuilder()
1154 .SetConfig({.capture_level_adjustment = {.enabled = true,
1155 .analog_mic_gain_emulation{
1156 .enabled = true,
1157 .initial_level = 255}},
1158 .gain_controller1 = {.enabled = false}})
1159 .Create();
1160
1161 constexpr int kOneFrame = 1;
1162 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1163 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1164 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1165}
1166
1167// Even if there is an enabled input volume controller, when the input volume is
1168// emulated, the recommended volume is always the applied volume because the
1169// active controller must only adjust the internally emulated volume and leave
1170// the externally applied volume unchanged.
1171// TODO(bugs.webrtc.org/14581): Enable when APM fixed to let this test pass.
1172TEST(AudioProcessingImplTest,
1173 DISABLED_RecommendAppliedInputVolumeWithAgcWithEmulation) {
1174 auto apm =
1175 AudioProcessingBuilder()
1176 .SetConfig({.capture_level_adjustment = {.enabled = true,
1177 .analog_mic_gain_emulation{
1178 .enabled = true}},
1179 .gain_controller1 = {.enabled = true,
1180 .analog_gain_controller{
1181 .enabled = true,
1182 }}})
1183 .Create();
1184
1185 constexpr int kOneFrame = 1;
1186 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/123), 123);
1187 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/59), 59);
1188 EXPECT_EQ(ProcessInputVolume(*apm, kOneFrame, /*initial_volume=*/135), 135);
1189}
1190
andrew@webrtc.org60730cf2014-01-07 17:45:09 +00001191} // namespace webrtc