1 /*
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
11 #include "modules/audio_processing/aec3/echo_canceller3.h"
12
13 #include <deque>
14 #include <memory>
15 #include <sstream>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "modules/audio_processing/aec3/aec3_common.h"
21 #include "modules/audio_processing/aec3/block_processor.h"
22 #include "modules/audio_processing/aec3/frame_blocker.h"
23 #include "modules/audio_processing/aec3/mock/mock_block_processor.h"
24 #include "modules/audio_processing/audio_buffer.h"
25 #include "test/gmock.h"
26 #include "test/gtest.h"
27
28 namespace webrtc {
29 namespace {
30
31 using testing::StrictMock;
32 using testing::_;
33
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.
PopulateInputFrame(size_t frame_length,size_t num_bands,size_t frame_index,float * const * frame,int offset)37 void 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
50 // Populates the frame with linearly increasing sample values.
PopulateInputFrame(size_t frame_length,size_t frame_index,float * frame,int offset)51 void 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
61 // 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.
VerifyOutputFrameBitexactness(size_t frame_length,size_t num_bands,size_t frame_index,const float * const * frame,int offset)64 bool 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.
91 class CaptureTransportVerificationProcessor : public BlockProcessor {
92 public:
CaptureTransportVerificationProcessor(size_t num_bands)93 explicit CaptureTransportVerificationProcessor(size_t num_bands) {}
94 ~CaptureTransportVerificationProcessor() override = default;
95
ProcessCapture(bool level_change,bool saturated_microphone_signal,std::vector<std::vector<float>> * capture_block)96 void ProcessCapture(bool level_change,
97 bool saturated_microphone_signal,
98 std::vector<std::vector<float>>* capture_block) override {
99 }
100
BufferRender(const std::vector<std::vector<float>> & block)101 void BufferRender(const std::vector<std::vector<float>>& block) override {}
102
UpdateEchoLeakageStatus(bool leakage_detected)103 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
104
GetMetrics(EchoControl::Metrics * metrics) const105 void GetMetrics(EchoControl::Metrics* metrics) const override {}
106
107 private:
108 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
109 };
110
111 // Class for testing that the render data is properly received by the block
112 // processor.
113 class RenderTransportVerificationProcessor : public BlockProcessor {
114 public:
RenderTransportVerificationProcessor(size_t num_bands)115 explicit RenderTransportVerificationProcessor(size_t num_bands) {}
116 ~RenderTransportVerificationProcessor() override = default;
117
ProcessCapture(bool level_change,bool saturated_microphone_signal,std::vector<std::vector<float>> * capture_block)118 void ProcessCapture(bool level_change,
119 bool saturated_microphone_signal,
120 std::vector<std::vector<float>>* capture_block) override {
121 std::vector<std::vector<float>> render_block =
122 received_render_blocks_.front();
123 received_render_blocks_.pop_front();
124 capture_block->swap(render_block);
125 }
126
BufferRender(const std::vector<std::vector<float>> & block)127 void BufferRender(const std::vector<std::vector<float>>& block) override {
128 received_render_blocks_.push_back(block);
129 }
130
UpdateEchoLeakageStatus(bool leakage_detected)131 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
132
GetMetrics(EchoControl::Metrics * metrics) const133 void GetMetrics(EchoControl::Metrics* metrics) const override {}
134
135 private:
136 std::deque<std::vector<std::vector<float>>> received_render_blocks_;
137 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor);
138 };
139
140 class EchoCanceller3Tester {
141 public:
EchoCanceller3Tester(int sample_rate_hz)142 explicit EchoCanceller3Tester(int sample_rate_hz)
143 : sample_rate_hz_(sample_rate_hz),
144 num_bands_(NumBandsForRate(sample_rate_hz_)),
145 frame_length_(sample_rate_hz_ == 8000 ? 80 : 160),
146 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)),
147 capture_buffer_(fullband_frame_length_,
148 1,
149 fullband_frame_length_,
150 1,
151 fullband_frame_length_),
152 render_buffer_(fullband_frame_length_,
153 1,
154 fullband_frame_length_,
155 1,
156 fullband_frame_length_) {}
157
158 // Verifies that the capture data is properly received by the block processor
159 // and that the processor data is properly passed to the EchoCanceller3
160 // output.
RunCaptureTransportVerificationTest()161 void RunCaptureTransportVerificationTest() {
162 EchoCanceller3 aec3(
163 sample_rate_hz_, false,
164 std::unique_ptr<BlockProcessor>(
165 new CaptureTransportVerificationProcessor(num_bands_)));
166
167 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
168 ++frame_index) {
169 aec3.AnalyzeCapture(&capture_buffer_);
170 OptionalBandSplit();
171 PopulateInputFrame(frame_length_, num_bands_, frame_index,
172 &capture_buffer_.split_bands_f(0)[0], 0);
173 PopulateInputFrame(frame_length_, frame_index,
174 &render_buffer_.channels_f()[0][0], 0);
175
176 aec3.AnalyzeRender(&render_buffer_);
177 aec3.ProcessCapture(&capture_buffer_, false);
178 EXPECT_TRUE(VerifyOutputFrameBitexactness(
179 frame_length_, num_bands_, frame_index,
180 &capture_buffer_.split_bands_f(0)[0], -64));
181 }
182 }
183
184 // Test method for testing that the render data is properly received by the
185 // block processor.
RunRenderTransportVerificationTest()186 void RunRenderTransportVerificationTest() {
187 EchoCanceller3 aec3(
188 sample_rate_hz_, false,
189 std::unique_ptr<BlockProcessor>(
190 new RenderTransportVerificationProcessor(num_bands_)));
191
192 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
193 ++frame_index) {
194 aec3.AnalyzeCapture(&capture_buffer_);
195 OptionalBandSplit();
196 PopulateInputFrame(frame_length_, num_bands_, frame_index,
197 &capture_buffer_.split_bands_f(0)[0], 100);
198 PopulateInputFrame(frame_length_, num_bands_, frame_index,
199 &render_buffer_.split_bands_f(0)[0], 0);
200
201 aec3.AnalyzeRender(&render_buffer_);
202 aec3.ProcessCapture(&capture_buffer_, false);
203 EXPECT_TRUE(VerifyOutputFrameBitexactness(
204 frame_length_, num_bands_, frame_index,
205 &capture_buffer_.split_bands_f(0)[0], -64));
206 }
207 }
208
209 // Verifies that information about echo path changes are properly propagated
210 // to the block processor.
211 // The cases tested are:
212 // -That no set echo path change flags are received when there is no echo path
213 // change.
214 // -That set echo path change flags are received and continues to be received
215 // as long as echo path changes are flagged.
216 // -That set echo path change flags are no longer received when echo path
217 // change events stop being flagged.
218 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky };
219
RunEchoPathChangeVerificationTest(EchoPathChangeTestVariant echo_path_change_test_variant)220 void RunEchoPathChangeVerificationTest(
221 EchoPathChangeTestVariant echo_path_change_test_variant) {
222 const size_t num_full_blocks_per_frame =
223 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
224 const size_t expected_num_block_to_process =
225 (kNumFramesToProcess *
226 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
227 kBlockSize;
228 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
229 block_processor_mock(
230 new StrictMock<webrtc::test::MockBlockProcessor>());
231 EXPECT_CALL(*block_processor_mock, BufferRender(_))
232 .Times(expected_num_block_to_process);
233 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
234
235 switch (echo_path_change_test_variant) {
236 case EchoPathChangeTestVariant::kNone:
237 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
238 .Times(expected_num_block_to_process);
239 break;
240 case EchoPathChangeTestVariant::kOneSticky:
241 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
242 .Times(expected_num_block_to_process);
243 break;
244 case EchoPathChangeTestVariant::kOneNonSticky:
245 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
246 .Times(num_full_blocks_per_frame);
247 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
248 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
249 break;
250 }
251
252 EchoCanceller3 aec3(sample_rate_hz_, false,
253 std::move(block_processor_mock));
254
255 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
256 ++frame_index) {
257 bool echo_path_change = false;
258 switch (echo_path_change_test_variant) {
259 case EchoPathChangeTestVariant::kNone:
260 break;
261 case EchoPathChangeTestVariant::kOneSticky:
262 echo_path_change = true;
263 break;
264 case EchoPathChangeTestVariant::kOneNonSticky:
265 if (frame_index == 0) {
266 echo_path_change = true;
267 }
268 break;
269 }
270
271 aec3.AnalyzeCapture(&capture_buffer_);
272 OptionalBandSplit();
273
274 PopulateInputFrame(frame_length_, num_bands_, frame_index,
275 &capture_buffer_.split_bands_f(0)[0], 0);
276 PopulateInputFrame(frame_length_, frame_index,
277 &render_buffer_.channels_f()[0][0], 0);
278
279 aec3.AnalyzeRender(&render_buffer_);
280 aec3.ProcessCapture(&capture_buffer_, echo_path_change);
281 }
282 }
283
284 // Test for verifying that echo leakage information is being properly passed
285 // to the processor.
286 // The cases tested are:
287 // -That no method calls are received when they should not.
288 // -That false values are received each time they are flagged.
289 // -That true values are received each time they are flagged.
290 // -That a false value is received when flagged after a true value has been
291 // flagged.
292 enum class EchoLeakageTestVariant {
293 kNone,
294 kFalseSticky,
295 kTrueSticky,
296 kTrueNonSticky
297 };
298
RunEchoLeakageVerificationTest(EchoLeakageTestVariant leakage_report_variant)299 void RunEchoLeakageVerificationTest(
300 EchoLeakageTestVariant leakage_report_variant) {
301 const size_t expected_num_block_to_process =
302 (kNumFramesToProcess *
303 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
304 kBlockSize;
305 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
306 block_processor_mock(
307 new StrictMock<webrtc::test::MockBlockProcessor>());
308 EXPECT_CALL(*block_processor_mock, BufferRender(_))
309 .Times(expected_num_block_to_process);
310 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _))
311 .Times(expected_num_block_to_process);
312
313 switch (leakage_report_variant) {
314 case EchoLeakageTestVariant::kNone:
315 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
316 break;
317 case EchoLeakageTestVariant::kFalseSticky:
318 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
319 .Times(1);
320 break;
321 case EchoLeakageTestVariant::kTrueSticky:
322 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
323 .Times(1);
324 break;
325 case EchoLeakageTestVariant::kTrueNonSticky: {
326 testing::InSequence s;
327 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
328 .Times(1);
329 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
330 .Times(kNumFramesToProcess - 1);
331 } break;
332 }
333
334 EchoCanceller3 aec3(sample_rate_hz_, false,
335 std::move(block_processor_mock));
336
337 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
338 ++frame_index) {
339 switch (leakage_report_variant) {
340 case EchoLeakageTestVariant::kNone:
341 break;
342 case EchoLeakageTestVariant::kFalseSticky:
343 if (frame_index == 0) {
344 aec3.UpdateEchoLeakageStatus(false);
345 }
346 break;
347 case EchoLeakageTestVariant::kTrueSticky:
348 if (frame_index == 0) {
349 aec3.UpdateEchoLeakageStatus(true);
350 }
351 break;
352 case EchoLeakageTestVariant::kTrueNonSticky:
353 if (frame_index == 0) {
354 aec3.UpdateEchoLeakageStatus(true);
355 } else {
356 aec3.UpdateEchoLeakageStatus(false);
357 }
358 break;
359 }
360
361 aec3.AnalyzeCapture(&capture_buffer_);
362 OptionalBandSplit();
363
364 PopulateInputFrame(frame_length_, num_bands_, frame_index,
365 &capture_buffer_.split_bands_f(0)[0], 0);
366 PopulateInputFrame(frame_length_, frame_index,
367 &render_buffer_.channels_f()[0][0], 0);
368
369 aec3.AnalyzeRender(&render_buffer_);
370 aec3.ProcessCapture(&capture_buffer_, false);
371 }
372 }
373
374 // This verifies that saturation information is properly passed to the
375 // BlockProcessor.
376 // The cases tested are:
377 // -That no saturation event is passed to the processor if there is no
378 // saturation.
379 // -That one frame with one negative saturated sample value is reported to be
380 // saturated and that following non-saturated frames are properly reported as
381 // not being saturated.
382 // -That one frame with one positive saturated sample value is reported to be
383 // saturated and that following non-saturated frames are properly reported as
384 // not being saturated.
385 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive };
386
RunCaptureSaturationVerificationTest(SaturationTestVariant saturation_variant)387 void RunCaptureSaturationVerificationTest(
388 SaturationTestVariant saturation_variant) {
389 const size_t num_full_blocks_per_frame =
390 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
391 const size_t expected_num_block_to_process =
392 (kNumFramesToProcess *
393 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
394 kBlockSize;
395 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
396 block_processor_mock(
397 new StrictMock<webrtc::test::MockBlockProcessor>());
398 EXPECT_CALL(*block_processor_mock, BufferRender(_))
399 .Times(expected_num_block_to_process);
400 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
401
402 switch (saturation_variant) {
403 case SaturationTestVariant::kNone:
404 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
405 .Times(expected_num_block_to_process);
406 break;
407 case SaturationTestVariant::kOneNegative: {
408 testing::InSequence s;
409 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
410 .Times(num_full_blocks_per_frame);
411 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
412 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
413 } break;
414 case SaturationTestVariant::kOnePositive: {
415 testing::InSequence s;
416 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
417 .Times(num_full_blocks_per_frame);
418 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
419 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
420 } break;
421 }
422
423 EchoCanceller3 aec3(sample_rate_hz_, false,
424 std::move(block_processor_mock));
425 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
426 ++frame_index) {
427 for (int k = 0; k < fullband_frame_length_; ++k) {
428 capture_buffer_.channels_f()[0][k] = 0.f;
429 }
430 switch (saturation_variant) {
431 case SaturationTestVariant::kNone:
432 break;
433 case SaturationTestVariant::kOneNegative:
434 if (frame_index == 0) {
435 capture_buffer_.channels_f()[0][10] = -32768.f;
436 }
437 break;
438 case SaturationTestVariant::kOnePositive:
439 if (frame_index == 0) {
440 capture_buffer_.channels_f()[0][10] = 32767.f;
441 }
442 break;
443 }
444
445 aec3.AnalyzeCapture(&capture_buffer_);
446 OptionalBandSplit();
447
448 PopulateInputFrame(frame_length_, num_bands_, frame_index,
449 &capture_buffer_.split_bands_f(0)[0], 0);
450 PopulateInputFrame(frame_length_, num_bands_, frame_index,
451 &render_buffer_.split_bands_f(0)[0], 0);
452
453 aec3.AnalyzeRender(&render_buffer_);
454 aec3.ProcessCapture(&capture_buffer_, false);
455 }
456 }
457
458 // This test verifies that the swapqueue is able to handle jitter in the
459 // capture and render API calls.
RunRenderSwapQueueVerificationTest()460 void RunRenderSwapQueueVerificationTest() {
461 EchoCanceller3 aec3(
462 sample_rate_hz_, false,
463 std::unique_ptr<BlockProcessor>(
464 new RenderTransportVerificationProcessor(num_bands_)));
465
466 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
467 ++frame_index) {
468 if (sample_rate_hz_ > 16000) {
469 render_buffer_.SplitIntoFrequencyBands();
470 }
471 PopulateInputFrame(frame_length_, num_bands_, frame_index,
472 &render_buffer_.split_bands_f(0)[0], 0);
473
474 if (sample_rate_hz_ > 16000) {
475 render_buffer_.SplitIntoFrequencyBands();
476 }
477
478 aec3.AnalyzeRender(&render_buffer_);
479 }
480
481 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
482 ++frame_index) {
483 aec3.AnalyzeCapture(&capture_buffer_);
484 if (sample_rate_hz_ > 16000) {
485 capture_buffer_.SplitIntoFrequencyBands();
486 }
487
488 PopulateInputFrame(frame_length_, num_bands_, frame_index,
489 &capture_buffer_.split_bands_f(0)[0], 0);
490
491 aec3.ProcessCapture(&capture_buffer_, false);
492 EXPECT_TRUE(VerifyOutputFrameBitexactness(
493 frame_length_, num_bands_, frame_index,
494 &capture_buffer_.split_bands_f(0)[0], -64));
495 }
496 }
497
498 // This test verifies that a buffer overrun in the render swapqueue is
499 // properly reported.
RunRenderPipelineSwapQueueOverrunReturnValueTest()500 void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
501 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false);
502
503 constexpr size_t kRenderTransferQueueSize = 30;
504 for (size_t k = 0; k < 2; ++k) {
505 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
506 ++frame_index) {
507 if (sample_rate_hz_ > 16000) {
508 render_buffer_.SplitIntoFrequencyBands();
509 }
510 PopulateInputFrame(frame_length_, frame_index,
511 &render_buffer_.channels_f()[0][0], 0);
512
513 if (k == 0) {
514 aec3.AnalyzeRender(&render_buffer_);
515 } else {
516 aec3.AnalyzeRender(&render_buffer_);
517 }
518 }
519 }
520 }
521
522 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
523 // Verifies the that the check for the number of bands in the AnalyzeRender
524 // input is correct by adjusting the sample rates of EchoCanceller3 and the
525 // input AudioBuffer to have a different number of bands.
RunAnalyzeRenderNumBandsCheckVerification()526 void RunAnalyzeRenderNumBandsCheckVerification() {
527 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
528 // way that the number of bands for the rates are different.
529 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
530 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
531 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
532
533 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
534 }
535
536 // Verifies the that the check for the number of bands in the ProcessCapture
537 // input is correct by adjusting the sample rates of EchoCanceller3 and the
538 // input AudioBuffer to have a different number of bands.
RunProcessCaptureNumBandsCheckVerification()539 void RunProcessCaptureNumBandsCheckVerification() {
540 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
541 // way that the number of bands for the rates are different.
542 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
543 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
544 PopulateInputFrame(frame_length_, num_bands_, 0,
545 &capture_buffer_.split_bands_f(0)[0], 100);
546 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
547 }
548
549 // Verifies the that the check for the frame length in the AnalyzeRender input
550 // is correct by adjusting the sample rates of EchoCanceller3 and the input
551 // AudioBuffer to have a different frame lengths.
RunAnalyzeRenderFrameLengthCheckVerification()552 void RunAnalyzeRenderFrameLengthCheckVerification() {
553 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
554 // way that the band frame lengths are different.
555 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
556 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
557
558 OptionalBandSplit();
559 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
560
561 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
562 }
563
564 // Verifies the that the check for the frame length in the AnalyzeRender input
565 // is correct by adjusting the sample rates of EchoCanceller3 and the input
566 // AudioBuffer to have a different frame lengths.
RunProcessCaptureFrameLengthCheckVerification()567 void RunProcessCaptureFrameLengthCheckVerification() {
568 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
569 // way that the band frame lengths are different.
570 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
571 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
572
573 OptionalBandSplit();
574 PopulateInputFrame(frame_length_, num_bands_, 0,
575 &capture_buffer_.split_bands_f(0)[0], 100);
576
577 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
578 }
579
580 #endif
581
582 private:
OptionalBandSplit()583 void OptionalBandSplit() {
584 if (sample_rate_hz_ > 16000) {
585 capture_buffer_.SplitIntoFrequencyBands();
586 render_buffer_.SplitIntoFrequencyBands();
587 }
588 }
589
590 static constexpr size_t kNumFramesToProcess = 20;
591 const int sample_rate_hz_;
592 const size_t num_bands_;
593 const size_t frame_length_;
594 const int fullband_frame_length_;
595 AudioBuffer capture_buffer_;
596 AudioBuffer render_buffer_;
597
598 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester);
599 };
600
ProduceDebugText(int sample_rate_hz)601 std::string ProduceDebugText(int sample_rate_hz) {
602 std::ostringstream ss;
603 ss << "Sample rate: " << sample_rate_hz;
604 return ss.str();
605 }
606
ProduceDebugText(int sample_rate_hz,int variant)607 std::string ProduceDebugText(int sample_rate_hz, int variant) {
608 std::ostringstream ss;
609 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant;
610 return ss.str();
611 }
612
613 } // namespace
614
TEST(EchoCanceller3Buffering,CaptureBitexactness)615 TEST(EchoCanceller3Buffering, CaptureBitexactness) {
616 for (auto rate : {8000, 16000, 32000, 48000}) {
617 SCOPED_TRACE(ProduceDebugText(rate));
618 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest();
619 }
620 }
621
TEST(EchoCanceller3Buffering,RenderBitexactness)622 TEST(EchoCanceller3Buffering, RenderBitexactness) {
623 for (auto rate : {8000, 16000, 32000, 48000}) {
624 SCOPED_TRACE(ProduceDebugText(rate));
625 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest();
626 }
627 }
628
TEST(EchoCanceller3Buffering,RenderSwapQueue)629 TEST(EchoCanceller3Buffering, RenderSwapQueue) {
630 for (auto rate : {8000, 16000}) {
631 SCOPED_TRACE(ProduceDebugText(rate));
632 EchoCanceller3Tester(rate).RunRenderSwapQueueVerificationTest();
633 }
634 }
635
TEST(EchoCanceller3Buffering,RenderSwapQueueOverrunReturnValue)636 TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) {
637 for (auto rate : {8000, 16000, 32000, 48000}) {
638 SCOPED_TRACE(ProduceDebugText(rate));
639 EchoCanceller3Tester(rate)
640 .RunRenderPipelineSwapQueueOverrunReturnValueTest();
641 }
642 }
643
TEST(EchoCanceller3Messaging,CaptureSaturation)644 TEST(EchoCanceller3Messaging, CaptureSaturation) {
645 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone,
646 EchoCanceller3Tester::SaturationTestVariant::kOneNegative,
647 EchoCanceller3Tester::SaturationTestVariant::kOnePositive};
648 for (auto rate : {8000, 16000, 32000, 48000}) {
649 for (auto variant : variants) {
650 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
651 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant);
652 }
653 }
654 }
655
TEST(EchoCanceller3Messaging,EchoPathChange)656 TEST(EchoCanceller3Messaging, EchoPathChange) {
657 auto variants = {
658 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone,
659 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky,
660 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky};
661 for (auto rate : {8000, 16000, 32000, 48000}) {
662 for (auto variant : variants) {
663 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
664 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant);
665 }
666 }
667 }
668
TEST(EchoCanceller3Messaging,EchoLeakage)669 TEST(EchoCanceller3Messaging, EchoLeakage) {
670 auto variants = {
671 EchoCanceller3Tester::EchoLeakageTestVariant::kNone,
672 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky,
673 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky,
674 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky};
675 for (auto rate : {8000, 16000, 32000, 48000}) {
676 for (auto variant : variants) {
677 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
678 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant);
679 }
680 }
681 }
682
TEST(EchoCanceller3,ConfigValidation)683 TEST(EchoCanceller3, ConfigValidation) {
684 EchoCanceller3Config config;
685 EXPECT_TRUE(EchoCanceller3::Validate(config));
686 }
687
688 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
689
TEST(EchoCanceller3InputCheck,WrongCaptureNumBandsCheckVerification)690 TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) {
691 for (auto rate : {8000, 16000, 32000, 48000}) {
692 SCOPED_TRACE(ProduceDebugText(rate));
693 EchoCanceller3Tester(rate).RunProcessCaptureNumBandsCheckVerification();
694 }
695 }
696
697 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
698 // tests on test bots has been fixed.
TEST(EchoCanceller3InputCheck,DISABLED_WrongRenderFrameLengthCheckVerification)699 TEST(EchoCanceller3InputCheck,
700 DISABLED_WrongRenderFrameLengthCheckVerification) {
701 for (auto rate : {8000, 16000}) {
702 SCOPED_TRACE(ProduceDebugText(rate));
703 EchoCanceller3Tester(rate).RunAnalyzeRenderFrameLengthCheckVerification();
704 }
705 }
706
TEST(EchoCanceller3InputCheck,WrongCaptureFrameLengthCheckVerification)707 TEST(EchoCanceller3InputCheck, WrongCaptureFrameLengthCheckVerification) {
708 for (auto rate : {8000, 16000}) {
709 SCOPED_TRACE(ProduceDebugText(rate));
710 EchoCanceller3Tester(rate).RunProcessCaptureFrameLengthCheckVerification();
711 }
712 }
713
714 // Verifiers that the verification for null input to the render analysis api
715 // call works.
TEST(EchoCanceller3InputCheck,NullRenderAnalysisParameter)716 TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) {
717 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
718 .AnalyzeRender(nullptr),
719 "");
720 }
721
722 // Verifiers that the verification for null input to the capture analysis api
723 // call works.
TEST(EchoCanceller3InputCheck,NullCaptureAnalysisParameter)724 TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) {
725 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
726 .AnalyzeCapture(nullptr),
727 "");
728 }
729
730 // Verifiers that the verification for null input to the capture processing api
731 // call works.
TEST(EchoCanceller3InputCheck,NullCaptureProcessingParameter)732 TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
733 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
734 .ProcessCapture(nullptr, false),
735 "");
736 }
737
738 // Verifies the check for correct sample rate.
739 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
740 // tests on test bots has been fixed.
TEST(EchoCanceller3InputCheck,DISABLED_WrongSampleRate)741 TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
742 ApmDataDumper data_dumper(0);
743 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8001, false), "");
744 }
745
746 #endif
747
748 } // namespace webrtc
749