blob: ef1830357a90d8c1eeb6157c2b228403bf43e645 [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
Mirko Bonadeid9708072019-01-25 20:26:48 +010016#include "api/scoped_refptr.h"
Per Åhgren652ada52021-03-03 10:52:44 +000017#include "modules/audio_processing/common.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"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "rtc_base/ref_counted_object.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "test/gmock.h"
28#include "test/gtest.h"
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000029
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000030namespace webrtc {
peaha9cc40b2017-06-29 08:32:09 -070031namespace {
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000032
Alessio Bazzicae4498052018-12-17 09:44:06 +010033using ::testing::Invoke;
34using ::testing::NotNull;
35
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000036class MockInitialize : public AudioProcessingImpl {
37 public:
peah88ac8532016-09-12 16:47:25 -070038 explicit MockInitialize(const webrtc::Config& config)
39 : AudioProcessingImpl(config) {}
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000040
Per Åhgren0ade9832020-09-01 23:57:20 +020041 MOCK_METHOD(void, InitializeLocked, (), (override));
42 void RealInitializeLocked() RTC_NO_THREAD_SAFETY_ANALYSIS {
43 AudioProcessingImpl::InitializeLocked();
pbos@webrtc.org788acd12014-12-15 09:41:24 +000044 }
peaha9cc40b2017-06-29 08:32:09 -070045
Danil Chapovalov704fb552020-05-18 15:10:15 +020046 MOCK_METHOD(void, AddRef, (), (const, override));
47 MOCK_METHOD(rtc::RefCountReleaseStatus, Release, (), (const, override));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +000048};
49
Alessio Bazzicae4498052018-12-17 09:44:06 +010050// Creates MockEchoControl instances and provides a raw pointer access to
51// the next created one. The raw pointer is meant to be used with gmock.
52// Returning a pointer of the next created MockEchoControl instance is necessary
53// for the following reasons: (i) gmock expectations must be set before any call
54// occurs, (ii) APM is initialized the first time that
55// AudioProcessingImpl::ProcessStream() is called and the initialization leads
56// to the creation of a new EchoControl object.
57class MockEchoControlFactory : public EchoControlFactory {
58 public:
Mirko Bonadei317a1f02019-09-17 17:06:18 +020059 MockEchoControlFactory() : next_mock_(std::make_unique<MockEchoControl>()) {}
Alessio Bazzicae4498052018-12-17 09:44:06 +010060 // Returns a pointer to the next MockEchoControl that this factory creates.
61 MockEchoControl* GetNext() const { return next_mock_.get(); }
Per Åhgren4e5c7092019-11-01 20:44:11 +010062 std::unique_ptr<EchoControl> Create(int sample_rate_hz,
63 int num_render_channels,
64 int num_capture_channels) override {
Alessio Bazzicae4498052018-12-17 09:44:06 +010065 std::unique_ptr<EchoControl> mock = std::move(next_mock_);
Mirko Bonadei317a1f02019-09-17 17:06:18 +020066 next_mock_ = std::make_unique<MockEchoControl>();
Alessio Bazzicae4498052018-12-17 09:44:06 +010067 return mock;
68 }
69
70 private:
71 std::unique_ptr<MockEchoControl> next_mock_;
72};
73
Alessio Bazzicad2b97402018-08-09 14:23:11 +020074// Mocks EchoDetector and records the first samples of the last analyzed render
75// stream frame. Used to check what data is read by an EchoDetector
76// implementation injected into an APM.
77class TestEchoDetector : public EchoDetector {
78 public:
79 TestEchoDetector()
80 : analyze_render_audio_called_(false),
81 last_render_audio_first_sample_(0.f) {}
82 ~TestEchoDetector() override = default;
83 void AnalyzeRenderAudio(rtc::ArrayView<const float> render_audio) override {
84 last_render_audio_first_sample_ = render_audio[0];
85 analyze_render_audio_called_ = true;
86 }
87 void AnalyzeCaptureAudio(rtc::ArrayView<const float> capture_audio) override {
88 }
89 void Initialize(int capture_sample_rate_hz,
90 int num_capture_channels,
91 int render_sample_rate_hz,
92 int num_render_channels) override {}
93 EchoDetector::Metrics GetMetrics() const override { return {}; }
94 // Returns true if AnalyzeRenderAudio() has been called at least once.
95 bool analyze_render_audio_called() const {
96 return analyze_render_audio_called_;
97 }
98 // Returns the first sample of the last analyzed render frame.
99 float last_render_audio_first_sample() const {
100 return last_render_audio_first_sample_;
101 }
102
103 private:
104 bool analyze_render_audio_called_;
105 float last_render_audio_first_sample_;
106};
107
108// Mocks CustomProcessing and applies ProcessSample() to all the samples.
109// Meant to be injected into an APM to modify samples in a known and detectable
110// way.
111class TestRenderPreProcessor : public CustomProcessing {
112 public:
113 TestRenderPreProcessor() = default;
114 ~TestRenderPreProcessor() = default;
115 void Initialize(int sample_rate_hz, int num_channels) override {}
116 void Process(AudioBuffer* audio) override {
117 for (size_t k = 0; k < audio->num_channels(); ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200118 rtc::ArrayView<float> channel_view(audio->channels()[k],
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200119 audio->num_frames());
120 std::transform(channel_view.begin(), channel_view.end(),
121 channel_view.begin(), ProcessSample);
122 }
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100123 }
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200124 std::string ToString() const override { return "TestRenderPreProcessor"; }
125 void SetRuntimeSetting(AudioProcessing::RuntimeSetting setting) override {}
126 // Modifies a sample. This member is used in Process() to modify a frame and
127 // it is publicly visible to enable tests.
128 static constexpr float ProcessSample(float x) { return 2.f * x; }
129};
130
peaha9cc40b2017-06-29 08:32:09 -0700131} // namespace
132
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000133TEST(AudioProcessingImplTest, AudioParameterChangeTriggersInit) {
Per Åhgren2507f8c2020-03-19 12:33:29 +0100134 webrtc::Config webrtc_config;
135 MockInitialize mock(webrtc_config);
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000136 ON_CALL(mock, InitializeLocked())
137 .WillByDefault(Invoke(&mock, &MockInitialize::RealInitializeLocked));
138
139 EXPECT_CALL(mock, InitializeLocked()).Times(1);
140 mock.Initialize();
141
Per Åhgren2507f8c2020-03-19 12:33:29 +0100142 constexpr size_t kMaxSampleRateHz = 32000;
143 constexpr size_t kMaxNumChannels = 2;
144 std::array<int16_t, kMaxNumChannels * kMaxSampleRateHz / 100> frame;
145 frame.fill(0);
146 StreamConfig config(16000, 1, /*has_keyboard=*/false);
peah2ace3f92016-09-10 04:42:27 -0700147 // Call with the default parameters; there should be an init.
Per Åhgren4bdced52017-06-27 16:00:38 +0200148 EXPECT_CALL(mock, InitializeLocked()).Times(0);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100149 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
Per Åhgren2507f8c2020-03-19 12:33:29 +0100150 EXPECT_NOERR(
151 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000152
153 // New sample rate. (Only impacts ProcessStream).
Per Åhgren2507f8c2020-03-19 12:33:29 +0100154 config = StreamConfig(32000, 1, /*has_keyboard=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200155 EXPECT_CALL(mock, InitializeLocked()).Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100156 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000157
158 // New number of channels.
peah2ace3f92016-09-10 04:42:27 -0700159 // TODO(peah): Investigate why this causes 2 inits.
Per Åhgren2507f8c2020-03-19 12:33:29 +0100160 config = StreamConfig(32000, 2, /*has_keyboard=*/false);
Yves Gerey665174f2018-06-19 15:03:05 +0200161 EXPECT_CALL(mock, InitializeLocked()).Times(2);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100162 EXPECT_NOERR(mock.ProcessStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000163 // ProcessStream sets num_channels_ == num_output_channels.
Per Åhgren2507f8c2020-03-19 12:33:29 +0100164 EXPECT_NOERR(
165 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000166
aluebsb0319552016-03-17 20:39:53 -0700167 // A new sample rate passed to ProcessReverseStream should cause an init.
Per Åhgren2507f8c2020-03-19 12:33:29 +0100168 config = StreamConfig(16000, 2, /*has_keyboard=*/false);
Alex Luebs5b830fe2016-03-08 17:52:52 +0100169 EXPECT_CALL(mock, InitializeLocked()).Times(1);
Per Åhgren2507f8c2020-03-19 12:33:29 +0100170 EXPECT_NOERR(
171 mock.ProcessReverseStream(frame.data(), config, config, frame.data()));
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000172}
173
Alessio Bazzicac054e782018-04-16 12:10:09 +0200174TEST(AudioProcessingImplTest, UpdateCapturePreGainRuntimeSetting) {
Per Åhgrencc73ed32020-04-26 23:56:17 +0200175 std::unique_ptr<AudioProcessing> apm(
176 AudioProcessingBuilderForTesting().Create());
Alex Loikob5c9a792018-04-16 16:31:22 +0200177 webrtc::AudioProcessing::Config apm_config;
178 apm_config.pre_amplifier.enabled = true;
179 apm_config.pre_amplifier.fixed_gain_factor = 1.f;
180 apm->ApplyConfig(apm_config);
181
Per Åhgren2507f8c2020-03-19 12:33:29 +0100182 constexpr int kSampleRateHz = 48000;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200183 constexpr int16_t kAudioLevel = 10000;
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200184 constexpr size_t kNumChannels = 2;
Alex Loikob5c9a792018-04-16 16:31:22 +0200185
Per Åhgren2507f8c2020-03-19 12:33:29 +0100186 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
187 StreamConfig config(kSampleRateHz, kNumChannels, /*has_keyboard=*/false);
188 frame.fill(kAudioLevel);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100189 apm->ProcessStream(frame.data(), config, config, frame.data());
Per Åhgren2507f8c2020-03-19 12:33:29 +0100190 EXPECT_EQ(frame[100], kAudioLevel)
Alex Loikob5c9a792018-04-16 16:31:22 +0200191 << "With factor 1, frame shouldn't be modified.";
192
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200193 constexpr float kGainFactor = 2.f;
Alex Loikob5c9a792018-04-16 16:31:22 +0200194 apm->SetRuntimeSetting(
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200195 AudioProcessing::RuntimeSetting::CreateCapturePreGain(kGainFactor));
Alex Loikob5c9a792018-04-16 16:31:22 +0200196
197 // Process for two frames to have time to ramp up gain.
198 for (int i = 0; i < 2; ++i) {
Per Åhgren2507f8c2020-03-19 12:33:29 +0100199 frame.fill(kAudioLevel);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100200 apm->ProcessStream(frame.data(), config, config, frame.data());
Alex Loikob5c9a792018-04-16 16:31:22 +0200201 }
Per Åhgren2507f8c2020-03-19 12:33:29 +0100202 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
Alex Loikob5c9a792018-04-16 16:31:22 +0200203 << "Frame should be amplified.";
Alessio Bazzicac054e782018-04-16 12:10:09 +0200204}
205
Per Åhgrendb5d7282021-03-15 16:31:04 +0000206TEST(AudioProcessingImplTest,
207 LevelAdjustmentUpdateCapturePreGainRuntimeSetting) {
208 std::unique_ptr<AudioProcessing> apm(
209 AudioProcessingBuilderForTesting().Create());
210 webrtc::AudioProcessing::Config apm_config;
211 apm_config.capture_level_adjustment.enabled = true;
212 apm_config.capture_level_adjustment.pre_gain_factor = 1.f;
213 apm->ApplyConfig(apm_config);
214
215 constexpr int kSampleRateHz = 48000;
216 constexpr int16_t kAudioLevel = 10000;
217 constexpr size_t kNumChannels = 2;
218
219 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
220 StreamConfig config(kSampleRateHz, kNumChannels, /*has_keyboard=*/false);
221 frame.fill(kAudioLevel);
222 apm->ProcessStream(frame.data(), config, config, frame.data());
223 EXPECT_EQ(frame[100], kAudioLevel)
224 << "With factor 1, frame shouldn't be modified.";
225
226 constexpr float kGainFactor = 2.f;
227 apm->SetRuntimeSetting(
228 AudioProcessing::RuntimeSetting::CreateCapturePreGain(kGainFactor));
229
230 // Process for two frames to have time to ramp up gain.
231 for (int i = 0; i < 2; ++i) {
232 frame.fill(kAudioLevel);
233 apm->ProcessStream(frame.data(), config, config, frame.data());
234 }
235 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
236 << "Frame should be amplified.";
237}
238
239TEST(AudioProcessingImplTest,
240 LevelAdjustmentUpdateCapturePostGainRuntimeSetting) {
241 std::unique_ptr<AudioProcessing> apm(
242 AudioProcessingBuilderForTesting().Create());
243 webrtc::AudioProcessing::Config apm_config;
244 apm_config.capture_level_adjustment.enabled = true;
245 apm_config.capture_level_adjustment.post_gain_factor = 1.f;
246 apm->ApplyConfig(apm_config);
247
248 constexpr int kSampleRateHz = 48000;
249 constexpr int16_t kAudioLevel = 10000;
250 constexpr size_t kNumChannels = 2;
251
252 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
253 StreamConfig config(kSampleRateHz, kNumChannels, /*has_keyboard=*/false);
254 frame.fill(kAudioLevel);
255 apm->ProcessStream(frame.data(), config, config, frame.data());
256 EXPECT_EQ(frame[100], kAudioLevel)
257 << "With factor 1, frame shouldn't be modified.";
258
259 constexpr float kGainFactor = 2.f;
260 apm->SetRuntimeSetting(
261 AudioProcessing::RuntimeSetting::CreateCapturePostGain(kGainFactor));
262
263 // Process for two frames to have time to ramp up gain.
264 for (int i = 0; i < 2; ++i) {
265 frame.fill(kAudioLevel);
266 apm->ProcessStream(frame.data(), config, config, frame.data());
267 }
268 EXPECT_EQ(frame[100], kGainFactor * kAudioLevel)
269 << "Frame should be amplified.";
270}
271
Per Åhgren652ada52021-03-03 10:52:44 +0000272TEST(AudioProcessingImplTest, EchoControllerObservesSetCaptureUsageChange) {
273 // Tests that the echo controller observes that the capture usage has been
274 // updated.
275 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
276 const MockEchoControlFactory* echo_control_factory_ptr =
277 echo_control_factory.get();
278
279 std::unique_ptr<AudioProcessing> apm(
280 AudioProcessingBuilderForTesting()
281 .SetEchoControlFactory(std::move(echo_control_factory))
282 .Create());
283
284 constexpr int16_t kAudioLevel = 10000;
285 constexpr int kSampleRateHz = 48000;
286 constexpr int kNumChannels = 2;
287 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
288 StreamConfig config(kSampleRateHz, kNumChannels, /*has_keyboard=*/false);
289 frame.fill(kAudioLevel);
290
291 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
292
293 // Ensure that SetCaptureOutputUsage is not called when no runtime settings
294 // are passed.
295 EXPECT_CALL(*echo_control_mock, SetCaptureOutputUsage(testing::_)).Times(0);
296 apm->ProcessStream(frame.data(), config, config, frame.data());
297
298 // Ensure that SetCaptureOutputUsage is called with the right information when
299 // a runtime setting is passed.
300 EXPECT_CALL(*echo_control_mock,
301 SetCaptureOutputUsage(/*capture_output_used=*/false))
302 .Times(1);
303 EXPECT_TRUE(apm->PostRuntimeSetting(
304 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
305 /*capture_output_used=*/false)));
306 apm->ProcessStream(frame.data(), config, config, frame.data());
307
308 EXPECT_CALL(*echo_control_mock,
309 SetCaptureOutputUsage(/*capture_output_used=*/true))
310 .Times(1);
311 EXPECT_TRUE(apm->PostRuntimeSetting(
312 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
313 /*capture_output_used=*/true)));
314 apm->ProcessStream(frame.data(), config, config, frame.data());
315
316 // The number of positions to place items in the queue is equal to the queue
317 // size minus 1.
318 constexpr int kNumSlotsInQueue = RuntimeSettingQueueSize();
319
320 // Ensure that SetCaptureOutputUsage is called with the right information when
321 // many runtime settings are passed.
322 for (int k = 0; k < kNumSlotsInQueue - 1; ++k) {
323 EXPECT_TRUE(apm->PostRuntimeSetting(
324 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
325 /*capture_output_used=*/false)));
326 }
327 EXPECT_CALL(*echo_control_mock,
328 SetCaptureOutputUsage(/*capture_output_used=*/false))
329 .Times(kNumSlotsInQueue - 1);
330 apm->ProcessStream(frame.data(), config, config, frame.data());
331
332 // Ensure that SetCaptureOutputUsage is properly called with the fallback
333 // value when the runtime settings queue becomes full.
334 for (int k = 0; k < kNumSlotsInQueue; ++k) {
335 EXPECT_TRUE(apm->PostRuntimeSetting(
336 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
337 /*capture_output_used=*/false)));
338 }
339 EXPECT_FALSE(apm->PostRuntimeSetting(
340 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
341 /*capture_output_used=*/false)));
342 EXPECT_FALSE(apm->PostRuntimeSetting(
343 AudioProcessing::RuntimeSetting::CreateCaptureOutputUsedSetting(
344 /*capture_output_used=*/false)));
345 EXPECT_CALL(*echo_control_mock,
346 SetCaptureOutputUsage(/*capture_output_used=*/false))
347 .Times(kNumSlotsInQueue);
348 EXPECT_CALL(*echo_control_mock,
349 SetCaptureOutputUsage(/*capture_output_used=*/true))
350 .Times(1);
351 apm->ProcessStream(frame.data(), config, config, frame.data());
352}
353
Alessio Bazzicae4498052018-12-17 09:44:06 +0100354TEST(AudioProcessingImplTest,
355 EchoControllerObservesPreAmplifierEchoPathGainChange) {
356 // Tests that the echo controller observes an echo path gain change when the
357 // pre-amplifier submodule changes the gain.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200358 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Alessio Bazzicae4498052018-12-17 09:44:06 +0100359 const auto* echo_control_factory_ptr = echo_control_factory.get();
360
361 std::unique_ptr<AudioProcessing> apm(
Per Åhgrencc73ed32020-04-26 23:56:17 +0200362 AudioProcessingBuilderForTesting()
Alessio Bazzicae4498052018-12-17 09:44:06 +0100363 .SetEchoControlFactory(std::move(echo_control_factory))
364 .Create());
Sam Zackrisson41478c72019-10-15 10:10:26 +0200365 // Disable AGC.
Alessio Bazzicae4498052018-12-17 09:44:06 +0100366 webrtc::AudioProcessing::Config apm_config;
Sam Zackrisson41478c72019-10-15 10:10:26 +0200367 apm_config.gain_controller1.enabled = false;
Alessio Bazzicae4498052018-12-17 09:44:06 +0100368 apm_config.gain_controller2.enabled = false;
369 apm_config.pre_amplifier.enabled = true;
370 apm_config.pre_amplifier.fixed_gain_factor = 1.f;
371 apm->ApplyConfig(apm_config);
372
Alessio Bazzicae4498052018-12-17 09:44:06 +0100373 constexpr int16_t kAudioLevel = 10000;
374 constexpr size_t kSampleRateHz = 48000;
375 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100376 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
377 StreamConfig config(kSampleRateHz, kNumChannels, /*has_keyboard=*/false);
378 frame.fill(kAudioLevel);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100379
380 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
381
Per Åhgren0aefbf02019-08-23 21:29:17 +0200382 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200383 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100384 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200385 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100386 apm->ProcessStream(frame.data(), config, config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100387
Per Åhgren0aefbf02019-08-23 21:29:17 +0200388 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200389 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100390 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
Fredrik Hernqvistbf47f342019-05-09 10:50:31 +0200391 .Times(1);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100392 apm->SetRuntimeSetting(
393 AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100394 apm->ProcessStream(frame.data(), config, config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100395}
396
397TEST(AudioProcessingImplTest,
Per Åhgrendb5d7282021-03-15 16:31:04 +0000398 EchoControllerObservesLevelAdjustmentPreGainEchoPathGainChange) {
399 // Tests that the echo controller observes an echo path gain change when the
400 // pre-amplifier submodule changes the gain.
401 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
402 const auto* echo_control_factory_ptr = echo_control_factory.get();
403
404 std::unique_ptr<AudioProcessing> apm(
405 AudioProcessingBuilderForTesting()
406 .SetEchoControlFactory(std::move(echo_control_factory))
407 .Create());
408 // Disable AGC.
409 webrtc::AudioProcessing::Config apm_config;
410 apm_config.gain_controller1.enabled = false;
411 apm_config.gain_controller2.enabled = false;
412 apm_config.capture_level_adjustment.enabled = true;
413 apm_config.capture_level_adjustment.pre_gain_factor = 1.f;
414 apm->ApplyConfig(apm_config);
415
416 constexpr int16_t kAudioLevel = 10000;
417 constexpr size_t kSampleRateHz = 48000;
418 constexpr size_t kNumChannels = 2;
419 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
420 StreamConfig config(kSampleRateHz, kNumChannels, /*has_keyboard=*/false);
421 frame.fill(kAudioLevel);
422
423 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
424
425 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
426 EXPECT_CALL(*echo_control_mock,
427 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
428 .Times(1);
429 apm->ProcessStream(frame.data(), config, config, frame.data());
430
431 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
432 EXPECT_CALL(*echo_control_mock,
433 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
434 .Times(1);
435 apm->SetRuntimeSetting(
436 AudioProcessing::RuntimeSetting::CreateCapturePreGain(2.f));
437 apm->ProcessStream(frame.data(), config, config, frame.data());
438}
439
440TEST(AudioProcessingImplTest,
Alessio Bazzicae4498052018-12-17 09:44:06 +0100441 EchoControllerObservesAnalogAgc1EchoPathGainChange) {
442 // Tests that the echo controller observes an echo path gain change when the
443 // AGC1 analog adaptive submodule changes the analog gain.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200444 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Alessio Bazzicae4498052018-12-17 09:44:06 +0100445 const auto* echo_control_factory_ptr = echo_control_factory.get();
446
447 std::unique_ptr<AudioProcessing> apm(
Per Åhgrencc73ed32020-04-26 23:56:17 +0200448 AudioProcessingBuilderForTesting()
Alessio Bazzicae4498052018-12-17 09:44:06 +0100449 .SetEchoControlFactory(std::move(echo_control_factory))
450 .Create());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100451 webrtc::AudioProcessing::Config apm_config;
Sam Zackrisson41478c72019-10-15 10:10:26 +0200452 // Enable AGC1.
453 apm_config.gain_controller1.enabled = true;
454 apm_config.gain_controller1.mode =
455 AudioProcessing::Config::GainController1::kAdaptiveAnalog;
Alessio Bazzicae4498052018-12-17 09:44:06 +0100456 apm_config.gain_controller2.enabled = false;
457 apm_config.pre_amplifier.enabled = false;
458 apm->ApplyConfig(apm_config);
459
Alessio Bazzicae4498052018-12-17 09:44:06 +0100460 constexpr int16_t kAudioLevel = 1000;
461 constexpr size_t kSampleRateHz = 48000;
462 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100463 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
464 StreamConfig stream_config(kSampleRateHz, kNumChannels,
465 /*has_keyboard=*/false);
466 frame.fill(kAudioLevel);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100467
468 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
469
Sam Zackrisson41478c72019-10-15 10:10:26 +0200470 const int initial_analog_gain = apm->recommended_stream_analog_level();
Per Åhgren0aefbf02019-08-23 21:29:17 +0200471 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100472 EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), testing::_, false))
473 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100474 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100475
476 // Force an analog gain change if it did not happen.
Sam Zackrisson41478c72019-10-15 10:10:26 +0200477 if (initial_analog_gain == apm->recommended_stream_analog_level()) {
478 apm->set_stream_analog_level(initial_analog_gain + 1);
Alessio Bazzicae4498052018-12-17 09:44:06 +0100479 }
480
Per Åhgren0aefbf02019-08-23 21:29:17 +0200481 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100482 EXPECT_CALL(*echo_control_mock, ProcessCapture(NotNull(), testing::_, true))
483 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100484 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Alessio Bazzicae4498052018-12-17 09:44:06 +0100485}
486
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200487TEST(AudioProcessingImplTest, EchoControllerObservesPlayoutVolumeChange) {
488 // Tests that the echo controller observes an echo path gain change when a
489 // playout volume change is reported.
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200490 auto echo_control_factory = std::make_unique<MockEchoControlFactory>();
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200491 const auto* echo_control_factory_ptr = echo_control_factory.get();
492
493 std::unique_ptr<AudioProcessing> apm(
Per Åhgrencc73ed32020-04-26 23:56:17 +0200494 AudioProcessingBuilderForTesting()
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200495 .SetEchoControlFactory(std::move(echo_control_factory))
496 .Create());
Sam Zackrisson41478c72019-10-15 10:10:26 +0200497 // Disable AGC.
498 webrtc::AudioProcessing::Config apm_config;
499 apm_config.gain_controller1.enabled = false;
500 apm_config.gain_controller2.enabled = false;
501 apm->ApplyConfig(apm_config);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200502
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200503 constexpr int16_t kAudioLevel = 10000;
504 constexpr size_t kSampleRateHz = 48000;
505 constexpr size_t kNumChannels = 2;
Per Åhgren2507f8c2020-03-19 12:33:29 +0100506 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
507 StreamConfig stream_config(kSampleRateHz, kNumChannels,
508 /*has_keyboard=*/false);
509 frame.fill(kAudioLevel);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200510
511 MockEchoControl* echo_control_mock = echo_control_factory_ptr->GetNext();
512
Per Åhgren0aefbf02019-08-23 21:29:17 +0200513 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200514 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100515 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200516 .Times(1);
Per Åhgrendc5522b2020-03-19 14:55:58 +0100517 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200518
Per Åhgren0aefbf02019-08-23 21:29:17 +0200519 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200520 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100521 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200522 .Times(1);
523 apm->SetRuntimeSetting(
524 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100525 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200526
Per Åhgren0aefbf02019-08-23 21:29:17 +0200527 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200528 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100529 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/false))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200530 .Times(1);
531 apm->SetRuntimeSetting(
532 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(50));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100533 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200534
Per Åhgren0aefbf02019-08-23 21:29:17 +0200535 EXPECT_CALL(*echo_control_mock, AnalyzeCapture(testing::_)).Times(1);
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200536 EXPECT_CALL(*echo_control_mock,
Per Åhgrenc20a19c2019-11-13 11:12:29 +0100537 ProcessCapture(NotNull(), testing::_, /*echo_path_change=*/true))
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200538 .Times(1);
539 apm->SetRuntimeSetting(
540 AudioProcessing::RuntimeSetting::CreatePlayoutVolumeChange(100));
Per Åhgrendc5522b2020-03-19 14:55:58 +0100541 apm->ProcessStream(frame.data(), stream_config, stream_config, frame.data());
Fredrik Hernqvistca362852019-05-10 15:50:02 +0200542}
543
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200544TEST(AudioProcessingImplTest, RenderPreProcessorBeforeEchoDetector) {
545 // Make sure that signal changes caused by a render pre-processing sub-module
546 // take place before any echo detector analysis.
547 rtc::scoped_refptr<TestEchoDetector> test_echo_detector(
548 new rtc::RefCountedObject<TestEchoDetector>());
549 std::unique_ptr<CustomProcessing> test_render_pre_processor(
550 new TestRenderPreProcessor());
551 // Create APM injecting the test echo detector and render pre-processor.
552 std::unique_ptr<AudioProcessing> apm(
Per Åhgrencc73ed32020-04-26 23:56:17 +0200553 AudioProcessingBuilderForTesting()
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200554 .SetEchoDetector(test_echo_detector)
555 .SetRenderPreProcessing(std::move(test_render_pre_processor))
556 .Create());
557 webrtc::AudioProcessing::Config apm_config;
558 apm_config.pre_amplifier.enabled = true;
559 apm_config.residual_echo_detector.enabled = true;
560 apm->ApplyConfig(apm_config);
561
562 constexpr int16_t kAudioLevel = 1000;
563 constexpr int kSampleRateHz = 16000;
564 constexpr size_t kNumChannels = 1;
Sam Zackrisson12e319a2020-01-03 14:54:20 +0100565 // Explicitly initialize APM to ensure no render frames are discarded.
566 const ProcessingConfig processing_config = {{
567 {kSampleRateHz, kNumChannels, /*has_keyboard=*/false},
568 {kSampleRateHz, kNumChannels, /*has_keyboard=*/false},
569 {kSampleRateHz, kNumChannels, /*has_keyboard=*/false},
570 {kSampleRateHz, kNumChannels, /*has_keyboard=*/false},
571 }};
572 apm->Initialize(processing_config);
573
Per Åhgren2507f8c2020-03-19 12:33:29 +0100574 std::array<int16_t, kNumChannels * kSampleRateHz / 100> frame;
575 StreamConfig stream_config(kSampleRateHz, kNumChannels,
576 /*has_keyboard=*/false);
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200577
578 constexpr float kAudioLevelFloat = static_cast<float>(kAudioLevel);
579 constexpr float kExpectedPreprocessedAudioLevel =
580 TestRenderPreProcessor::ProcessSample(kAudioLevelFloat);
581 ASSERT_NE(kAudioLevelFloat, kExpectedPreprocessedAudioLevel);
582
583 // Analyze a render stream frame.
Per Åhgren2507f8c2020-03-19 12:33:29 +0100584 frame.fill(kAudioLevel);
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200585 ASSERT_EQ(AudioProcessing::Error::kNoError,
Per Åhgren2507f8c2020-03-19 12:33:29 +0100586 apm->ProcessReverseStream(frame.data(), stream_config,
587 stream_config, frame.data()));
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200588 // Trigger a call to in EchoDetector::AnalyzeRenderAudio() via
589 // ProcessStream().
Per Åhgren2507f8c2020-03-19 12:33:29 +0100590 frame.fill(kAudioLevel);
591 ASSERT_EQ(AudioProcessing::Error::kNoError,
592 apm->ProcessStream(frame.data(), stream_config, stream_config,
Per Åhgrendc5522b2020-03-19 14:55:58 +0100593 frame.data()));
Alessio Bazzicad2b97402018-08-09 14:23:11 +0200594 // Regardless of how the call to in EchoDetector::AnalyzeRenderAudio() is
595 // triggered, the line below checks that the call has occurred. If not, the
596 // APM implementation may have changed and this test might need to be adapted.
597 ASSERT_TRUE(test_echo_detector->analyze_render_audio_called());
598 // Check that the data read in EchoDetector::AnalyzeRenderAudio() is that
599 // produced by the render pre-processor.
600 EXPECT_EQ(kExpectedPreprocessedAudioLevel,
601 test_echo_detector->last_render_audio_first_sample());
602}
603
Sam Zackrissonb37e59d2020-04-27 08:39:33 +0200604// Disabling build-optional submodules and trying to enable them via the APM
605// config should be bit-exact with running APM with said submodules disabled.
606// This mainly tests that SetCreateOptionalSubmodulesForTesting has an effect.
607TEST(ApmWithSubmodulesExcludedTest, BitexactWithDisabledModules) {
608 rtc::scoped_refptr<AudioProcessingImpl> apm =
609 new rtc::RefCountedObject<AudioProcessingImpl>(webrtc::Config());
610 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
611
612 ApmSubmoduleCreationOverrides overrides;
613 overrides.transient_suppression = true;
614 apm->OverrideSubmoduleCreationForTesting(overrides);
615
616 AudioProcessing::Config apm_config = apm->GetConfig();
617 apm_config.transient_suppression.enabled = true;
618 apm->ApplyConfig(apm_config);
619
620 rtc::scoped_refptr<AudioProcessing> apm_reference =
621 AudioProcessingBuilder().Create();
622 apm_config = apm_reference->GetConfig();
623 apm_config.transient_suppression.enabled = false;
624 apm_reference->ApplyConfig(apm_config);
625
626 constexpr int kSampleRateHz = 16000;
627 constexpr int kNumChannels = 1;
628 std::array<float, kSampleRateHz / 100> buffer;
629 std::array<float, kSampleRateHz / 100> buffer_reference;
630 float* channel_pointers[] = {buffer.data()};
631 float* channel_pointers_reference[] = {buffer_reference.data()};
632 StreamConfig stream_config(/*sample_rate_hz=*/kSampleRateHz,
633 /*num_channels=*/kNumChannels,
634 /*has_keyboard=*/false);
635 Random random_generator(2341U);
636 constexpr int kFramesToProcessPerConfiguration = 10;
637
638 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
639 RandomizeSampleVector(&random_generator, buffer);
640 std::copy(buffer.begin(), buffer.end(), buffer_reference.begin());
641 ASSERT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
642 channel_pointers),
643 kNoErr);
644 ASSERT_EQ(
645 apm_reference->ProcessStream(channel_pointers_reference, stream_config,
646 stream_config, channel_pointers_reference),
647 kNoErr);
648 for (int j = 0; j < kSampleRateHz / 100; ++j) {
649 EXPECT_EQ(buffer[j], buffer_reference[j]);
650 }
651 }
652}
653
654// Disable transient suppressor creation and run APM in ways that should trigger
655// calls to the transient suppressor API.
656TEST(ApmWithSubmodulesExcludedTest, ReinitializeTransientSuppressor) {
657 rtc::scoped_refptr<AudioProcessingImpl> apm =
658 new rtc::RefCountedObject<AudioProcessingImpl>(webrtc::Config());
659 ASSERT_EQ(apm->Initialize(), kNoErr);
660
661 ApmSubmoduleCreationOverrides overrides;
662 overrides.transient_suppression = true;
663 apm->OverrideSubmoduleCreationForTesting(overrides);
664
665 AudioProcessing::Config config = apm->GetConfig();
666 config.transient_suppression.enabled = true;
667 apm->ApplyConfig(config);
668 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
669 float buffer[960];
670 float* channel_pointers[] = {&buffer[0], &buffer[480]};
671 Random random_generator(2341U);
672 constexpr int kFramesToProcessPerConfiguration = 3;
673
674 StreamConfig initial_stream_config(/*sample_rate_hz=*/16000,
675 /*num_channels=*/1,
676 /*has_keyboard=*/false);
677 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
678 RandomizeSampleVector(&random_generator, buffer);
679 EXPECT_EQ(apm->ProcessStream(channel_pointers, initial_stream_config,
680 initial_stream_config, channel_pointers),
681 kNoErr);
682 }
683
684 StreamConfig stereo_stream_config(/*sample_rate_hz=*/16000,
685 /*num_channels=*/2,
686 /*has_keyboard=*/false);
687 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
688 RandomizeSampleVector(&random_generator, buffer);
689 EXPECT_EQ(apm->ProcessStream(channel_pointers, stereo_stream_config,
690 stereo_stream_config, channel_pointers),
691 kNoErr);
692 }
693
694 StreamConfig high_sample_rate_stream_config(/*sample_rate_hz=*/48000,
695 /*num_channels=*/1,
696 /*has_keyboard=*/false);
697 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
698 RandomizeSampleVector(&random_generator, buffer);
699 EXPECT_EQ(
700 apm->ProcessStream(channel_pointers, high_sample_rate_stream_config,
701 high_sample_rate_stream_config, channel_pointers),
702 kNoErr);
703 }
704
705 StreamConfig keyboard_stream_config(/*sample_rate_hz=*/16000,
706 /*num_channels=*/1,
707 /*has_keyboard=*/true);
708 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
709 RandomizeSampleVector(&random_generator, buffer);
710 EXPECT_EQ(apm->ProcessStream(channel_pointers, keyboard_stream_config,
711 keyboard_stream_config, channel_pointers),
712 kNoErr);
713 }
714}
715
716// Disable transient suppressor creation and run APM in ways that should trigger
717// calls to the transient suppressor API.
718TEST(ApmWithSubmodulesExcludedTest, ToggleTransientSuppressor) {
719 rtc::scoped_refptr<AudioProcessingImpl> apm =
720 new rtc::RefCountedObject<AudioProcessingImpl>(webrtc::Config());
721 ASSERT_EQ(apm->Initialize(), AudioProcessing::kNoError);
722
723 ApmSubmoduleCreationOverrides overrides;
724 overrides.transient_suppression = true;
725 apm->OverrideSubmoduleCreationForTesting(overrides);
726
727 // 960 samples per frame: 10 ms of <= 48 kHz audio with <= 2 channels.
728 float buffer[960];
729 float* channel_pointers[] = {&buffer[0], &buffer[480]};
730 Random random_generator(2341U);
731 constexpr int kFramesToProcessPerConfiguration = 3;
732 StreamConfig stream_config(/*sample_rate_hz=*/16000,
733 /*num_channels=*/1,
734 /*has_keyboard=*/false);
735
736 AudioProcessing::Config config = apm->GetConfig();
737 config.transient_suppression.enabled = true;
738 apm->ApplyConfig(config);
739 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
740 RandomizeSampleVector(&random_generator, buffer);
741 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
742 channel_pointers),
743 kNoErr);
744 }
745
746 config = apm->GetConfig();
747 config.transient_suppression.enabled = false;
748 apm->ApplyConfig(config);
749 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
750 RandomizeSampleVector(&random_generator, buffer);
751 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
752 channel_pointers),
753 kNoErr);
754 }
755
756 config = apm->GetConfig();
757 config.transient_suppression.enabled = true;
758 apm->ApplyConfig(config);
759 for (int i = 0; i < kFramesToProcessPerConfiguration; ++i) {
760 RandomizeSampleVector(&random_generator, buffer);
761 EXPECT_EQ(apm->ProcessStream(channel_pointers, stream_config, stream_config,
762 channel_pointers),
763 kNoErr);
764 }
765}
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000766} // namespace webrtc