blob: 1b6bdaf7aa7b9df4e03095ecdf896edb2c6fb85b [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"
Jonas Olsson366a50c2018-09-06 13:41:30 +020024#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "test/gmock.h"
26#include "test/gtest.h"
peahd0263542017-01-03 04:20:34 -080027
28namespace webrtc {
29namespace {
30
Mirko Bonadei6a489f22019-04-09 15:11:12 +020031using ::testing::_;
32using ::testing::StrictMock;
peahd0263542017-01-03 04:20:34 -080033
34// Populates the frame with linearly increasing sample values for each band,
35// with a band-specific offset, in order to allow simple bitexactness
36// verification for each band.
37void PopulateInputFrame(size_t frame_length,
38 size_t num_bands,
39 size_t frame_index,
40 float* const* frame,
41 int offset) {
42 for (size_t k = 0; k < num_bands; ++k) {
43 for (size_t i = 0; i < frame_length; ++i) {
44 float value = static_cast<int>(frame_index * frame_length + i) + offset;
45 frame[k][i] = (value > 0 ? 5000 * k + value : 0);
46 }
47 }
48}
49
peah522d71b2017-02-23 05:16:26 -080050// Populates the frame with linearly increasing sample values.
51void PopulateInputFrame(size_t frame_length,
52 size_t frame_index,
53 float* frame,
54 int offset) {
55 for (size_t i = 0; i < frame_length; ++i) {
56 float value = static_cast<int>(frame_index * frame_length + i) + offset;
57 frame[i] = std::max(value, 0.f);
58 }
59}
60
peahd0263542017-01-03 04:20:34 -080061// Verifies the that samples in the output frame are identical to the samples
62// that were produced for the input frame, with an offset in order to compensate
63// for buffering delays.
64bool VerifyOutputFrameBitexactness(size_t frame_length,
65 size_t num_bands,
66 size_t frame_index,
67 const float* const* frame,
68 int offset) {
69 float reference_frame_data[kMaxNumBands][2 * kSubFrameLength];
70 float* reference_frame[kMaxNumBands];
71 for (size_t k = 0; k < num_bands; ++k) {
72 reference_frame[k] = &reference_frame_data[k][0];
73 }
74
75 PopulateInputFrame(frame_length, num_bands, frame_index, reference_frame,
76 offset);
77 for (size_t k = 0; k < num_bands; ++k) {
78 for (size_t i = 0; i < frame_length; ++i) {
79 if (reference_frame[k][i] != frame[k][i]) {
80 return false;
81 }
82 }
83 }
84
85 return true;
86}
87
88// Class for testing that the capture data is properly received by the block
89// processor and that the processor data is properly passed to the
90// EchoCanceller3 output.
91class CaptureTransportVerificationProcessor : public BlockProcessor {
92 public:
93 explicit CaptureTransportVerificationProcessor(size_t num_bands) {}
94 ~CaptureTransportVerificationProcessor() override = default;
95
peah69221db2017-01-27 03:28:19 -080096 void ProcessCapture(bool level_change,
peahd0263542017-01-03 04:20:34 -080097 bool saturated_microphone_signal,
98 std::vector<std::vector<float>>* capture_block) override {
99 }
100
peahcf02cf12017-04-05 14:18:07 -0700101 void BufferRender(const std::vector<std::vector<float>>& block) override {}
peahd0263542017-01-03 04:20:34 -0800102
peah69221db2017-01-27 03:28:19 -0800103 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800104
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100105 void GetMetrics(EchoControl::Metrics* metrics) const override {}
106
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100107 void SetAudioBufferDelay(size_t delay_ms) override {}
Per Ã…hgrend0fa8202018-04-18 09:35:13 +0200108
peahd0263542017-01-03 04:20:34 -0800109 private:
110 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
111};
112
113// Class for testing that the render data is properly received by the block
114// processor.
115class RenderTransportVerificationProcessor : public BlockProcessor {
116 public:
117 explicit RenderTransportVerificationProcessor(size_t num_bands) {}
118 ~RenderTransportVerificationProcessor() override = default;
119
peah69221db2017-01-27 03:28:19 -0800120 void ProcessCapture(bool level_change,
peahd0263542017-01-03 04:20:34 -0800121 bool saturated_microphone_signal,
122 std::vector<std::vector<float>>* capture_block) override {
123 std::vector<std::vector<float>> render_block =
124 received_render_blocks_.front();
125 received_render_blocks_.pop_front();
126 capture_block->swap(render_block);
127 }
128
peahcf02cf12017-04-05 14:18:07 -0700129 void BufferRender(const std::vector<std::vector<float>>& block) override {
130 received_render_blocks_.push_back(block);
peahd0263542017-01-03 04:20:34 -0800131 }
132
peah69221db2017-01-27 03:28:19 -0800133 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800134
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100135 void GetMetrics(EchoControl::Metrics* metrics) const override {}
136
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100137 void SetAudioBufferDelay(size_t delay_ms) override {}
Per Ã…hgrend0fa8202018-04-18 09:35:13 +0200138
peahd0263542017-01-03 04:20:34 -0800139 private:
140 std::deque<std::vector<std::vector<float>>> received_render_blocks_;
141 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor);
142};
143
144class EchoCanceller3Tester {
145 public:
146 explicit EchoCanceller3Tester(int sample_rate_hz)
147 : sample_rate_hz_(sample_rate_hz),
148 num_bands_(NumBandsForRate(sample_rate_hz_)),
149 frame_length_(sample_rate_hz_ == 8000 ? 80 : 160),
150 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)),
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200151 capture_buffer_(fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800152 1,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200153 fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800154 1,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200155 fullband_frame_length_ * 100,
156 1),
157 render_buffer_(fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800158 1,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200159 fullband_frame_length_ * 100,
peahd0263542017-01-03 04:20:34 -0800160 1,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200161 fullband_frame_length_ * 100,
162 1) {}
peahd0263542017-01-03 04:20:34 -0800163
164 // Verifies that the capture data is properly received by the block processor
165 // and that the processor data is properly passed to the EchoCanceller3
166 // output.
167 void RunCaptureTransportVerificationTest() {
168 EchoCanceller3 aec3(
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100169 EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800170 std::unique_ptr<BlockProcessor>(
171 new CaptureTransportVerificationProcessor(num_bands_)));
172
173 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
174 ++frame_index) {
175 aec3.AnalyzeCapture(&capture_buffer_);
176 OptionalBandSplit();
177 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200178 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800179 PopulateInputFrame(frame_length_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200180 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800181
peahcf02cf12017-04-05 14:18:07 -0700182 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800183 aec3.ProcessCapture(&capture_buffer_, false);
184 EXPECT_TRUE(VerifyOutputFrameBitexactness(
185 frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200186 &capture_buffer_.split_bands(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800187 }
188 }
189
190 // Test method for testing that the render data is properly received by the
191 // block processor.
192 void RunRenderTransportVerificationTest() {
193 EchoCanceller3 aec3(
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100194 EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800195 std::unique_ptr<BlockProcessor>(
196 new RenderTransportVerificationProcessor(num_bands_)));
197
198 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
199 ++frame_index) {
200 aec3.AnalyzeCapture(&capture_buffer_);
201 OptionalBandSplit();
202 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200203 &capture_buffer_.split_bands(0)[0], 100);
peahcf02cf12017-04-05 14:18:07 -0700204 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200205 &render_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800206
peahcf02cf12017-04-05 14:18:07 -0700207 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800208 aec3.ProcessCapture(&capture_buffer_, false);
209 EXPECT_TRUE(VerifyOutputFrameBitexactness(
peahcf02cf12017-04-05 14:18:07 -0700210 frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200211 &capture_buffer_.split_bands(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800212 }
213 }
214
215 // Verifies that information about echo path changes are properly propagated
216 // to the block processor.
217 // The cases tested are:
218 // -That no set echo path change flags are received when there is no echo path
219 // change.
220 // -That set echo path change flags are received and continues to be received
221 // as long as echo path changes are flagged.
222 // -That set echo path change flags are no longer received when echo path
223 // change events stop being flagged.
224 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky };
225
226 void RunEchoPathChangeVerificationTest(
227 EchoPathChangeTestVariant echo_path_change_test_variant) {
228 const size_t num_full_blocks_per_frame =
229 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
230 const size_t expected_num_block_to_process =
231 (kNumFramesToProcess *
232 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
233 kBlockSize;
234 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
235 block_processor_mock(
236 new StrictMock<webrtc::test::MockBlockProcessor>());
237 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700238 .Times(expected_num_block_to_process);
peah69221db2017-01-27 03:28:19 -0800239 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800240
241 switch (echo_path_change_test_variant) {
242 case EchoPathChangeTestVariant::kNone:
243 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
244 .Times(expected_num_block_to_process);
245 break;
246 case EchoPathChangeTestVariant::kOneSticky:
247 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
248 .Times(expected_num_block_to_process);
249 break;
250 case EchoPathChangeTestVariant::kOneNonSticky:
251 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
252 .Times(num_full_blocks_per_frame);
253 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
254 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
255 break;
256 }
257
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100258 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800259 std::move(block_processor_mock));
260
261 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
262 ++frame_index) {
263 bool echo_path_change = false;
264 switch (echo_path_change_test_variant) {
265 case EchoPathChangeTestVariant::kNone:
266 break;
267 case EchoPathChangeTestVariant::kOneSticky:
268 echo_path_change = true;
269 break;
270 case EchoPathChangeTestVariant::kOneNonSticky:
271 if (frame_index == 0) {
272 echo_path_change = true;
273 }
274 break;
275 }
276
277 aec3.AnalyzeCapture(&capture_buffer_);
278 OptionalBandSplit();
279
280 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200281 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800282 PopulateInputFrame(frame_length_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200283 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800284
peahcf02cf12017-04-05 14:18:07 -0700285 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800286 aec3.ProcessCapture(&capture_buffer_, echo_path_change);
287 }
288 }
289
290 // Test for verifying that echo leakage information is being properly passed
291 // to the processor.
292 // The cases tested are:
293 // -That no method calls are received when they should not.
294 // -That false values are received each time they are flagged.
295 // -That true values are received each time they are flagged.
296 // -That a false value is received when flagged after a true value has been
297 // flagged.
298 enum class EchoLeakageTestVariant {
299 kNone,
300 kFalseSticky,
301 kTrueSticky,
302 kTrueNonSticky
303 };
304
305 void RunEchoLeakageVerificationTest(
306 EchoLeakageTestVariant leakage_report_variant) {
307 const size_t expected_num_block_to_process =
308 (kNumFramesToProcess *
309 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
310 kBlockSize;
311 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
312 block_processor_mock(
313 new StrictMock<webrtc::test::MockBlockProcessor>());
314 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700315 .Times(expected_num_block_to_process);
peahd0263542017-01-03 04:20:34 -0800316 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _))
317 .Times(expected_num_block_to_process);
318
319 switch (leakage_report_variant) {
320 case EchoLeakageTestVariant::kNone:
peah69221db2017-01-27 03:28:19 -0800321 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800322 break;
323 case EchoLeakageTestVariant::kFalseSticky:
peah69221db2017-01-27 03:28:19 -0800324 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
325 .Times(1);
peahd0263542017-01-03 04:20:34 -0800326 break;
327 case EchoLeakageTestVariant::kTrueSticky:
peah69221db2017-01-27 03:28:19 -0800328 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
329 .Times(1);
peahd0263542017-01-03 04:20:34 -0800330 break;
331 case EchoLeakageTestVariant::kTrueNonSticky: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200332 ::testing::InSequence s;
peah69221db2017-01-27 03:28:19 -0800333 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
334 .Times(1);
335 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
peahd0263542017-01-03 04:20:34 -0800336 .Times(kNumFramesToProcess - 1);
337 } break;
338 }
339
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100340 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800341 std::move(block_processor_mock));
342
343 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
344 ++frame_index) {
345 switch (leakage_report_variant) {
346 case EchoLeakageTestVariant::kNone:
347 break;
348 case EchoLeakageTestVariant::kFalseSticky:
349 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800350 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800351 }
352 break;
353 case EchoLeakageTestVariant::kTrueSticky:
354 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800355 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800356 }
357 break;
358 case EchoLeakageTestVariant::kTrueNonSticky:
359 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800360 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800361 } else {
peah69221db2017-01-27 03:28:19 -0800362 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800363 }
364 break;
365 }
366
367 aec3.AnalyzeCapture(&capture_buffer_);
368 OptionalBandSplit();
369
370 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200371 &capture_buffer_.split_bands(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800372 PopulateInputFrame(frame_length_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200373 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800374
peahcf02cf12017-04-05 14:18:07 -0700375 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800376 aec3.ProcessCapture(&capture_buffer_, false);
377 }
378 }
379
380 // This verifies that saturation information is properly passed to the
381 // BlockProcessor.
382 // The cases tested are:
383 // -That no saturation event is passed to the processor if there is no
384 // saturation.
385 // -That one frame with one negative saturated sample value is reported to be
386 // saturated and that following non-saturated frames are properly reported as
387 // not being saturated.
388 // -That one frame with one positive saturated sample value is reported to be
389 // saturated and that following non-saturated frames are properly reported as
390 // not being saturated.
391 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive };
392
393 void RunCaptureSaturationVerificationTest(
394 SaturationTestVariant saturation_variant) {
395 const size_t num_full_blocks_per_frame =
396 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
397 const size_t expected_num_block_to_process =
398 (kNumFramesToProcess *
399 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
400 kBlockSize;
401 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
402 block_processor_mock(
403 new StrictMock<webrtc::test::MockBlockProcessor>());
404 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700405 .Times(expected_num_block_to_process);
peah69221db2017-01-27 03:28:19 -0800406 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800407
408 switch (saturation_variant) {
409 case SaturationTestVariant::kNone:
410 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
411 .Times(expected_num_block_to_process);
412 break;
413 case SaturationTestVariant::kOneNegative: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200414 ::testing::InSequence s;
peahd0263542017-01-03 04:20:34 -0800415 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
416 .Times(num_full_blocks_per_frame);
417 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
418 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
419 } break;
420 case SaturationTestVariant::kOnePositive: {
Mirko Bonadei6a489f22019-04-09 15:11:12 +0200421 ::testing::InSequence s;
peahd0263542017-01-03 04:20:34 -0800422 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
423 .Times(num_full_blocks_per_frame);
424 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
425 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
426 } break;
427 }
428
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100429 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800430 std::move(block_processor_mock));
peahd0263542017-01-03 04:20:34 -0800431 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
432 ++frame_index) {
433 for (int k = 0; k < fullband_frame_length_; ++k) {
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200434 capture_buffer_.channels()[0][k] = 0.f;
peahd0263542017-01-03 04:20:34 -0800435 }
436 switch (saturation_variant) {
437 case SaturationTestVariant::kNone:
438 break;
439 case SaturationTestVariant::kOneNegative:
440 if (frame_index == 0) {
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200441 capture_buffer_.channels()[0][10] = -32768.f;
peahd0263542017-01-03 04:20:34 -0800442 }
443 break;
444 case SaturationTestVariant::kOnePositive:
445 if (frame_index == 0) {
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200446 capture_buffer_.channels()[0][10] = 32767.f;
peahd0263542017-01-03 04:20:34 -0800447 }
448 break;
449 }
450
451 aec3.AnalyzeCapture(&capture_buffer_);
452 OptionalBandSplit();
453
454 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200455 &capture_buffer_.split_bands(0)[0], 0);
peahcf02cf12017-04-05 14:18:07 -0700456 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200457 &render_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800458
peahcf02cf12017-04-05 14:18:07 -0700459 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800460 aec3.ProcessCapture(&capture_buffer_, false);
461 }
462 }
463
464 // This test verifies that the swapqueue is able to handle jitter in the
465 // capture and render API calls.
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000466 void RunRenderSwapQueueVerificationTest() {
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100467 const EchoCanceller3Config config;
peahd0263542017-01-03 04:20:34 -0800468 EchoCanceller3 aec3(
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100469 config, sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800470 std::unique_ptr<BlockProcessor>(
471 new RenderTransportVerificationProcessor(num_bands_)));
472
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100473 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
peahd0263542017-01-03 04:20:34 -0800474 ++frame_index) {
475 if (sample_rate_hz_ > 16000) {
476 render_buffer_.SplitIntoFrequencyBands();
477 }
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 if (sample_rate_hz_ > 16000) {
482 render_buffer_.SplitIntoFrequencyBands();
483 }
484
485 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800486 }
487
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100488 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
peahd0263542017-01-03 04:20:34 -0800489 ++frame_index) {
490 aec3.AnalyzeCapture(&capture_buffer_);
491 if (sample_rate_hz_ > 16000) {
492 capture_buffer_.SplitIntoFrequencyBands();
493 }
494
495 PopulateInputFrame(frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200496 &capture_buffer_.split_bands(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800497
498 aec3.ProcessCapture(&capture_buffer_, false);
499 EXPECT_TRUE(VerifyOutputFrameBitexactness(
peahcf02cf12017-04-05 14:18:07 -0700500 frame_length_, num_bands_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200501 &capture_buffer_.split_bands(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800502 }
503 }
504
505 // This test verifies that a buffer overrun in the render swapqueue is
506 // properly reported.
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000507 void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200508 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false);
peahd0263542017-01-03 04:20:34 -0800509
peahcf02cf12017-04-05 14:18:07 -0700510 constexpr size_t kRenderTransferQueueSize = 30;
peahd0263542017-01-03 04:20:34 -0800511 for (size_t k = 0; k < 2; ++k) {
peahcf02cf12017-04-05 14:18:07 -0700512 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
peahd0263542017-01-03 04:20:34 -0800513 ++frame_index) {
514 if (sample_rate_hz_ > 16000) {
515 render_buffer_.SplitIntoFrequencyBands();
516 }
peah522d71b2017-02-23 05:16:26 -0800517 PopulateInputFrame(frame_length_, frame_index,
Per Ã…hgrend47941e2019-08-22 11:51:13 +0200518 &render_buffer_.channels()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800519
520 if (k == 0) {
peahcf02cf12017-04-05 14:18:07 -0700521 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800522 } else {
peahcf02cf12017-04-05 14:18:07 -0700523 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800524 }
525 }
526 }
527 }
528
529#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
530 // Verifies the that the check for the number of bands in the AnalyzeRender
531 // input is correct by adjusting the sample rates of EchoCanceller3 and the
532 // input AudioBuffer to have a different number of bands.
533 void RunAnalyzeRenderNumBandsCheckVerification() {
534 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
535 // way that the number of bands for the rates are different.
536 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200537 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peah522d71b2017-02-23 05:16:26 -0800538 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800539
540 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
541 }
542
543 // Verifies the that the check for the number of bands in the ProcessCapture
544 // input is correct by adjusting the sample rates of EchoCanceller3 and the
545 // input AudioBuffer to have a different number of bands.
546 void RunProcessCaptureNumBandsCheckVerification() {
547 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
548 // way that the number of bands for the rates are different.
549 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200550 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800551 PopulateInputFrame(frame_length_, num_bands_, 0,
552 &capture_buffer_.split_bands_f(0)[0], 100);
553 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
554 }
555
556 // Verifies the that the check for the frame length in the AnalyzeRender input
557 // is correct by adjusting the sample rates of EchoCanceller3 and the input
558 // AudioBuffer to have a different frame lengths.
559 void RunAnalyzeRenderFrameLengthCheckVerification() {
560 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
561 // way that the band frame lengths are different.
562 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200563 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800564
565 OptionalBandSplit();
peah522d71b2017-02-23 05:16:26 -0800566 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800567
568 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
569 }
570
571 // Verifies the that the check for the frame length in the AnalyzeRender input
572 // is correct by adjusting the sample rates of EchoCanceller3 and the input
573 // AudioBuffer to have a different frame lengths.
574 void RunProcessCaptureFrameLengthCheckVerification() {
575 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
576 // way that the band frame lengths are different.
577 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200578 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800579
580 OptionalBandSplit();
581 PopulateInputFrame(frame_length_, num_bands_, 0,
582 &capture_buffer_.split_bands_f(0)[0], 100);
583
584 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
585 }
586
587#endif
588
589 private:
590 void OptionalBandSplit() {
591 if (sample_rate_hz_ > 16000) {
592 capture_buffer_.SplitIntoFrequencyBands();
593 render_buffer_.SplitIntoFrequencyBands();
594 }
595 }
596
597 static constexpr size_t kNumFramesToProcess = 20;
598 const int sample_rate_hz_;
599 const size_t num_bands_;
600 const size_t frame_length_;
601 const int fullband_frame_length_;
602 AudioBuffer capture_buffer_;
603 AudioBuffer render_buffer_;
604
605 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester);
606};
607
608std::string ProduceDebugText(int sample_rate_hz) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200609 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800610 ss << "Sample rate: " << sample_rate_hz;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200611 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800612}
613
614std::string ProduceDebugText(int sample_rate_hz, int variant) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200615 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800616 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200617 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800618}
619
620} // namespace
621
622TEST(EchoCanceller3Buffering, CaptureBitexactness) {
623 for (auto rate : {8000, 16000, 32000, 48000}) {
624 SCOPED_TRACE(ProduceDebugText(rate));
625 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest();
626 }
627}
628
629TEST(EchoCanceller3Buffering, RenderBitexactness) {
630 for (auto rate : {8000, 16000, 32000, 48000}) {
631 SCOPED_TRACE(ProduceDebugText(rate));
632 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest();
633 }
634}
635
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000636TEST(EchoCanceller3Buffering, RenderSwapQueue) {
peahcf02cf12017-04-05 14:18:07 -0700637 for (auto rate : {8000, 16000}) {
peahd0263542017-01-03 04:20:34 -0800638 SCOPED_TRACE(ProduceDebugText(rate));
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000639 EchoCanceller3Tester(rate).RunRenderSwapQueueVerificationTest();
peahd0263542017-01-03 04:20:34 -0800640 }
641}
642
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000643TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) {
peahd0263542017-01-03 04:20:34 -0800644 for (auto rate : {8000, 16000, 32000, 48000}) {
645 SCOPED_TRACE(ProduceDebugText(rate));
646 EchoCanceller3Tester(rate)
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000647 .RunRenderPipelineSwapQueueOverrunReturnValueTest();
peahd0263542017-01-03 04:20:34 -0800648 }
649}
650
651TEST(EchoCanceller3Messaging, CaptureSaturation) {
652 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone,
653 EchoCanceller3Tester::SaturationTestVariant::kOneNegative,
654 EchoCanceller3Tester::SaturationTestVariant::kOnePositive};
655 for (auto rate : {8000, 16000, 32000, 48000}) {
656 for (auto variant : variants) {
657 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
658 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant);
659 }
660 }
661}
662
663TEST(EchoCanceller3Messaging, EchoPathChange) {
664 auto variants = {
665 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone,
666 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky,
667 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky};
668 for (auto rate : {8000, 16000, 32000, 48000}) {
669 for (auto variant : variants) {
670 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
671 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant);
672 }
673 }
674}
675
676TEST(EchoCanceller3Messaging, EchoLeakage) {
677 auto variants = {
678 EchoCanceller3Tester::EchoLeakageTestVariant::kNone,
679 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky,
680 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky,
681 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky};
682 for (auto rate : {8000, 16000, 32000, 48000}) {
683 for (auto variant : variants) {
684 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
685 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant);
686 }
687 }
688}
689
690#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
peahd0263542017-01-03 04:20:34 -0800691
692TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) {
693 for (auto rate : {8000, 16000, 32000, 48000}) {
694 SCOPED_TRACE(ProduceDebugText(rate));
695 EchoCanceller3Tester(rate).RunProcessCaptureNumBandsCheckVerification();
696 }
697}
698
peah522d71b2017-02-23 05:16:26 -0800699// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
700// tests on test bots has been fixed.
701TEST(EchoCanceller3InputCheck,
702 DISABLED_WrongRenderFrameLengthCheckVerification) {
peahd0263542017-01-03 04:20:34 -0800703 for (auto rate : {8000, 16000}) {
704 SCOPED_TRACE(ProduceDebugText(rate));
705 EchoCanceller3Tester(rate).RunAnalyzeRenderFrameLengthCheckVerification();
706 }
707}
708
709TEST(EchoCanceller3InputCheck, WrongCaptureFrameLengthCheckVerification) {
710 for (auto rate : {8000, 16000}) {
711 SCOPED_TRACE(ProduceDebugText(rate));
712 EchoCanceller3Tester(rate).RunProcessCaptureFrameLengthCheckVerification();
713 }
714}
715
716// Verifiers that the verification for null input to the render analysis api
717// call works.
718TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200719 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
720 .AnalyzeRender(nullptr),
721 "");
peahd0263542017-01-03 04:20:34 -0800722}
723
724// Verifiers that the verification for null input to the capture analysis api
725// call works.
726TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200727 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
728 .AnalyzeCapture(nullptr),
729 "");
peahd0263542017-01-03 04:20:34 -0800730}
731
732// Verifiers that the verification for null input to the capture processing api
733// call works.
734TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200735 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
736 .ProcessCapture(nullptr, false),
737 "");
peahd0263542017-01-03 04:20:34 -0800738}
739
peah21920892017-02-08 05:08:56 -0800740// Verifies the check for correct sample rate.
peahcf02cf12017-04-05 14:18:07 -0700741// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
742// tests on test bots has been fixed.
743TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
peah21920892017-02-08 05:08:56 -0800744 ApmDataDumper data_dumper(0);
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200745 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8001, false), "");
peah21920892017-02-08 05:08:56 -0800746}
747
peahd0263542017-01-03 04:20:34 -0800748#endif
749
750} // namespace webrtc