blob: a29b77934862cae53e5ece7d7605b20ece39817b [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
peah69221db2017-01-27 03:28:19 -0800112 void ProcessCapture(bool level_change,
peahd0263542017-01-03 04:20:34 -0800113 bool saturated_microphone_signal,
114 std::vector<std::vector<float>>* capture_block) override {
115 }
116
peahcf02cf12017-04-05 14:18:07 -0700117 void BufferRender(const std::vector<std::vector<float>>& block) override {}
peahd0263542017-01-03 04:20:34 -0800118
peah69221db2017-01-27 03:28:19 -0800119 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800120
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100121 void GetMetrics(EchoControl::Metrics* metrics) const override {}
122
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100123 void SetAudioBufferDelay(size_t delay_ms) override {}
Per Åhgrend0fa8202018-04-18 09:35:13 +0200124
peahd0263542017-01-03 04:20:34 -0800125 private:
126 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
127};
128
129// Class for testing that the render data is properly received by the block
130// processor.
131class RenderTransportVerificationProcessor : public BlockProcessor {
132 public:
133 explicit RenderTransportVerificationProcessor(size_t num_bands) {}
134 ~RenderTransportVerificationProcessor() override = default;
135
peah69221db2017-01-27 03:28:19 -0800136 void ProcessCapture(bool level_change,
peahd0263542017-01-03 04:20:34 -0800137 bool saturated_microphone_signal,
138 std::vector<std::vector<float>>* capture_block) override {
139 std::vector<std::vector<float>> render_block =
140 received_render_blocks_.front();
141 received_render_blocks_.pop_front();
142 capture_block->swap(render_block);
143 }
144
peahcf02cf12017-04-05 14:18:07 -0700145 void BufferRender(const std::vector<std::vector<float>>& block) override {
146 received_render_blocks_.push_back(block);
peahd0263542017-01-03 04:20:34 -0800147 }
148
peah69221db2017-01-27 03:28:19 -0800149 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800150
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100151 void GetMetrics(EchoControl::Metrics* metrics) const override {}
152
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100153 void SetAudioBufferDelay(size_t delay_ms) override {}
Per Åhgrend0fa8202018-04-18 09:35:13 +0200154
peahd0263542017-01-03 04:20:34 -0800155 private:
156 std::deque<std::vector<std::vector<float>>> received_render_blocks_;
157 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor);
158};
159
160class EchoCanceller3Tester {
161 public:
162 explicit EchoCanceller3Tester(int sample_rate_hz)
163 : sample_rate_hz_(sample_rate_hz),
164 num_bands_(NumBandsForRate(sample_rate_hz_)),
165 frame_length_(sample_rate_hz_ == 8000 ? 80 : 160),
166 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)),
Per Åhgrend47941e2019-08-22 11:51:13 +0200167 capture_buffer_(fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800168 1,
Per Åhgrend47941e2019-08-22 11:51:13 +0200169 fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800170 1,
Per Åhgrend47941e2019-08-22 11:51:13 +0200171 fullband_frame_length_ * 100,
172 1),
173 render_buffer_(fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800174 1,
Per Åhgrend47941e2019-08-22 11:51:13 +0200175 fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800176 1,
Per Åhgrend47941e2019-08-22 11:51:13 +0200177 fullband_frame_length_ * 100,
178 1) {}
peahd0263542017-01-03 04:20:34 -0800179
180 // Verifies that the capture data is properly received by the block processor
181 // and that the processor data is properly passed to the EchoCanceller3
182 // output.
183 void RunCaptureTransportVerificationTest() {
184 EchoCanceller3 aec3(
Per Åhgren0aefbf02019-08-23 21:29:17 +0200185 EchoCanceller3Config(), sample_rate_hz_,
peahd0263542017-01-03 04:20:34 -0800186 std::unique_ptr<BlockProcessor>(
187 new CaptureTransportVerificationProcessor(num_bands_)));
188
189 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
190 ++frame_index) {
191 aec3.AnalyzeCapture(&capture_buffer_);
192 OptionalBandSplit();
193 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200194 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800195 PopulateInputFrame(frame_length_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200196 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800197
peahcf02cf12017-04-05 14:18:07 -0700198 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800199 aec3.ProcessCapture(&capture_buffer_, false);
200 EXPECT_TRUE(VerifyOutputFrameBitexactness(
201 frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200202 &capture_buffer_.split_bands(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800203 }
204 }
205
206 // Test method for testing that the render data is properly received by the
207 // block processor.
208 void RunRenderTransportVerificationTest() {
209 EchoCanceller3 aec3(
Per Åhgren0aefbf02019-08-23 21:29:17 +0200210 EchoCanceller3Config(), sample_rate_hz_,
peahd0263542017-01-03 04:20:34 -0800211 std::unique_ptr<BlockProcessor>(
212 new RenderTransportVerificationProcessor(num_bands_)));
213
Per Åhgren0aefbf02019-08-23 21:29:17 +0200214 std::vector<float> render_input;
215 std::vector<float> capture_output;
peahd0263542017-01-03 04:20:34 -0800216 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
217 ++frame_index) {
218 aec3.AnalyzeCapture(&capture_buffer_);
219 OptionalBandSplit();
220 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200221 &capture_buffer_.split_bands(0)[0], 100);
peahcf02cf12017-04-05 14:18:07 -0700222 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200223 &render_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800224
Per Åhgren0aefbf02019-08-23 21:29:17 +0200225 for (size_t k = 0; k < frame_length_; ++k) {
226 render_input.push_back(render_buffer_.split_bands(0)[0][k]);
227 }
peahcf02cf12017-04-05 14:18:07 -0700228 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800229 aec3.ProcessCapture(&capture_buffer_, false);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200230 for (size_t k = 0; k < frame_length_; ++k) {
231 capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
232 }
peahd0263542017-01-03 04:20:34 -0800233 }
Per Åhgren0aefbf02019-08-23 21:29:17 +0200234 HighPassFilter hp_filter(1);
235 hp_filter.Process(render_input);
236
237 EXPECT_TRUE(
238 VerifyOutputFrameBitexactness(render_input, capture_output, -64));
peahd0263542017-01-03 04:20:34 -0800239 }
240
241 // Verifies that information about echo path changes are properly propagated
242 // to the block processor.
243 // The cases tested are:
244 // -That no set echo path change flags are received when there is no echo path
245 // change.
246 // -That set echo path change flags are received and continues to be received
247 // as long as echo path changes are flagged.
248 // -That set echo path change flags are no longer received when echo path
249 // change events stop being flagged.
250 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky };
251
252 void RunEchoPathChangeVerificationTest(
253 EchoPathChangeTestVariant echo_path_change_test_variant) {
254 const size_t num_full_blocks_per_frame =
255 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
256 const size_t expected_num_block_to_process =
257 (kNumFramesToProcess *
258 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
259 kBlockSize;
260 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
261 block_processor_mock(
262 new StrictMock<webrtc::test::MockBlockProcessor>());
263 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700264 .Times(expected_num_block_to_process);
peah69221db2017-01-27 03:28:19 -0800265 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800266
267 switch (echo_path_change_test_variant) {
268 case EchoPathChangeTestVariant::kNone:
269 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
270 .Times(expected_num_block_to_process);
271 break;
272 case EchoPathChangeTestVariant::kOneSticky:
273 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
274 .Times(expected_num_block_to_process);
275 break;
276 case EchoPathChangeTestVariant::kOneNonSticky:
277 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
278 .Times(num_full_blocks_per_frame);
279 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
280 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
281 break;
282 }
283
Per Åhgren0aefbf02019-08-23 21:29:17 +0200284 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_,
peahd0263542017-01-03 04:20:34 -0800285 std::move(block_processor_mock));
286
287 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
288 ++frame_index) {
289 bool echo_path_change = false;
290 switch (echo_path_change_test_variant) {
291 case EchoPathChangeTestVariant::kNone:
292 break;
293 case EchoPathChangeTestVariant::kOneSticky:
294 echo_path_change = true;
295 break;
296 case EchoPathChangeTestVariant::kOneNonSticky:
297 if (frame_index == 0) {
298 echo_path_change = true;
299 }
300 break;
301 }
302
303 aec3.AnalyzeCapture(&capture_buffer_);
304 OptionalBandSplit();
305
306 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200307 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800308 PopulateInputFrame(frame_length_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200309 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800310
peahcf02cf12017-04-05 14:18:07 -0700311 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800312 aec3.ProcessCapture(&capture_buffer_, echo_path_change);
313 }
314 }
315
316 // Test for verifying that echo leakage information is being properly passed
317 // to the processor.
318 // The cases tested are:
319 // -That no method calls are received when they should not.
320 // -That false values are received each time they are flagged.
321 // -That true values are received each time they are flagged.
322 // -That a false value is received when flagged after a true value has been
323 // flagged.
324 enum class EchoLeakageTestVariant {
325 kNone,
326 kFalseSticky,
327 kTrueSticky,
328 kTrueNonSticky
329 };
330
331 void RunEchoLeakageVerificationTest(
332 EchoLeakageTestVariant leakage_report_variant) {
333 const size_t expected_num_block_to_process =
334 (kNumFramesToProcess *
335 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
336 kBlockSize;
337 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
338 block_processor_mock(
339 new StrictMock<webrtc::test::MockBlockProcessor>());
340 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700341 .Times(expected_num_block_to_process);
peahd0263542017-01-03 04:20:34 -0800342 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _))
343 .Times(expected_num_block_to_process);
344
345 switch (leakage_report_variant) {
346 case EchoLeakageTestVariant::kNone:
peah69221db2017-01-27 03:28:19 -0800347 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800348 break;
349 case EchoLeakageTestVariant::kFalseSticky:
peah69221db2017-01-27 03:28:19 -0800350 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
351 .Times(1);
peahd0263542017-01-03 04:20:34 -0800352 break;
353 case EchoLeakageTestVariant::kTrueSticky:
peah69221db2017-01-27 03:28:19 -0800354 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
355 .Times(1);
peahd0263542017-01-03 04:20:34 -0800356 break;
357 case EchoLeakageTestVariant::kTrueNonSticky: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200358 ::testing::InSequence s;
peah69221db2017-01-27 03:28:19 -0800359 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
360 .Times(1);
361 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
peahd0263542017-01-03 04:20:34 -0800362 .Times(kNumFramesToProcess - 1);
363 } break;
364 }
365
Per Åhgren0aefbf02019-08-23 21:29:17 +0200366 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_,
peahd0263542017-01-03 04:20:34 -0800367 std::move(block_processor_mock));
368
369 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
370 ++frame_index) {
371 switch (leakage_report_variant) {
372 case EchoLeakageTestVariant::kNone:
373 break;
374 case EchoLeakageTestVariant::kFalseSticky:
375 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800376 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800377 }
378 break;
379 case EchoLeakageTestVariant::kTrueSticky:
380 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800381 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800382 }
383 break;
384 case EchoLeakageTestVariant::kTrueNonSticky:
385 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800386 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800387 } else {
peah69221db2017-01-27 03:28:19 -0800388 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800389 }
390 break;
391 }
392
393 aec3.AnalyzeCapture(&capture_buffer_);
394 OptionalBandSplit();
395
396 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200397 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800398 PopulateInputFrame(frame_length_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200399 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800400
peahcf02cf12017-04-05 14:18:07 -0700401 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800402 aec3.ProcessCapture(&capture_buffer_, false);
403 }
404 }
405
406 // This verifies that saturation information is properly passed to the
407 // BlockProcessor.
408 // The cases tested are:
409 // -That no saturation event is passed to the processor if there is no
410 // saturation.
411 // -That one frame with one negative saturated sample value is reported to be
412 // saturated and that following non-saturated frames are properly reported as
413 // not being saturated.
414 // -That one frame with one positive saturated sample value is reported to be
415 // saturated and that following non-saturated frames are properly reported as
416 // not being saturated.
417 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive };
418
419 void RunCaptureSaturationVerificationTest(
420 SaturationTestVariant saturation_variant) {
421 const size_t num_full_blocks_per_frame =
422 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
423 const size_t expected_num_block_to_process =
424 (kNumFramesToProcess *
425 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
426 kBlockSize;
427 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
428 block_processor_mock(
429 new StrictMock<webrtc::test::MockBlockProcessor>());
430 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700431 .Times(expected_num_block_to_process);
peah69221db2017-01-27 03:28:19 -0800432 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800433
434 switch (saturation_variant) {
435 case SaturationTestVariant::kNone:
436 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
437 .Times(expected_num_block_to_process);
438 break;
439 case SaturationTestVariant::kOneNegative: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200440 ::testing::InSequence s;
peahd0263542017-01-03 04:20:34 -0800441 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
442 .Times(num_full_blocks_per_frame);
443 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
444 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
445 } break;
446 case SaturationTestVariant::kOnePositive: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200447 ::testing::InSequence s;
peahd0263542017-01-03 04:20:34 -0800448 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
449 .Times(num_full_blocks_per_frame);
450 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
451 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
452 } break;
453 }
454
Per Åhgren0aefbf02019-08-23 21:29:17 +0200455 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_,
peahd0263542017-01-03 04:20:34 -0800456 std::move(block_processor_mock));
peahd0263542017-01-03 04:20:34 -0800457 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
458 ++frame_index) {
459 for (int k = 0; k < fullband_frame_length_; ++k) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200460 capture_buffer_.channels()[0][k] = 0.f;
peahd0263542017-01-03 04:20:34 -0800461 }
462 switch (saturation_variant) {
463 case SaturationTestVariant::kNone:
464 break;
465 case SaturationTestVariant::kOneNegative:
466 if (frame_index == 0) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200467 capture_buffer_.channels()[0][10] = -32768.f;
peahd0263542017-01-03 04:20:34 -0800468 }
469 break;
470 case SaturationTestVariant::kOnePositive:
471 if (frame_index == 0) {
Per Åhgrend47941e2019-08-22 11:51:13 +0200472 capture_buffer_.channels()[0][10] = 32767.f;
peahd0263542017-01-03 04:20:34 -0800473 }
474 break;
475 }
476
477 aec3.AnalyzeCapture(&capture_buffer_);
478 OptionalBandSplit();
479
480 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200481 &capture_buffer_.split_bands(0)[0], 0);
peahcf02cf12017-04-05 14:18:07 -0700482 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200483 &render_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800484
peahcf02cf12017-04-05 14:18:07 -0700485 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800486 aec3.ProcessCapture(&capture_buffer_, false);
487 }
488 }
489
490 // This test verifies that the swapqueue is able to handle jitter in the
491 // capture and render API calls.
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000492 void RunRenderSwapQueueVerificationTest() {
Per Åhgren8ba58612017-12-01 23:01:44 +0100493 const EchoCanceller3Config config;
peahd0263542017-01-03 04:20:34 -0800494 EchoCanceller3 aec3(
Per Åhgren0aefbf02019-08-23 21:29:17 +0200495 config, sample_rate_hz_,
peahd0263542017-01-03 04:20:34 -0800496 std::unique_ptr<BlockProcessor>(
497 new RenderTransportVerificationProcessor(num_bands_)));
498
Per Åhgren0aefbf02019-08-23 21:29:17 +0200499 std::vector<float> render_input;
500 std::vector<float> capture_output;
501
Per Åhgren8ba58612017-12-01 23:01:44 +0100502 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
peahd0263542017-01-03 04:20:34 -0800503 ++frame_index) {
504 if (sample_rate_hz_ > 16000) {
505 render_buffer_.SplitIntoFrequencyBands();
506 }
peahcf02cf12017-04-05 14:18:07 -0700507 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200508 &render_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800509
peahcf02cf12017-04-05 14:18:07 -0700510 if (sample_rate_hz_ > 16000) {
511 render_buffer_.SplitIntoFrequencyBands();
512 }
513
Per Åhgren0aefbf02019-08-23 21:29:17 +0200514 for (size_t k = 0; k < frame_length_; ++k) {
515 render_input.push_back(render_buffer_.split_bands(0)[0][k]);
516 }
peahcf02cf12017-04-05 14:18:07 -0700517 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800518 }
519
Per Åhgren8ba58612017-12-01 23:01:44 +0100520 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
peahd0263542017-01-03 04:20:34 -0800521 ++frame_index) {
522 aec3.AnalyzeCapture(&capture_buffer_);
523 if (sample_rate_hz_ > 16000) {
524 capture_buffer_.SplitIntoFrequencyBands();
525 }
526
527 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200528 &capture_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800529
530 aec3.ProcessCapture(&capture_buffer_, false);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200531 for (size_t k = 0; k < frame_length_; ++k) {
532 capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
533 }
peahd0263542017-01-03 04:20:34 -0800534 }
Per Åhgren0aefbf02019-08-23 21:29:17 +0200535 HighPassFilter hp_filter(1);
536 hp_filter.Process(render_input);
537
538 EXPECT_TRUE(
539 VerifyOutputFrameBitexactness(render_input, capture_output, -64));
peahd0263542017-01-03 04:20:34 -0800540 }
541
542 // This test verifies that a buffer overrun in the render swapqueue is
543 // properly reported.
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000544 void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
Per Åhgren0aefbf02019-08-23 21:29:17 +0200545 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_);
peahd0263542017-01-03 04:20:34 -0800546
peahcf02cf12017-04-05 14:18:07 -0700547 constexpr size_t kRenderTransferQueueSize = 30;
peahd0263542017-01-03 04:20:34 -0800548 for (size_t k = 0; k < 2; ++k) {
peahcf02cf12017-04-05 14:18:07 -0700549 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
peahd0263542017-01-03 04:20:34 -0800550 ++frame_index) {
551 if (sample_rate_hz_ > 16000) {
552 render_buffer_.SplitIntoFrequencyBands();
553 }
peah522d71b2017-02-23 05:16:26 -0800554 PopulateInputFrame(frame_length_, frame_index,
Per Åhgrend47941e2019-08-22 11:51:13 +0200555 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800556
Per Åhgren0aefbf02019-08-23 21:29:17 +0200557 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800558 }
559 }
560 }
561
562#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
563 // Verifies the that the check for the number of bands in the AnalyzeRender
564 // input is correct by adjusting the sample rates of EchoCanceller3 and the
565 // input AudioBuffer to have a different number of bands.
566 void RunAnalyzeRenderNumBandsCheckVerification() {
567 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
568 // way that the number of bands for the rates are different.
569 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Per Åhgren0aefbf02019-08-23 21:29:17 +0200570 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz);
peah522d71b2017-02-23 05:16:26 -0800571 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800572
573 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
574 }
575
576 // Verifies the that the check for the number of bands in the ProcessCapture
577 // input is correct by adjusting the sample rates of EchoCanceller3 and the
578 // input AudioBuffer to have a different number of bands.
579 void RunProcessCaptureNumBandsCheckVerification() {
580 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
581 // way that the number of bands for the rates are different.
582 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Per Åhgren0aefbf02019-08-23 21:29:17 +0200583 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz);
peahd0263542017-01-03 04:20:34 -0800584 PopulateInputFrame(frame_length_, num_bands_, 0,
585 &capture_buffer_.split_bands_f(0)[0], 100);
586 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
587 }
588
589 // Verifies the that the check for the frame length in the AnalyzeRender input
590 // is correct by adjusting the sample rates of EchoCanceller3 and the input
591 // AudioBuffer to have a different frame lengths.
592 void RunAnalyzeRenderFrameLengthCheckVerification() {
593 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
594 // way that the band frame lengths are different.
595 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
Per Åhgren0aefbf02019-08-23 21:29:17 +0200596 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz);
peahd0263542017-01-03 04:20:34 -0800597
598 OptionalBandSplit();
peah522d71b2017-02-23 05:16:26 -0800599 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800600
601 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
602 }
603
604 // Verifies the that the check for the frame length in the AnalyzeRender input
605 // is correct by adjusting the sample rates of EchoCanceller3 and the input
606 // AudioBuffer to have a different frame lengths.
607 void RunProcessCaptureFrameLengthCheckVerification() {
608 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
609 // way that the band frame lengths are different.
610 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
Per Åhgren0aefbf02019-08-23 21:29:17 +0200611 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz);
peahd0263542017-01-03 04:20:34 -0800612
613 OptionalBandSplit();
614 PopulateInputFrame(frame_length_, num_bands_, 0,
615 &capture_buffer_.split_bands_f(0)[0], 100);
616
617 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
618 }
619
620#endif
621
622 private:
623 void OptionalBandSplit() {
624 if (sample_rate_hz_ > 16000) {
625 capture_buffer_.SplitIntoFrequencyBands();
626 render_buffer_.SplitIntoFrequencyBands();
627 }
628 }
629
630 static constexpr size_t kNumFramesToProcess = 20;
631 const int sample_rate_hz_;
632 const size_t num_bands_;
633 const size_t frame_length_;
634 const int fullband_frame_length_;
635 AudioBuffer capture_buffer_;
636 AudioBuffer render_buffer_;
637
638 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester);
639};
640
641std::string ProduceDebugText(int sample_rate_hz) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200642 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800643 ss << "Sample rate: " << sample_rate_hz;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200644 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800645}
646
647std::string ProduceDebugText(int sample_rate_hz, int variant) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200648 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800649 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200650 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800651}
652
653} // namespace
654
655TEST(EchoCanceller3Buffering, CaptureBitexactness) {
656 for (auto rate : {8000, 16000, 32000, 48000}) {
657 SCOPED_TRACE(ProduceDebugText(rate));
658 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest();
659 }
660}
661
662TEST(EchoCanceller3Buffering, RenderBitexactness) {
663 for (auto rate : {8000, 16000, 32000, 48000}) {
664 SCOPED_TRACE(ProduceDebugText(rate));
665 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest();
666 }
667}
668
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000669TEST(EchoCanceller3Buffering, RenderSwapQueue) {
peahcf02cf12017-04-05 14:18:07 -0700670 for (auto rate : {8000, 16000}) {
peahd0263542017-01-03 04:20:34 -0800671 SCOPED_TRACE(ProduceDebugText(rate));
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000672 EchoCanceller3Tester(rate).RunRenderSwapQueueVerificationTest();
peahd0263542017-01-03 04:20:34 -0800673 }
674}
675
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000676TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) {
peahd0263542017-01-03 04:20:34 -0800677 for (auto rate : {8000, 16000, 32000, 48000}) {
678 SCOPED_TRACE(ProduceDebugText(rate));
679 EchoCanceller3Tester(rate)
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000680 .RunRenderPipelineSwapQueueOverrunReturnValueTest();
peahd0263542017-01-03 04:20:34 -0800681 }
682}
683
684TEST(EchoCanceller3Messaging, CaptureSaturation) {
685 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone,
686 EchoCanceller3Tester::SaturationTestVariant::kOneNegative,
687 EchoCanceller3Tester::SaturationTestVariant::kOnePositive};
688 for (auto rate : {8000, 16000, 32000, 48000}) {
689 for (auto variant : variants) {
690 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
691 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant);
692 }
693 }
694}
695
696TEST(EchoCanceller3Messaging, EchoPathChange) {
697 auto variants = {
698 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone,
699 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky,
700 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky};
701 for (auto rate : {8000, 16000, 32000, 48000}) {
702 for (auto variant : variants) {
703 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
704 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant);
705 }
706 }
707}
708
709TEST(EchoCanceller3Messaging, EchoLeakage) {
710 auto variants = {
711 EchoCanceller3Tester::EchoLeakageTestVariant::kNone,
712 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky,
713 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky,
714 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky};
715 for (auto rate : {8000, 16000, 32000, 48000}) {
716 for (auto variant : variants) {
717 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
718 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant);
719 }
720 }
721}
722
723#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
peahd0263542017-01-03 04:20:34 -0800724
725TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) {
726 for (auto rate : {8000, 16000, 32000, 48000}) {
727 SCOPED_TRACE(ProduceDebugText(rate));
728 EchoCanceller3Tester(rate).RunProcessCaptureNumBandsCheckVerification();
729 }
730}
731
peah522d71b2017-02-23 05:16:26 -0800732// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
733// tests on test bots has been fixed.
734TEST(EchoCanceller3InputCheck,
735 DISABLED_WrongRenderFrameLengthCheckVerification) {
peahd0263542017-01-03 04:20:34 -0800736 for (auto rate : {8000, 16000}) {
737 SCOPED_TRACE(ProduceDebugText(rate));
738 EchoCanceller3Tester(rate).RunAnalyzeRenderFrameLengthCheckVerification();
739 }
740}
741
742TEST(EchoCanceller3InputCheck, WrongCaptureFrameLengthCheckVerification) {
743 for (auto rate : {8000, 16000}) {
744 SCOPED_TRACE(ProduceDebugText(rate));
745 EchoCanceller3Tester(rate).RunProcessCaptureFrameLengthCheckVerification();
746 }
747}
748
peahd0263542017-01-03 04:20:34 -0800749// Verifiers that the verification for null input to the capture processing api
750// call works.
751TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
Per Åhgren0aefbf02019-08-23 21:29:17 +0200752 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 16000)
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200753 .ProcessCapture(nullptr, false),
754 "");
peahd0263542017-01-03 04:20:34 -0800755}
756
peah21920892017-02-08 05:08:56 -0800757// Verifies the check for correct sample rate.
peahcf02cf12017-04-05 14:18:07 -0700758// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
759// tests on test bots has been fixed.
760TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
peah21920892017-02-08 05:08:56 -0800761 ApmDataDumper data_dumper(0);
Per Åhgren0aefbf02019-08-23 21:29:17 +0200762 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8001), "");
peah21920892017-02-08 05:08:56 -0800763}
764
peahd0263542017-01-03 04:20:34 -0800765#endif
766
767} // namespace webrtc