blob: 7d617bf97f244a607f512fa7f5d4f4498b3c1140 [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>
15
Niels Möller105711e2022-06-14 15:48:26 +020016#include "api/make_ref_counted.h"
Mirko Bonadeid9708072019-01-25 20:26:48 +010017#include "api/scoped_refptr.h"
Alessio Bazzicad2b97402018-08-09 14:23:11 +020018#include "modules/audio_processing/include/audio_processing.h"
Sam Zackrissonb37e59d2020-04-27 08:39:33 +020019#include "modules/audio_processing/optionally_built_submodule_creators.h"
Per Åhgrencc73ed32020-04-26 23:56:17 +020020#include "modules/audio_processing/test/audio_processing_builder_for_testing.h"
Sam Zackrissonb37e59d2020-04-27 08:39:33 +020021#include "modules/audio_processing/test/echo_canceller_test_tools.h"
Alessio Bazzicae4498052018-12-17 09:44:06 +010022#include "modules/audio_processing/test/echo_control_mock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "modules/audio_processing/test/test_utils.h"
Alessio Bazzicae4498052018-12-17 09:44:06 +010024#include "rtc_base/checks.h"
Sam Zackrissonb37e59d2020-04-27 08:39:33 +020025#include "rtc_base/random.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "test/gmock.h"
27#include "test/gtest.h"
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000028
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000029namespace webrtc {
peaha9cc40b2017-06-29 08:32:09 -070030namespace {
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000031
Alessio Bazzicae4498052018-12-17 09:44:06 +010032using ::testing::Invoke;
33using ::testing::NotNull;
34
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000035class MockInitialize : public AudioProcessingImpl {
36 public:
Alessio Bazzicabe1b8982021-09-17 08:26:10 +020037 MockInitialize() : AudioProcessingImpl() {}
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000038
Per Åhgren0ade9832020-09-01 23:57:20 +020039 MOCK_METHOD(void, InitializeLocked, (), (override));
Niels Möller5b747232021-07-26 17:16:25 +020040 void RealInitializeLocked() {
41 AssertLockedForTest();
Per Åhgren0ade9832020-09-01 23:57:20 +020042 AudioProcessingImpl::InitializeLocked();
pbos@webrtc.org788acd12014-12-15 09:41:24 +000043 }
peaha9cc40b2017-06-29 08:32:09 -070044
Danil Chapovalov704fb552020-05-18 15:10:15 +020045 MOCK_METHOD(void, AddRef, (), (const, override));
46 MOCK_METHOD(rtc::RefCountReleaseStatus, Release, (), (const, override));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000047};
48
Alessio Bazzicae4498052018-12-17 09:44:06 +010049// Creates MockEchoControl instances and provides a raw pointer access to
50// the next created one. The raw pointer is meant to be used with gmock.
51// Returning a pointer of the next created MockEchoControl instance is necessary
52// for the following reasons: (i) gmock expectations must be set before any call
53// occurs, (ii) APM is initialized the first time that
54// AudioProcessingImpl::ProcessStream() is called and the initialization leads
55// to the creation of a new EchoControl object.
56class MockEchoControlFactory : public EchoControlFactory {
57 public:
Mirko Bonadei317a1f02019-09-17 17:06:18 +020058 MockEchoControlFactory() : next_mock_(std::make_unique<MockEchoControl>()) {}
Alessio Bazzicae4498052018-12-17 09:44:06 +010059 // Returns a pointer to the next MockEchoControl that this factory creates.
60 MockEchoControl* GetNext() const { return next_mock_.get(); }
Per Åhgren4e5c7092019-11-01 20:44:11 +010061 std::unique_ptr<EchoControl> Create(int sample_rate_hz,
62 int num_render_channels,
63 int num_capture_channels) override {
Alessio Bazzicae4498052018-12-17 09:44:06 +010064 std::unique_ptr<EchoControl> mock = std::move(next_mock_);
Mirko Bonadei317a1f02019-09-17 17:06:18 +020065 next_mock_ = std::make_unique<MockEchoControl>();
Alessio Bazzicae4498052018-12-17 09:44:06 +010066 return mock;
67 }
68
69 private:
70 std::unique_ptr<MockEchoControl> next_mock_;
71};
72
Alessio Bazzicad2b97402018-08-09 14:23:11 +020073// Mocks EchoDetector and records the first samples of the last analyzed render
74// stream frame. Used to check what data is read by an EchoDetector
75// implementation injected into an APM.
76class TestEchoDetector : public EchoDetector {
77 public:
78 TestEchoDetector()
79 : analyze_render_audio_called_(false),
80 last_render_audio_first_sample_(0.f) {}
81 ~TestEchoDetector() override = default;
82 void AnalyzeRenderAudio(rtc::ArrayView<const float> render_audio) override {
83 last_render_audio_first_sample_ = render_audio[0];
84 analyze_render_audio_called_ = true;
85 }
86 void AnalyzeCaptureAudio(rtc::ArrayView<const float> capture_audio) override {
87 }
88 void Initialize(int capture_sample_rate_hz,
89 int num_capture_channels,
90 int render_sample_rate_hz,
91 int num_render_channels) override {}
92 EchoDetector::Metrics GetMetrics() const override { return {}; }
93 // Returns true if AnalyzeRenderAudio() has been called at least once.
94 bool analyze_render_audio_called() const {
95 return analyze_render_audio_called_;
96 }
97 // Returns the first sample of the last analyzed render frame.
98 float last_render_audio_first_sample() const {
99 return last_render_audio_first_sample_;
100 }
101
102 private:
103 bool analyze_render_audio_called_;
104 float last_render_audio_first_sample_;
105};
106
107// Mocks CustomProcessing and applies ProcessSample() to all the samples.
108// Meant to be injected into an APM to modify samples in a known and detectable
109// way.
110class TestRenderPreProcessor : public CustomProcessing {
111 public:
112 TestRenderPreProcessor() = default;
113 ~TestRenderPreProcessor() = default;
114 void Initialize(int sample_rate_hz, int num_channels) override {}
115 void Process(AudioBuffer* audio) override {
116 for (size_t k = 0; k < audio->num_channels(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200117 rtc::ArrayView<float> channel_view(audio->channels()[k],
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200118 audio->num_frames());
119 std::transform(channel_view.begin(), channel_view.end(),
120 channel_view.begin(), ProcessSample);
121 }
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100122 }
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200123 std::string ToString() const override { return "TestRenderPreProcessor"; }
124 void SetRuntimeSetting(AudioProcessing::RuntimeSetting setting) override {}
125 // Modifies a sample. This member is used in Process() to modify a frame and
126 // it is publicly visible to enable tests.
127 static constexpr float ProcessSample(float x) { return 2.f * x; }
128};
129
peaha9cc40b2017-06-29 08:32:09 -0700130} // namespace
131
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000132TEST(AudioProcessingImplTest, AudioParameterChangeTriggersInit) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200133 MockInitialize mock;
134 ON_CALL(mock, InitializeLocked)
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000135 .WillByDefault(Invoke(&mock, &MockInitialize::RealInitializeLocked));
136
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200137 EXPECT_CALL(mock, InitializeLocked).Times(1);
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000138 mock.Initialize();
139
Per Åhgren2507f8c2020-03-19 12:33:29 +0100140 constexpr size_t kMaxSampleRateHz = 32000;
141 constexpr size_t kMaxNumChannels = 2;
142 std::array<int16_t, kMaxNumChannels * kMaxSampleRateHz / 100> frame;
143 frame.fill(0);
Henrik Lundin64253a92022-02-04 09:02:48 +0000144 StreamConfig config(16000, 1);
peah2ace3f92016-09-10 04:42:27 -0700145 // Call with the default parameters; there should be an init.
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200146 EXPECT_CALL(mock, InitializeLocked).Times(0);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100147 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
Per Åhgren2507f8c2020-03-19 12:33:29 +0100148 EXPECT_NOERR(
149 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000150
151 // New sample rate. (Only impacts ProcessStream).
Henrik Lundin64253a92022-02-04 09:02:48 +0000152 config = StreamConfig(32000, 1);
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200153 EXPECT_CALL(mock, InitializeLocked).Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100154 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000155
156 // New number of channels.
peah2ace3f92016-09-10 04:42:27 -0700157 // TODO(peah): Investigate why this causes 2 inits.
Henrik Lundin64253a92022-02-04 09:02:48 +0000158 config = StreamConfig(32000, 2);
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200159 EXPECT_CALL(mock, InitializeLocked).Times(2);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100160 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000161 // ProcessStream sets num_channels_ == num_output_channels.
Per Åhgren2507f8c2020-03-19 12:33:29 +0100162 EXPECT_NOERR(
163 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000164
aluebsb0319552016-03-17 20:39:53 -0700165 // A new sample rate passed to ProcessReverseStream should cause an init.
Henrik Lundin64253a92022-02-04 09:02:48 +0000166 config = StreamConfig(16000, 2);
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200167 EXPECT_CALL(mock, InitializeLocked).Times(1);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100168 EXPECT_NOERR(
169 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000170}
171
Alessio Bazzicac054e782018-04-16 12:10:09 +0200172TEST(AudioProcessingImplTest, UpdateCapturePreGainRuntimeSetting) {
Niels Möller4f776ac2021-07-02 11:30:54 +0200173 rtc::scoped_refptr<AudioProcessing> apm =
174 AudioProcessingBuilderForTesting().Create();
Alex Loikob5c9a792018-04-16 16:31:22 +0200175 webrtc::AudioProcessing::Config apm_config;
176 apm_config.pre_amplifier.enabled = true;
177 apm_config.pre_amplifier.fixed_gain_factor = 1.f;
178 apm->ApplyConfig(apm_config);
179
Per Åhgren2507f8c2020-03-19 12:33:29 +0100180 constexpr int kSampleRateHz = 48000;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200181 constexpr int16_t kAudioLevel = 10000;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200182 constexpr size_t kNumChannels = 2;
Alex Loikob5c9a792018-04-16 16:31:22 +0200183
Per Åhgren2507f8c2020-03-19 12:33:29 +0100184 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000185 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100186 frame.fill(kAudioLevel);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100187 apm->ProcessStream(frame.data(), config, config, frame.data());
Per Åhgren2507f8c2020-03-19 12:33:29 +0100188 EXPECT_EQ(frame[100], kAudioLevel)
Alex Loikob5c9a792018-04-16 16:31:22 +0200189 << "With factor 1, frame shouldn't be modified.";
190
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200191 constexpr float kGainFactor = 2.f;
Alex Loikob5c9a792018-04-16 16:31:22 +0200192 apm->SetRuntimeSetting(
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200193 AudioProcessing::RuntimeSetting::CreateCapturePreGain(kGainFactor));
Alex Loikob5c9a792018-04-16 16:31:22 +0200194
195 // Process for two frames to have time to ramp up gain.
196 for (int i = 0; i < 2; ++i) {
Per Åhgren2507f8c2020-03-19 12:33:29 +0100197 frame.fill(kAudioLevel);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100198 apm->ProcessStream(frame.data(), config, config, frame.data());
Alex Loikob5c9a792018-04-16 16:31:22 +0200199 }
Per Åhgren2507f8c2020-03-19 12:33:29 +0100200 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
Alex Loikob5c9a792018-04-16 16:31:22 +0200201 << "Frame should be amplified.";
Alessio Bazzicac054e782018-04-16 12:10:09 +0200202}
203
Per Åhgrendb5d7282021-03-15 16:31:04 +0000204TEST(AudioProcessingImplTest,
205 LevelAdjustmentUpdateCapturePreGainRuntimeSetting) {
Niels Möller4f776ac2021-07-02 11:30:54 +0200206 rtc::scoped_refptr<AudioProcessing> apm =
207 AudioProcessingBuilderForTesting().Create();
Per Åhgrendb5d7282021-03-15 16:31:04 +0000208 webrtc::AudioProcessing::Config apm_config;
209 apm_config.capture_level_adjustment.enabled = true;
210 apm_config.capture_level_adjustment.pre_gain_factor = 1.f;
211 apm->ApplyConfig(apm_config);
212
213 constexpr int kSampleRateHz = 48000;
214 constexpr int16_t kAudioLevel = 10000;
215 constexpr size_t kNumChannels = 2;
216
217 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000218 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgrendb5d7282021-03-15 16:31:04 +0000219 frame.fill(kAudioLevel);
220 apm->ProcessStream(frame.data(), config, config, frame.data());
221 EXPECT_EQ(frame[100], kAudioLevel)
222 << "With factor 1, frame shouldn't be modified.";
223
224 constexpr float kGainFactor = 2.f;
225 apm->SetRuntimeSetting(
226 AudioProcessing::RuntimeSetting::CreateCapturePreGain(kGainFactor));
227
228 // Process for two frames to have time to ramp up gain.
229 for (int i = 0; i < 2; ++i) {
230 frame.fill(kAudioLevel);
231 apm->ProcessStream(frame.data(), config, config, frame.data());
232 }
233 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
234 << "Frame should be amplified.";
235}
236
237TEST(AudioProcessingImplTest,
238 LevelAdjustmentUpdateCapturePostGainRuntimeSetting) {
Niels Möller4f776ac2021-07-02 11:30:54 +0200239 rtc::scoped_refptr<AudioProcessing> apm =
240 AudioProcessingBuilderForTesting().Create();
Per Åhgrendb5d7282021-03-15 16:31:04 +0000241 webrtc::AudioProcessing::Config apm_config;
242 apm_config.capture_level_adjustment.enabled = true;
243 apm_config.capture_level_adjustment.post_gain_factor = 1.f;
244 apm->ApplyConfig(apm_config);
245
246 constexpr int kSampleRateHz = 48000;
247 constexpr int16_t kAudioLevel = 10000;
248 constexpr size_t kNumChannels = 2;
249
250 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000251 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgrendb5d7282021-03-15 16:31:04 +0000252 frame.fill(kAudioLevel);
253 apm->ProcessStream(frame.data(), config, config, frame.data());
254 EXPECT_EQ(frame[100], kAudioLevel)
255 << "With factor 1, frame shouldn't be modified.";
256
257 constexpr float kGainFactor = 2.f;
258 apm->SetRuntimeSetting(
259 AudioProcessing::RuntimeSetting::CreateCapturePostGain(kGainFactor));
260
261 // Process for two frames to have time to ramp up gain.
262 for (int i = 0; i < 2; ++i) {
263 frame.fill(kAudioLevel);
264 apm->ProcessStream(frame.data(), config, config, frame.data());
265 }
266 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
267 << "Frame should be amplified.";
268}
269
Per Åhgren652ada52021-03-03 10:52:44 +0000270TEST(AudioProcessingImplTest, EchoControllerObservesSetCaptureUsageChange) {
271 // Tests that the echo controller observes that the capture usage has been
272 // updated.
273 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
274 const MockEchoControlFactory* echo_control_factory_ptr =
275 echo_control_factory.get();
276
Niels Möller4f776ac2021-07-02 11:30:54 +0200277 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgren652ada52021-03-03 10:52:44 +0000278 AudioProcessingBuilderForTesting()
279 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200280 .Create();
Per Åhgren652ada52021-03-03 10:52:44 +0000281
282 constexpr int16_t kAudioLevel = 10000;
283 constexpr int kSampleRateHz = 48000;
284 constexpr int kNumChannels = 2;
285 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000286 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgren652ada52021-03-03 10:52:44 +0000287 frame.fill(kAudioLevel);
288
289 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
290
291 // Ensure that SetCaptureOutputUsage is not called when no runtime settings
292 // are passed.
293 EXPECT_CALL(*echo_control_mock, SetCaptureOutputUsage(testing::_)).Times(0);
294 apm->ProcessStream(frame.data(), config, config, frame.data());
295
296 // Ensure that SetCaptureOutputUsage is called with the right information when
297 // a runtime setting is passed.
298 EXPECT_CALL(*echo_control_mock,
299 SetCaptureOutputUsage(/*capture_output_used=*/false))
300 .Times(1);
301 EXPECT_TRUE(apm->PostRuntimeSetting(
302 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
303 /*capture_output_used=*/false)));
304 apm->ProcessStream(frame.data(), config, config, frame.data());
305
306 EXPECT_CALL(*echo_control_mock,
307 SetCaptureOutputUsage(/*capture_output_used=*/true))
308 .Times(1);
309 EXPECT_TRUE(apm->PostRuntimeSetting(
310 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
311 /*capture_output_used=*/true)));
312 apm->ProcessStream(frame.data(), config, config, frame.data());
313
314 // The number of positions to place items in the queue is equal to the queue
315 // size minus 1.
316 constexpr int kNumSlotsInQueue = RuntimeSettingQueueSize();
317
318 // Ensure that SetCaptureOutputUsage is called with the right information when
319 // many runtime settings are passed.
320 for (int k = 0; k < kNumSlotsInQueue - 1; ++k) {
321 EXPECT_TRUE(apm->PostRuntimeSetting(
322 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
323 /*capture_output_used=*/false)));
324 }
325 EXPECT_CALL(*echo_control_mock,
326 SetCaptureOutputUsage(/*capture_output_used=*/false))
327 .Times(kNumSlotsInQueue - 1);
328 apm->ProcessStream(frame.data(), config, config, frame.data());
329
330 // Ensure that SetCaptureOutputUsage is properly called with the fallback
331 // value when the runtime settings queue becomes full.
332 for (int k = 0; k < kNumSlotsInQueue; ++k) {
333 EXPECT_TRUE(apm->PostRuntimeSetting(
334 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
335 /*capture_output_used=*/false)));
336 }
337 EXPECT_FALSE(apm->PostRuntimeSetting(
338 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
339 /*capture_output_used=*/false)));
340 EXPECT_FALSE(apm->PostRuntimeSetting(
341 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
342 /*capture_output_used=*/false)));
343 EXPECT_CALL(*echo_control_mock,
344 SetCaptureOutputUsage(/*capture_output_used=*/false))
345 .Times(kNumSlotsInQueue);
346 EXPECT_CALL(*echo_control_mock,
347 SetCaptureOutputUsage(/*capture_output_used=*/true))
348 .Times(1);
349 apm->ProcessStream(frame.data(), config, config, frame.data());
350}
351
Alessio Bazzicae4498052018-12-17 09:44:06 +0100352TEST(AudioProcessingImplTest,
353 EchoControllerObservesPreAmplifierEchoPathGainChange) {
354 // Tests that the echo controller observes an echo path gain change when the
355 // pre-amplifier submodule changes the gain.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200356 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Alessio Bazzicae4498052018-12-17 09:44:06 +0100357 const auto* echo_control_factory_ptr = echo_control_factory.get();
358
Niels Möller4f776ac2021-07-02 11:30:54 +0200359 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200360 AudioProcessingBuilderForTesting()
Alessio Bazzicae4498052018-12-17 09:44:06 +0100361 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200362 .Create();
Sam Zackrisson41478c72019-10-15 10:10:26 +0200363 // Disable AGC.
Alessio Bazzicae4498052018-12-17 09:44:06 +0100364 webrtc::AudioProcessing::Config apm_config;
Sam Zackrisson41478c72019-10-15 10:10:26 +0200365 apm_config.gain_controller1.enabled = false;
Alessio Bazzicae4498052018-12-17 09:44:06 +0100366 apm_config.gain_controller2.enabled = false;
367 apm_config.pre_amplifier.enabled = true;
368 apm_config.pre_amplifier.fixed_gain_factor = 1.f;
369 apm->ApplyConfig(apm_config);
370
Alessio Bazzicae4498052018-12-17 09:44:06 +0100371 constexpr int16_t kAudioLevel = 10000;
372 constexpr size_t kSampleRateHz = 48000;
373 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100374 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000375 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100376 frame.fill(kAudioLevel);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100377
378 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
379
Per Åhgren0aefbf02019-08-23 21:29:17 +0200380 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200381 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100382 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200383 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100384 apm->ProcessStream(frame.data(), config, config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100385
Per Åhgren0aefbf02019-08-23 21:29:17 +0200386 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200387 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100388 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200389 .Times(1);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100390 apm->SetRuntimeSetting(
391 AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100392 apm->ProcessStream(frame.data(), config, config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100393}
394
395TEST(AudioProcessingImplTest,
Per Åhgrendb5d7282021-03-15 16:31:04 +0000396 EchoControllerObservesLevelAdjustmentPreGainEchoPathGainChange) {
397 // Tests that the echo controller observes an echo path gain change when the
398 // pre-amplifier submodule changes the gain.
399 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
400 const auto* echo_control_factory_ptr = echo_control_factory.get();
401
Niels Möller4f776ac2021-07-02 11:30:54 +0200402 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrendb5d7282021-03-15 16:31:04 +0000403 AudioProcessingBuilderForTesting()
404 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200405 .Create();
Per Åhgrendb5d7282021-03-15 16:31:04 +0000406 // Disable AGC.
407 webrtc::AudioProcessing::Config apm_config;
408 apm_config.gain_controller1.enabled = false;
409 apm_config.gain_controller2.enabled = false;
410 apm_config.capture_level_adjustment.enabled = true;
411 apm_config.capture_level_adjustment.pre_gain_factor = 1.f;
412 apm->ApplyConfig(apm_config);
413
414 constexpr int16_t kAudioLevel = 10000;
415 constexpr size_t kSampleRateHz = 48000;
416 constexpr size_t kNumChannels = 2;
417 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000418 StreamConfig config(kSampleRateHz, kNumChannels);
Per Åhgrendb5d7282021-03-15 16:31:04 +0000419 frame.fill(kAudioLevel);
420
421 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
422
423 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
424 EXPECT_CALL(*echo_control_mock,
425 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
426 .Times(1);
427 apm->ProcessStream(frame.data(), config, config, frame.data());
428
429 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
430 EXPECT_CALL(*echo_control_mock,
431 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
432 .Times(1);
433 apm->SetRuntimeSetting(
434 AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
435 apm->ProcessStream(frame.data(), config, config, frame.data());
436}
437
438TEST(AudioProcessingImplTest,
Alessio Bazzicae4498052018-12-17 09:44:06 +0100439 EchoControllerObservesAnalogAgc1EchoPathGainChange) {
440 // Tests that the echo controller observes an echo path gain change when the
441 // AGC1 analog adaptive submodule changes the analog gain.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200442 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Alessio Bazzicae4498052018-12-17 09:44:06 +0100443 const auto* echo_control_factory_ptr = echo_control_factory.get();
444
Niels Möller4f776ac2021-07-02 11:30:54 +0200445 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200446 AudioProcessingBuilderForTesting()
Alessio Bazzicae4498052018-12-17 09:44:06 +0100447 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200448 .Create();
Alessio Bazzicae4498052018-12-17 09:44:06 +0100449 webrtc::AudioProcessing::Config apm_config;
Sam Zackrisson41478c72019-10-15 10:10:26 +0200450 // Enable AGC1.
451 apm_config.gain_controller1.enabled = true;
452 apm_config.gain_controller1.mode =
453 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
Alessio Bazzicae4498052018-12-17 09:44:06 +0100454 apm_config.gain_controller2.enabled = false;
455 apm_config.pre_amplifier.enabled = false;
456 apm->ApplyConfig(apm_config);
457
Alessio Bazzicae4498052018-12-17 09:44:06 +0100458 constexpr int16_t kAudioLevel = 1000;
459 constexpr size_t kSampleRateHz = 48000;
460 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100461 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000462 StreamConfig stream_config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100463 frame.fill(kAudioLevel);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100464
465 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
466
Sam Zackrisson41478c72019-10-15 10:10:26 +0200467 const int initial_analog_gain = apm->recommended_stream_analog_level();
Per Åhgren0aefbf02019-08-23 21:29:17 +0200468 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100469 EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), testing::_, false))
470 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100471 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100472
473 // Force an analog gain change if it did not happen.
Sam Zackrisson41478c72019-10-15 10:10:26 +0200474 if (initial_analog_gain == apm->recommended_stream_analog_level()) {
475 apm->set_stream_analog_level(initial_analog_gain + 1);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100476 }
477
Per Åhgren0aefbf02019-08-23 21:29:17 +0200478 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100479 EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), testing::_, true))
480 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100481 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100482}
483
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200484TEST(AudioProcessingImplTest, EchoControllerObservesPlayoutVolumeChange) {
485 // Tests that the echo controller observes an echo path gain change when a
486 // playout volume change is reported.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200487 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200488 const auto* echo_control_factory_ptr = echo_control_factory.get();
489
Niels Möller4f776ac2021-07-02 11:30:54 +0200490 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200491 AudioProcessingBuilderForTesting()
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200492 .SetEchoControlFactory(std::move(echo_control_factory))
Niels Möller4f776ac2021-07-02 11:30:54 +0200493 .Create();
Sam Zackrisson41478c72019-10-15 10:10:26 +0200494 // Disable AGC.
495 webrtc::AudioProcessing::Config apm_config;
496 apm_config.gain_controller1.enabled = false;
497 apm_config.gain_controller2.enabled = false;
498 apm->ApplyConfig(apm_config);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200499
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200500 constexpr int16_t kAudioLevel = 10000;
501 constexpr size_t kSampleRateHz = 48000;
502 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100503 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000504 StreamConfig stream_config(kSampleRateHz, kNumChannels);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100505 frame.fill(kAudioLevel);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200506
507 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
508
Per Åhgren0aefbf02019-08-23 21:29:17 +0200509 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200510 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100511 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200512 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100513 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200514
Per Åhgren0aefbf02019-08-23 21:29:17 +0200515 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200516 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100517 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200518 .Times(1);
519 apm->SetRuntimeSetting(
520 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100521 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200522
Per Åhgren0aefbf02019-08-23 21:29:17 +0200523 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200524 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100525 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200526 .Times(1);
527 apm->SetRuntimeSetting(
528 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100529 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200530
Per Åhgren0aefbf02019-08-23 21:29:17 +0200531 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200532 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100533 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200534 .Times(1);
535 apm->SetRuntimeSetting(
536 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(100));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100537 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200538}
539
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200540TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
541 // Make sure that signal changes caused by a render pre-processing sub-module
542 // take place before any echo detector analysis.
Tommi87f70902021-04-27 14:43:08 +0200543 auto test_echo_detector = rtc::make_ref_counted<TestEchoDetector>();
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200544 std::unique_ptr<CustomProcessing> test_render_pre_processor(
545 new TestRenderPreProcessor());
546 // Create APM injecting the test echo detector and render pre-processor.
Niels Möller4f776ac2021-07-02 11:30:54 +0200547 rtc::scoped_refptr<AudioProcessing> apm =
Per Åhgrencc73ed32020-04-26 23:56:17 +0200548 AudioProcessingBuilderForTesting()
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200549 .SetEchoDetector(test_echo_detector)
550 .SetRenderPreProcessing(std::move(test_render_pre_processor))
Niels Möller4f776ac2021-07-02 11:30:54 +0200551 .Create();
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200552 webrtc::AudioProcessing::Config apm_config;
553 apm_config.pre_amplifier.enabled = true;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200554 apm->ApplyConfig(apm_config);
555
556 constexpr int16_t kAudioLevel = 1000;
557 constexpr int kSampleRateHz = 16000;
558 constexpr size_t kNumChannels = 1;
Sam Zackrisson12e319a2020-01-03 14:54:20 +0100559 // Explicitly initialize APM to ensure no render frames are discarded.
560 const ProcessingConfig processing_config = {{
Henrik Lundin64253a92022-02-04 09:02:48 +0000561 {kSampleRateHz, kNumChannels},
562 {kSampleRateHz, kNumChannels},
563 {kSampleRateHz, kNumChannels},
564 {kSampleRateHz, kNumChannels},
Sam Zackrisson12e319a2020-01-03 14:54:20 +0100565 }};
566 apm->Initialize(processing_config);
567
Per Åhgren2507f8c2020-03-19 12:33:29 +0100568 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
Henrik Lundin64253a92022-02-04 09:02:48 +0000569 StreamConfig stream_config(kSampleRateHz, kNumChannels);
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200570
571 constexpr float kAudioLevelFloat = static_cast<float>(kAudioLevel);
572 constexpr float kExpectedPreprocessedAudioLevel =
573 TestRenderPreProcessor::ProcessSample(kAudioLevelFloat);
574 ASSERT_NE(kAudioLevelFloat, kExpectedPreprocessedAudioLevel);
575
576 // Analyze a render stream frame.
Per Åhgren2507f8c2020-03-19 12:33:29 +0100577 frame.fill(kAudioLevel);
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200578 ASSERT_EQ(AudioProcessing::Error::kNoError,
Per Åhgren2507f8c2020-03-19 12:33:29 +0100579 apm->ProcessReverseStream(frame.data(), stream_config,
580 stream_config, frame.data()));
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200581 // Trigger a call to in EchoDetector::AnalyzeRenderAudio() via
582 // ProcessStream().
Per Åhgren2507f8c2020-03-19 12:33:29 +0100583 frame.fill(kAudioLevel);
584 ASSERT_EQ(AudioProcessing::Error::kNoError,
585 apm->ProcessStream(frame.data(), stream_config, stream_config,
Per Åhgrendc5522b2020-03-19 14:55:58 +0100586 frame.data()));
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200587 // Regardless of how the call to in EchoDetector::AnalyzeRenderAudio() is
588 // triggered, the line below checks that the call has occurred. If not, the
589 // APM implementation may have changed and this test might need to be adapted.
590 ASSERT_TRUE(test_echo_detector->analyze_render_audio_called());
591 // Check that the data read in EchoDetector::AnalyzeRenderAudio() is that
592 // produced by the render pre-processor.
593 EXPECT_EQ(kExpectedPreprocessedAudioLevel,
594 test_echo_detector->last_render_audio_first_sample());
595}
596
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200597// Disabling build-optional submodules and trying to enable them via the APM
598// config should be bit-exact with running APM with said submodules disabled.
599// This mainly tests that SetCreateOptionalSubmodulesForTesting has an effect.
600TEST(ApmWithSubmodulesExcludedTest, BitexactWithDisabledModules) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200601 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200602 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
603
604 ApmSubmoduleCreationOverrides overrides;
605 overrides.transient_suppression = true;
606 apm->OverrideSubmoduleCreationForTesting(overrides);
607
608 AudioProcessing::Config apm_config = apm->GetConfig();
609 apm_config.transient_suppression.enabled = true;
610 apm->ApplyConfig(apm_config);
611
612 rtc::scoped_refptr<AudioProcessing> apm_reference =
613 AudioProcessingBuilder().Create();
614 apm_config = apm_reference->GetConfig();
615 apm_config.transient_suppression.enabled = false;
616 apm_reference->ApplyConfig(apm_config);
617
618 constexpr int kSampleRateHz = 16000;
619 constexpr int kNumChannels = 1;
620 std::array<float, kSampleRateHz / 100> buffer;
621 std::array<float, kSampleRateHz / 100> buffer_reference;
622 float* channel_pointers[] = {buffer.data()};
623 float* channel_pointers_reference[] = {buffer_reference.data()};
624 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
Henrik Lundin64253a92022-02-04 09:02:48 +0000625 /*num_channels=*/kNumChannels);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200626 Random random_generator(2341U);
627 constexpr int kFramesToProcessPerConfiguration = 10;
628
629 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
630 RandomizeSampleVector(&random_generator, buffer);
631 std::copy(buffer.begin(), buffer.end(), buffer_reference.begin());
632 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
633 channel_pointers),
634 kNoErr);
635 ASSERT_EQ(
636 apm_reference->ProcessStream(channel_pointers_reference, stream_config,
637 stream_config, channel_pointers_reference),
638 kNoErr);
639 for (int j = 0; j < kSampleRateHz / 100; ++j) {
640 EXPECT_EQ(buffer[j], buffer_reference[j]);
641 }
642 }
643}
644
645// Disable transient suppressor creation and run APM in ways that should trigger
646// calls to the transient suppressor API.
647TEST(ApmWithSubmodulesExcludedTest, ReinitializeTransientSuppressor) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200648 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200649 ASSERT_EQ(apm->Initialize(), kNoErr);
650
651 ApmSubmoduleCreationOverrides overrides;
652 overrides.transient_suppression = true;
653 apm->OverrideSubmoduleCreationForTesting(overrides);
654
655 AudioProcessing::Config config = apm->GetConfig();
656 config.transient_suppression.enabled = true;
657 apm->ApplyConfig(config);
658 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
659 float buffer[960];
660 float* channel_pointers[] = {&buffer[0], &buffer[480]};
661 Random random_generator(2341U);
662 constexpr int kFramesToProcessPerConfiguration = 3;
663
664 StreamConfig initial_stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000665 /*num_channels=*/1);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200666 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
667 RandomizeSampleVector(&random_generator, buffer);
668 EXPECT_EQ(apm->ProcessStream(channel_pointers, initial_stream_config,
669 initial_stream_config, channel_pointers),
670 kNoErr);
671 }
672
673 StreamConfig stereo_stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000674 /*num_channels=*/2);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200675 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
676 RandomizeSampleVector(&random_generator, buffer);
677 EXPECT_EQ(apm->ProcessStream(channel_pointers, stereo_stream_config,
678 stereo_stream_config, channel_pointers),
679 kNoErr);
680 }
681
682 StreamConfig high_sample_rate_stream_config(/*sample_rate_hz=*/48000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000683 /*num_channels=*/2);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200684 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
685 RandomizeSampleVector(&random_generator, buffer);
686 EXPECT_EQ(
687 apm->ProcessStream(channel_pointers, high_sample_rate_stream_config,
688 high_sample_rate_stream_config, channel_pointers),
689 kNoErr);
690 }
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200691}
692
693// Disable transient suppressor creation and run APM in ways that should trigger
694// calls to the transient suppressor API.
695TEST(ApmWithSubmodulesExcludedTest, ToggleTransientSuppressor) {
Alessio Bazzicabe1b8982021-09-17 08:26:10 +0200696 auto apm = rtc::make_ref_counted<AudioProcessingImpl>();
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200697 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
698
699 ApmSubmoduleCreationOverrides overrides;
700 overrides.transient_suppression = true;
701 apm->OverrideSubmoduleCreationForTesting(overrides);
702
703 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
704 float buffer[960];
705 float* channel_pointers[] = {&buffer[0], &buffer[480]};
706 Random random_generator(2341U);
707 constexpr int kFramesToProcessPerConfiguration = 3;
708 StreamConfig stream_config(/*sample_rate_hz=*/16000,
Henrik Lundin64253a92022-02-04 09:02:48 +0000709 /*num_channels=*/1);
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200710
711 AudioProcessing::Config config = apm->GetConfig();
712 config.transient_suppression.enabled = true;
713 apm->ApplyConfig(config);
714 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
715 RandomizeSampleVector(&random_generator, buffer);
716 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
717 channel_pointers),
718 kNoErr);
719 }
720
721 config = apm->GetConfig();
722 config.transient_suppression.enabled = false;
723 apm->ApplyConfig(config);
724 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
725 RandomizeSampleVector(&random_generator, buffer);
726 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
727 channel_pointers),
728 kNoErr);
729 }
730
731 config = apm->GetConfig();
732 config.transient_suppression.enabled = true;
733 apm->ApplyConfig(config);
734 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
735 RandomizeSampleVector(&random_generator, buffer);
736 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
737 channel_pointers),
738 kNoErr);
739 }
740}
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000741} // namespace webrtc