blob: c7a71c34fc266e2a67f77d0411358664d56643e2 [file] [log] [blame]
peahd0263542017-01-03 04:20:34 -08001/*
2 * Copyright (c) 2016 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/aec3/echo_canceller3.h"
peahd0263542017-01-03 04:20:34 -080012
13#include <deque>
14#include <memory>
peahd0263542017-01-03 04:20:34 -080015#include <string>
16#include <utility>
17#include <vector>
18
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_processing/aec3/aec3_common.h"
20#include "modules/audio_processing/aec3/block_processor.h"
21#include "modules/audio_processing/aec3/frame_blocker.h"
22#include "modules/audio_processing/aec3/mock/mock_block_processor.h"
23#include "modules/audio_processing/audio_buffer.h"
Per Åhgren0aefbf02019-08-23 21:29:17 +020024#include "modules/audio_processing/high_pass_filter.h"
25#include "modules/audio_processing/utility/cascaded_biquad_filter.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020026#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020027#include "test/gmock.h"
28#include "test/gtest.h"
peahd0263542017-01-03 04:20:34 -080029
30namespace webrtc {
31namespace {
32
Mirko Bonadei6a489f22019-04-09 15:11:12 +020033using ::testing::_;
34using ::testing::StrictMock;
peahd0263542017-01-03 04:20:34 -080035
36// Populates the frame with linearly increasing sample values for each band,
37// with a band-specific offset, in order to allow simple bitexactness
38// verification for each band.
39void PopulateInputFrame(size_t frame_length,
40 size_t num_bands,
41 size_t frame_index,
42 float* const* frame,
43 int offset) {
44 for (size_t k = 0; k < num_bands; ++k) {
45 for (size_t i = 0; i < frame_length; ++i) {
46 float value = static_cast<int>(frame_index * frame_length + i) + offset;
47 frame[k][i] = (value > 0 ? 5000 * k + value : 0);
48 }
49 }
50}
51
peah522d71b2017-02-23 05:16:26 -080052// Populates the frame with linearly increasing sample values.
53void PopulateInputFrame(size_t frame_length,
54 size_t frame_index,
55 float* frame,
56 int offset) {
57 for (size_t i = 0; i < frame_length; ++i) {
58 float value = static_cast<int>(frame_index * frame_length + i) + offset;
59 frame[i] = std::max(value, 0.f);
60 }
61}
62
peahd0263542017-01-03 04:20:34 -080063// Verifies the that samples in the output frame are identical to the samples
64// that were produced for the input frame, with an offset in order to compensate
65// for buffering delays.
66bool VerifyOutputFrameBitexactness(size_t frame_length,
67 size_t num_bands,
68 size_t frame_index,
69 const float* const* frame,
70 int offset) {
71 float reference_frame_data[kMaxNumBands][2 * kSubFrameLength];
72 float* reference_frame[kMaxNumBands];
73 for (size_t k = 0; k < num_bands; ++k) {
74 reference_frame[k] = &reference_frame_data[k][0];
75 }
76
77 PopulateInputFrame(frame_length, num_bands, frame_index, reference_frame,
78 offset);
79 for (size_t k = 0; k < num_bands; ++k) {
80 for (size_t i = 0; i < frame_length; ++i) {
81 if (reference_frame[k][i] != frame[k][i]) {
82 return false;
83 }
84 }
85 }
86
87 return true;
88}
89
Per Åhgren0aefbf02019-08-23 21:29:17 +020090bool VerifyOutputFrameBitexactness(rtc::ArrayView<const float> reference,
91 rtc::ArrayView<const float> frame,
92 int offset) {
93 for (size_t k = 0; k < frame.size(); ++k) {
94 int reference_index = static_cast<int>(k) + offset;
95 if (reference_index >= 0) {
96 if (reference[reference_index] != frame[k]) {
97 return false;
98 }
99 }
100 }
101 return true;
102}
103
peahd0263542017-01-03 04:20:34 -0800104// Class for testing that the capture data is properly received by the block
105// processor and that the processor data is properly passed to the
106// EchoCanceller3 output.
107class CaptureTransportVerificationProcessor : public BlockProcessor {
108 public:
109 explicit CaptureTransportVerificationProcessor(size_t num_bands) {}
110 ~CaptureTransportVerificationProcessor() override = default;
111
Per Åhgrence202a02019-09-02 17:01:19 +0200112 void ProcessCapture(
113 bool level_change,
114 bool saturated_microphone_signal,
115 std::vector<std::vector<std::vector<float>>>* capture_block) override {}
peahd0263542017-01-03 04:20:34 -0800116
Per Åhgrence202a02019-09-02 17:01:19 +0200117 void BufferRender(
118 const std::vector<std::vector<std::vector<float>>>& block) override {}
peahd0263542017-01-03 04:20:34 -0800119
peah69221db2017-01-27 03:28:19 -0800120 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800121
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100122 void GetMetrics(EchoControl::Metrics* metrics) const override {}
123
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100124 void SetAudioBufferDelay(size_t delay_ms) override {}
Per Åhgrend0fa8202018-04-18 09:35:13 +0200125
peahd0263542017-01-03 04:20:34 -0800126 private:
127 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
128};
129
130// Class for testing that the render data is properly received by the block
131// processor.
132class RenderTransportVerificationProcessor : public BlockProcessor {
133 public:
134 explicit RenderTransportVerificationProcessor(size_t num_bands) {}
135 ~RenderTransportVerificationProcessor() override = default;
136
Per Åhgrence202a02019-09-02 17:01:19 +0200137 void ProcessCapture(
138 bool level_change,
139 bool saturated_microphone_signal,
140 std::vector<std::vector<std::vector<float>>>* capture_block) override {
141 std::vector<std::vector<std::vector<float>>> render_block =
peahd0263542017-01-03 04:20:34 -0800142 received_render_blocks_.front();
143 received_render_blocks_.pop_front();
144 capture_block->swap(render_block);
145 }
146
Per Åhgrence202a02019-09-02 17:01:19 +0200147 void BufferRender(
148 const std::vector<std::vector<std::vector<float>>>& block) override {
peahcf02cf12017-04-05 14:18:07 -0700149 received_render_blocks_.push_back(block);
peahd0263542017-01-03 04:20:34 -0800150 }
151
peah69221db2017-01-27 03:28:19 -0800152 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800153
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100154 void GetMetrics(EchoControl::Metrics* metrics) const override {}
155
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100156 void SetAudioBufferDelay(size_t delay_ms) override {}
Per Åhgrend0fa8202018-04-18 09:35:13 +0200157
peahd0263542017-01-03 04:20:34 -0800158 private:
Per Åhgrence202a02019-09-02 17:01:19 +0200159 std::deque<std::vector<std::vector<std::vector<float>>>>
160 received_render_blocks_;
peahd0263542017-01-03 04:20:34 -0800161 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor);
162};
163
164class EchoCanceller3Tester {
165 public:
166 explicit EchoCanceller3Tester(int sample_rate_hz)
167 : sample_rate_hz_(sample_rate_hz),
168 num_bands_(NumBandsForRate(sample_rate_hz_)),
Per Åhgrence202a02019-09-02 17:01:19 +0200169 frame_length_(160),
peahd0263542017-01-03 04:20:34 -0800170 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)),
Per Åhgrend47941e2019-08-22 11:51:13 +0200171 capture_buffer_(fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800172 1,
Per Åhgrend47941e2019-08-22 11:51:13 +0200173 fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800174 1,
Per Åhgrend47941e2019-08-22 11:51:13 +0200175 fullband_frame_length_ * 100,
176 1),
177 render_buffer_(fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800178 1,
Per Åhgrend47941e2019-08-22 11:51:13 +0200179 fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800180 1,
Per Åhgrend47941e2019-08-22 11:51:13 +0200181 fullband_frame_length_ * 100,
182 1) {}
peahd0263542017-01-03 04:20:34 -0800183
184 // Verifies that the capture data is properly received by the block processor
185 // and that the processor data is properly passed to the EchoCanceller3
186 // output.
187 void RunCaptureTransportVerificationTest() {
188 EchoCanceller3 aec3(
Per Åhgrence202a02019-09-02 17:01:19 +0200189 EchoCanceller3Config(), sample_rate_hz_, 1, 1,
peahd0263542017-01-03 04:20:34 -0800190 std::unique_ptr<BlockProcessor>(
191 new CaptureTransportVerificationProcessor(num_bands_)));
192
193 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
194 ++frame_index) {
195 aec3.AnalyzeCapture(&capture_buffer_);
196 OptionalBandSplit();
197 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200198 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800199 PopulateInputFrame(frame_length_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200200 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800201
peahcf02cf12017-04-05 14:18:07 -0700202 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800203 aec3.ProcessCapture(&capture_buffer_, false);
204 EXPECT_TRUE(VerifyOutputFrameBitexactness(
205 frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200206 &capture_buffer_.split_bands(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800207 }
208 }
209
210 // Test method for testing that the render data is properly received by the
211 // block processor.
212 void RunRenderTransportVerificationTest() {
213 EchoCanceller3 aec3(
Per Åhgrence202a02019-09-02 17:01:19 +0200214 EchoCanceller3Config(), sample_rate_hz_, 1, 1,
peahd0263542017-01-03 04:20:34 -0800215 std::unique_ptr<BlockProcessor>(
216 new RenderTransportVerificationProcessor(num_bands_)));
217
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200218 std::vector<std::vector<float>> render_input(1);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200219 std::vector<float> capture_output;
peahd0263542017-01-03 04:20:34 -0800220 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
221 ++frame_index) {
222 aec3.AnalyzeCapture(&capture_buffer_);
223 OptionalBandSplit();
224 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200225 &capture_buffer_.split_bands(0)[0], 100);
peahcf02cf12017-04-05 14:18:07 -0700226 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200227 &render_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800228
Per Åhgren0aefbf02019-08-23 21:29:17 +0200229 for (size_t k = 0; k < frame_length_; ++k) {
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200230 render_input[0].push_back(render_buffer_.split_bands(0)[0][k]);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200231 }
peahcf02cf12017-04-05 14:18:07 -0700232 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800233 aec3.ProcessCapture(&capture_buffer_, false);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200234 for (size_t k = 0; k < frame_length_; ++k) {
235 capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
236 }
peahd0263542017-01-03 04:20:34 -0800237 }
Per Åhgren0aefbf02019-08-23 21:29:17 +0200238 HighPassFilter hp_filter(1);
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200239 hp_filter.Process(&render_input);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200240
241 EXPECT_TRUE(
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200242 VerifyOutputFrameBitexactness(render_input[0], capture_output, -64));
peahd0263542017-01-03 04:20:34 -0800243 }
244
245 // Verifies that information about echo path changes are properly propagated
246 // to the block processor.
247 // The cases tested are:
248 // -That no set echo path change flags are received when there is no echo path
249 // change.
250 // -That set echo path change flags are received and continues to be received
251 // as long as echo path changes are flagged.
252 // -That set echo path change flags are no longer received when echo path
253 // change events stop being flagged.
254 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky };
255
256 void RunEchoPathChangeVerificationTest(
257 EchoPathChangeTestVariant echo_path_change_test_variant) {
Per Åhgrence202a02019-09-02 17:01:19 +0200258 constexpr size_t kNumFullBlocksPerFrame = 160 / kBlockSize;
259 constexpr size_t kExpectedNumBlocksToProcess =
260 (kNumFramesToProcess * 160) / kBlockSize;
peahd0263542017-01-03 04:20:34 -0800261 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
262 block_processor_mock(
263 new StrictMock<webrtc::test::MockBlockProcessor>());
264 EXPECT_CALL(*block_processor_mock, BufferRender(_))
Per Åhgrence202a02019-09-02 17:01:19 +0200265 .Times(kExpectedNumBlocksToProcess);
peah69221db2017-01-27 03:28:19 -0800266 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800267
268 switch (echo_path_change_test_variant) {
269 case EchoPathChangeTestVariant::kNone:
270 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200271 .Times(kExpectedNumBlocksToProcess);
peahd0263542017-01-03 04:20:34 -0800272 break;
273 case EchoPathChangeTestVariant::kOneSticky:
274 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200275 .Times(kExpectedNumBlocksToProcess);
peahd0263542017-01-03 04:20:34 -0800276 break;
277 case EchoPathChangeTestVariant::kOneNonSticky:
278 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200279 .Times(kNumFullBlocksPerFrame);
peahd0263542017-01-03 04:20:34 -0800280 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200281 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
peahd0263542017-01-03 04:20:34 -0800282 break;
283 }
284
Per Åhgrence202a02019-09-02 17:01:19 +0200285 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1,
peahd0263542017-01-03 04:20:34 -0800286 std::move(block_processor_mock));
287
288 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
289 ++frame_index) {
290 bool echo_path_change = false;
291 switch (echo_path_change_test_variant) {
292 case EchoPathChangeTestVariant::kNone:
293 break;
294 case EchoPathChangeTestVariant::kOneSticky:
295 echo_path_change = true;
296 break;
297 case EchoPathChangeTestVariant::kOneNonSticky:
298 if (frame_index == 0) {
299 echo_path_change = true;
300 }
301 break;
302 }
303
304 aec3.AnalyzeCapture(&capture_buffer_);
305 OptionalBandSplit();
306
307 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200308 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800309 PopulateInputFrame(frame_length_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200310 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800311
peahcf02cf12017-04-05 14:18:07 -0700312 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800313 aec3.ProcessCapture(&capture_buffer_, echo_path_change);
314 }
315 }
316
317 // Test for verifying that echo leakage information is being properly passed
318 // to the processor.
319 // The cases tested are:
320 // -That no method calls are received when they should not.
321 // -That false values are received each time they are flagged.
322 // -That true values are received each time they are flagged.
323 // -That a false value is received when flagged after a true value has been
324 // flagged.
325 enum class EchoLeakageTestVariant {
326 kNone,
327 kFalseSticky,
328 kTrueSticky,
329 kTrueNonSticky
330 };
331
332 void RunEchoLeakageVerificationTest(
333 EchoLeakageTestVariant leakage_report_variant) {
Per Åhgrence202a02019-09-02 17:01:19 +0200334 constexpr size_t kExpectedNumBlocksToProcess =
335 (kNumFramesToProcess * 160) / kBlockSize;
peahd0263542017-01-03 04:20:34 -0800336 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
337 block_processor_mock(
338 new StrictMock<webrtc::test::MockBlockProcessor>());
339 EXPECT_CALL(*block_processor_mock, BufferRender(_))
Per Åhgrence202a02019-09-02 17:01:19 +0200340 .Times(kExpectedNumBlocksToProcess);
peahd0263542017-01-03 04:20:34 -0800341 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200342 .Times(kExpectedNumBlocksToProcess);
peahd0263542017-01-03 04:20:34 -0800343
344 switch (leakage_report_variant) {
345 case EchoLeakageTestVariant::kNone:
peah69221db2017-01-27 03:28:19 -0800346 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800347 break;
348 case EchoLeakageTestVariant::kFalseSticky:
peah69221db2017-01-27 03:28:19 -0800349 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
350 .Times(1);
peahd0263542017-01-03 04:20:34 -0800351 break;
352 case EchoLeakageTestVariant::kTrueSticky:
peah69221db2017-01-27 03:28:19 -0800353 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
354 .Times(1);
peahd0263542017-01-03 04:20:34 -0800355 break;
356 case EchoLeakageTestVariant::kTrueNonSticky: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200357 ::testing::InSequence s;
peah69221db2017-01-27 03:28:19 -0800358 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
359 .Times(1);
360 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
peahd0263542017-01-03 04:20:34 -0800361 .Times(kNumFramesToProcess - 1);
362 } break;
363 }
364
Per Åhgrence202a02019-09-02 17:01:19 +0200365 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1,
peahd0263542017-01-03 04:20:34 -0800366 std::move(block_processor_mock));
367
368 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
369 ++frame_index) {
370 switch (leakage_report_variant) {
371 case EchoLeakageTestVariant::kNone:
372 break;
373 case EchoLeakageTestVariant::kFalseSticky:
374 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800375 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800376 }
377 break;
378 case EchoLeakageTestVariant::kTrueSticky:
379 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800380 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800381 }
382 break;
383 case EchoLeakageTestVariant::kTrueNonSticky:
384 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800385 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800386 } else {
peah69221db2017-01-27 03:28:19 -0800387 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800388 }
389 break;
390 }
391
392 aec3.AnalyzeCapture(&capture_buffer_);
393 OptionalBandSplit();
394
395 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200396 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800397 PopulateInputFrame(frame_length_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200398 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800399
peahcf02cf12017-04-05 14:18:07 -0700400 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800401 aec3.ProcessCapture(&capture_buffer_, false);
402 }
403 }
404
405 // This verifies that saturation information is properly passed to the
406 // BlockProcessor.
407 // The cases tested are:
408 // -That no saturation event is passed to the processor if there is no
409 // saturation.
410 // -That one frame with one negative saturated sample value is reported to be
411 // saturated and that following non-saturated frames are properly reported as
412 // not being saturated.
413 // -That one frame with one positive saturated sample value is reported to be
414 // saturated and that following non-saturated frames are properly reported as
415 // not being saturated.
416 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive };
417
418 void RunCaptureSaturationVerificationTest(
419 SaturationTestVariant saturation_variant) {
Per Åhgrence202a02019-09-02 17:01:19 +0200420 const size_t kNumFullBlocksPerFrame = 160 / kBlockSize;
421 const size_t kExpectedNumBlocksToProcess =
422 (kNumFramesToProcess * 160) / kBlockSize;
peahd0263542017-01-03 04:20:34 -0800423 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
424 block_processor_mock(
425 new StrictMock<webrtc::test::MockBlockProcessor>());
426 EXPECT_CALL(*block_processor_mock, BufferRender(_))
Per Åhgrence202a02019-09-02 17:01:19 +0200427 .Times(kExpectedNumBlocksToProcess);
peah69221db2017-01-27 03:28:19 -0800428 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800429
430 switch (saturation_variant) {
431 case SaturationTestVariant::kNone:
432 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200433 .Times(kExpectedNumBlocksToProcess);
peahd0263542017-01-03 04:20:34 -0800434 break;
435 case SaturationTestVariant::kOneNegative: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200436 ::testing::InSequence s;
peahd0263542017-01-03 04:20:34 -0800437 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200438 .Times(kNumFullBlocksPerFrame);
peahd0263542017-01-03 04:20:34 -0800439 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200440 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
peahd0263542017-01-03 04:20:34 -0800441 } break;
442 case SaturationTestVariant::kOnePositive: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200443 ::testing::InSequence s;
peahd0263542017-01-03 04:20:34 -0800444 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200445 .Times(kNumFullBlocksPerFrame);
peahd0263542017-01-03 04:20:34 -0800446 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
Per Åhgrence202a02019-09-02 17:01:19 +0200447 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
peahd0263542017-01-03 04:20:34 -0800448 } break;
449 }
450
Per Åhgrence202a02019-09-02 17:01:19 +0200451 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1,
peahd0263542017-01-03 04:20:34 -0800452 std::move(block_processor_mock));
peahd0263542017-01-03 04:20:34 -0800453 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
454 ++frame_index) {
455 for (int k = 0; k < fullband_frame_length_; ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200456 capture_buffer_.channels()[0][k] = 0.f;
peahd0263542017-01-03 04:20:34 -0800457 }
458 switch (saturation_variant) {
459 case SaturationTestVariant::kNone:
460 break;
461 case SaturationTestVariant::kOneNegative:
462 if (frame_index == 0) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200463 capture_buffer_.channels()[0][10] = -32768.f;
peahd0263542017-01-03 04:20:34 -0800464 }
465 break;
466 case SaturationTestVariant::kOnePositive:
467 if (frame_index == 0) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200468 capture_buffer_.channels()[0][10] = 32767.f;
peahd0263542017-01-03 04:20:34 -0800469 }
470 break;
471 }
472
473 aec3.AnalyzeCapture(&capture_buffer_);
474 OptionalBandSplit();
475
476 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200477 &capture_buffer_.split_bands(0)[0], 0);
peahcf02cf12017-04-05 14:18:07 -0700478 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200479 &render_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800480
peahcf02cf12017-04-05 14:18:07 -0700481 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800482 aec3.ProcessCapture(&capture_buffer_, false);
483 }
484 }
485
486 // This test verifies that the swapqueue is able to handle jitter in the
487 // capture and render API calls.
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000488 void RunRenderSwapQueueVerificationTest() {
Per Åhgren8ba58612017-12-01 23:01:44 +0100489 const EchoCanceller3Config config;
peahd0263542017-01-03 04:20:34 -0800490 EchoCanceller3 aec3(
Per Åhgrence202a02019-09-02 17:01:19 +0200491 config, sample_rate_hz_, 1, 1,
peahd0263542017-01-03 04:20:34 -0800492 std::unique_ptr<BlockProcessor>(
493 new RenderTransportVerificationProcessor(num_bands_)));
494
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200495 std::vector<std::vector<float>> render_input(1);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200496 std::vector<float> capture_output;
497
Per Åhgren8ba58612017-12-01 23:01:44 +0100498 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
peahd0263542017-01-03 04:20:34 -0800499 ++frame_index) {
500 if (sample_rate_hz_ > 16000) {
501 render_buffer_.SplitIntoFrequencyBands();
502 }
peahcf02cf12017-04-05 14:18:07 -0700503 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200504 &render_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800505
peahcf02cf12017-04-05 14:18:07 -0700506 if (sample_rate_hz_ > 16000) {
507 render_buffer_.SplitIntoFrequencyBands();
508 }
509
Per Åhgren0aefbf02019-08-23 21:29:17 +0200510 for (size_t k = 0; k < frame_length_; ++k) {
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200511 render_input[0].push_back(render_buffer_.split_bands(0)[0][k]);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200512 }
peahcf02cf12017-04-05 14:18:07 -0700513 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800514 }
515
Per Åhgren8ba58612017-12-01 23:01:44 +0100516 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
peahd0263542017-01-03 04:20:34 -0800517 ++frame_index) {
518 aec3.AnalyzeCapture(&capture_buffer_);
519 if (sample_rate_hz_ > 16000) {
520 capture_buffer_.SplitIntoFrequencyBands();
521 }
522
523 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200524 &capture_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800525
526 aec3.ProcessCapture(&capture_buffer_, false);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200527 for (size_t k = 0; k < frame_length_; ++k) {
528 capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
529 }
peahd0263542017-01-03 04:20:34 -0800530 }
Per Åhgren0aefbf02019-08-23 21:29:17 +0200531 HighPassFilter hp_filter(1);
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200532 hp_filter.Process(&render_input);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200533
534 EXPECT_TRUE(
Sam Zackrissonfeee1e42019-09-20 07:50:35 +0200535 VerifyOutputFrameBitexactness(render_input[0], capture_output, -64));
peahd0263542017-01-03 04:20:34 -0800536 }
537
538 // This test verifies that a buffer overrun in the render swapqueue is
539 // properly reported.
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000540 void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
Per Åhgrence202a02019-09-02 17:01:19 +0200541 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1);
peahd0263542017-01-03 04:20:34 -0800542
peahcf02cf12017-04-05 14:18:07 -0700543 constexpr size_t kRenderTransferQueueSize = 30;
peahd0263542017-01-03 04:20:34 -0800544 for (size_t k = 0; k < 2; ++k) {
peahcf02cf12017-04-05 14:18:07 -0700545 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
peahd0263542017-01-03 04:20:34 -0800546 ++frame_index) {
547 if (sample_rate_hz_ > 16000) {
548 render_buffer_.SplitIntoFrequencyBands();
549 }
peah522d71b2017-02-23 05:16:26 -0800550 PopulateInputFrame(frame_length_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200551 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800552
Per Åhgren0aefbf02019-08-23 21:29:17 +0200553 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800554 }
555 }
556 }
557
558#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
559 // Verifies the that the check for the number of bands in the AnalyzeRender
560 // input is correct by adjusting the sample rates of EchoCanceller3 and the
561 // input AudioBuffer to have a different number of bands.
562 void RunAnalyzeRenderNumBandsCheckVerification() {
563 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
564 // way that the number of bands for the rates are different.
565 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Per Åhgrence202a02019-09-02 17:01:19 +0200566 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, 1, 1);
peah522d71b2017-02-23 05:16:26 -0800567 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800568
569 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
570 }
571
572 // Verifies the that the check for the number of bands in the ProcessCapture
573 // input is correct by adjusting the sample rates of EchoCanceller3 and the
574 // input AudioBuffer to have a different number of bands.
575 void RunProcessCaptureNumBandsCheckVerification() {
576 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
577 // way that the number of bands for the rates are different.
578 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Per Åhgrence202a02019-09-02 17:01:19 +0200579 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, 1, 1);
peahd0263542017-01-03 04:20:34 -0800580 PopulateInputFrame(frame_length_, num_bands_, 0,
581 &capture_buffer_.split_bands_f(0)[0], 100);
582 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
583 }
584
peahd0263542017-01-03 04:20:34 -0800585#endif
586
587 private:
588 void OptionalBandSplit() {
589 if (sample_rate_hz_ > 16000) {
590 capture_buffer_.SplitIntoFrequencyBands();
591 render_buffer_.SplitIntoFrequencyBands();
592 }
593 }
594
595 static constexpr size_t kNumFramesToProcess = 20;
596 const int sample_rate_hz_;
597 const size_t num_bands_;
598 const size_t frame_length_;
599 const int fullband_frame_length_;
600 AudioBuffer capture_buffer_;
601 AudioBuffer render_buffer_;
602
603 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester);
604};
605
606std::string ProduceDebugText(int sample_rate_hz) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200607 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800608 ss << "Sample rate: " << sample_rate_hz;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200609 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800610}
611
612std::string ProduceDebugText(int sample_rate_hz, int variant) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200613 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800614 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200615 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800616}
617
618} // namespace
619
620TEST(EchoCanceller3Buffering, CaptureBitexactness) {
Per Åhgrence202a02019-09-02 17:01:19 +0200621 for (auto rate : {16000, 32000, 48000}) {
peahd0263542017-01-03 04:20:34 -0800622 SCOPED_TRACE(ProduceDebugText(rate));
623 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest();
624 }
625}
626
627TEST(EchoCanceller3Buffering, RenderBitexactness) {
Per Åhgrence202a02019-09-02 17:01:19 +0200628 for (auto rate : {16000, 32000, 48000}) {
peahd0263542017-01-03 04:20:34 -0800629 SCOPED_TRACE(ProduceDebugText(rate));
630 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest();
631 }
632}
633
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000634TEST(EchoCanceller3Buffering, RenderSwapQueue) {
Per Åhgrence202a02019-09-02 17:01:19 +0200635 EchoCanceller3Tester(16000).RunRenderSwapQueueVerificationTest();
peahd0263542017-01-03 04:20:34 -0800636}
637
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000638TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) {
Per Åhgrence202a02019-09-02 17:01:19 +0200639 for (auto rate : {16000, 32000, 48000}) {
peahd0263542017-01-03 04:20:34 -0800640 SCOPED_TRACE(ProduceDebugText(rate));
641 EchoCanceller3Tester(rate)
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000642 .RunRenderPipelineSwapQueueOverrunReturnValueTest();
peahd0263542017-01-03 04:20:34 -0800643 }
644}
645
646TEST(EchoCanceller3Messaging, CaptureSaturation) {
647 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone,
648 EchoCanceller3Tester::SaturationTestVariant::kOneNegative,
649 EchoCanceller3Tester::SaturationTestVariant::kOnePositive};
Per Åhgrence202a02019-09-02 17:01:19 +0200650 for (auto rate : {16000, 32000, 48000}) {
peahd0263542017-01-03 04:20:34 -0800651 for (auto variant : variants) {
652 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
653 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant);
654 }
655 }
656}
657
658TEST(EchoCanceller3Messaging, EchoPathChange) {
659 auto variants = {
660 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone,
661 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky,
662 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky};
Per Åhgrence202a02019-09-02 17:01:19 +0200663 for (auto rate : {16000, 32000, 48000}) {
peahd0263542017-01-03 04:20:34 -0800664 for (auto variant : variants) {
665 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
666 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant);
667 }
668 }
669}
670
671TEST(EchoCanceller3Messaging, EchoLeakage) {
672 auto variants = {
673 EchoCanceller3Tester::EchoLeakageTestVariant::kNone,
674 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky,
675 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky,
676 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky};
Per Åhgrence202a02019-09-02 17:01:19 +0200677 for (auto rate : {16000, 32000, 48000}) {
peahd0263542017-01-03 04:20:34 -0800678 for (auto variant : variants) {
679 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
680 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant);
681 }
682 }
683}
684
685#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
peahd0263542017-01-03 04:20:34 -0800686
687TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) {
Per Åhgrence202a02019-09-02 17:01:19 +0200688 for (auto rate : {16000, 32000, 48000}) {
peahd0263542017-01-03 04:20:34 -0800689 SCOPED_TRACE(ProduceDebugText(rate));
690 EchoCanceller3Tester(rate).RunProcessCaptureNumBandsCheckVerification();
691 }
692}
693
peahd0263542017-01-03 04:20:34 -0800694// Verifiers that the verification for null input to the capture processing api
695// call works.
696TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
Per Åhgrence202a02019-09-02 17:01:19 +0200697 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 16000, 1, 1)
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200698 .ProcessCapture(nullptr, false),
699 "");
peahd0263542017-01-03 04:20:34 -0800700}
701
peah21920892017-02-08 05:08:56 -0800702// Verifies the check for correct sample rate.
peahcf02cf12017-04-05 14:18:07 -0700703// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
704// tests on test bots has been fixed.
705TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
peah21920892017-02-08 05:08:56 -0800706 ApmDataDumper data_dumper(0);
Per Åhgrence202a02019-09-02 17:01:19 +0200707 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8001, 1, 1), "");
peah21920892017-02-08 05:08:56 -0800708}
709
peahd0263542017-01-03 04:20:34 -0800710#endif
711
712} // namespace webrtc