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 <string>
16 #include <utility>
17 #include <vector>
18
19 #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"
24 #include "modules/audio_processing/high_pass_filter.h"
25 #include "modules/audio_processing/utility/cascaded_biquad_filter.h"
26 #include "rtc_base/strings/string_builder.h"
27 #include "test/field_trial.h"
28 #include "test/gmock.h"
29 #include "test/gtest.h"
30
31 namespace webrtc {
32 namespace {
33
34 using ::testing::_;
35 using ::testing::StrictMock;
36
37 // Populates the frame with linearly increasing sample values for each band,
38 // with a band-specific offset, in order to allow simple bitexactness
39 // verification for each band.
PopulateInputFrame(size_t frame_length,size_t num_bands,size_t frame_index,float * const * frame,int offset)40 void PopulateInputFrame(size_t frame_length,
41 size_t num_bands,
42 size_t frame_index,
43 float* const* frame,
44 int offset) {
45 for (size_t k = 0; k < num_bands; ++k) {
46 for (size_t i = 0; i < frame_length; ++i) {
47 float value = static_cast<int>(frame_index * frame_length + i) + offset;
48 frame[k][i] = (value > 0 ? 5000 * k + value : 0);
49 }
50 }
51 }
52
53 // Populates the frame with linearly increasing sample values.
PopulateInputFrame(size_t frame_length,size_t frame_index,float * frame,int offset)54 void PopulateInputFrame(size_t frame_length,
55 size_t frame_index,
56 float* frame,
57 int offset) {
58 for (size_t i = 0; i < frame_length; ++i) {
59 float value = static_cast<int>(frame_index * frame_length + i) + offset;
60 frame[i] = std::max(value, 0.f);
61 }
62 }
63
64 // Verifies the that samples in the output frame are identical to the samples
65 // that were produced for the input frame, with an offset in order to compensate
66 // for buffering delays.
VerifyOutputFrameBitexactness(size_t frame_length,size_t num_bands,size_t frame_index,const float * const * frame,int offset)67 bool VerifyOutputFrameBitexactness(size_t frame_length,
68 size_t num_bands,
69 size_t frame_index,
70 const float* const* frame,
71 int offset) {
72 float reference_frame_data[kMaxNumBands][2 * kSubFrameLength];
73 float* reference_frame[kMaxNumBands];
74 for (size_t k = 0; k < num_bands; ++k) {
75 reference_frame[k] = &reference_frame_data[k][0];
76 }
77
78 PopulateInputFrame(frame_length, num_bands, frame_index, reference_frame,
79 offset);
80 for (size_t k = 0; k < num_bands; ++k) {
81 for (size_t i = 0; i < frame_length; ++i) {
82 if (reference_frame[k][i] != frame[k][i]) {
83 return false;
84 }
85 }
86 }
87
88 return true;
89 }
90
VerifyOutputFrameBitexactness(rtc::ArrayView<const float> reference,rtc::ArrayView<const float> frame,int offset)91 bool VerifyOutputFrameBitexactness(rtc::ArrayView<const float> reference,
92 rtc::ArrayView<const float> frame,
93 int offset) {
94 for (size_t k = 0; k < frame.size(); ++k) {
95 int reference_index = static_cast<int>(k) + offset;
96 if (reference_index >= 0) {
97 if (reference[reference_index] != frame[k]) {
98 return false;
99 }
100 }
101 }
102 return true;
103 }
104
105 // Class for testing that the capture data is properly received by the block
106 // processor and that the processor data is properly passed to the
107 // EchoCanceller3 output.
108 class CaptureTransportVerificationProcessor : public BlockProcessor {
109 public:
CaptureTransportVerificationProcessor(size_t num_bands)110 explicit CaptureTransportVerificationProcessor(size_t num_bands) {}
111 ~CaptureTransportVerificationProcessor() override = default;
112
ProcessCapture(bool level_change,bool saturated_microphone_signal,std::vector<std::vector<std::vector<float>>> * linear_output,std::vector<std::vector<std::vector<float>>> * capture_block)113 void ProcessCapture(
114 bool level_change,
115 bool saturated_microphone_signal,
116 std::vector<std::vector<std::vector<float>>>* linear_output,
117 std::vector<std::vector<std::vector<float>>>* capture_block) override {}
118
BufferRender(const std::vector<std::vector<std::vector<float>>> & block)119 void BufferRender(
120 const std::vector<std::vector<std::vector<float>>>& block) override {}
121
UpdateEchoLeakageStatus(bool leakage_detected)122 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
123
GetMetrics(EchoControl::Metrics * metrics) const124 void GetMetrics(EchoControl::Metrics* metrics) const override {}
125
SetAudioBufferDelay(int delay_ms)126 void SetAudioBufferDelay(int delay_ms) override {}
127
128 private:
129 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
130 };
131
132 // Class for testing that the render data is properly received by the block
133 // processor.
134 class RenderTransportVerificationProcessor : public BlockProcessor {
135 public:
RenderTransportVerificationProcessor(size_t num_bands)136 explicit RenderTransportVerificationProcessor(size_t num_bands) {}
137 ~RenderTransportVerificationProcessor() override = default;
138
ProcessCapture(bool level_change,bool saturated_microphone_signal,std::vector<std::vector<std::vector<float>>> * linear_output,std::vector<std::vector<std::vector<float>>> * capture_block)139 void ProcessCapture(
140 bool level_change,
141 bool saturated_microphone_signal,
142 std::vector<std::vector<std::vector<float>>>* linear_output,
143 std::vector<std::vector<std::vector<float>>>* capture_block) override {
144 std::vector<std::vector<std::vector<float>>> render_block =
145 received_render_blocks_.front();
146 received_render_blocks_.pop_front();
147 capture_block->swap(render_block);
148 }
149
BufferRender(const std::vector<std::vector<std::vector<float>>> & block)150 void BufferRender(
151 const std::vector<std::vector<std::vector<float>>>& block) override {
152 received_render_blocks_.push_back(block);
153 }
154
UpdateEchoLeakageStatus(bool leakage_detected)155 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
156
GetMetrics(EchoControl::Metrics * metrics) const157 void GetMetrics(EchoControl::Metrics* metrics) const override {}
158
SetAudioBufferDelay(int delay_ms)159 void SetAudioBufferDelay(int delay_ms) override {}
160
161 private:
162 std::deque<std::vector<std::vector<std::vector<float>>>>
163 received_render_blocks_;
164 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor);
165 };
166
167 class EchoCanceller3Tester {
168 public:
EchoCanceller3Tester(int sample_rate_hz)169 explicit EchoCanceller3Tester(int sample_rate_hz)
170 : sample_rate_hz_(sample_rate_hz),
171 num_bands_(NumBandsForRate(sample_rate_hz_)),
172 frame_length_(160),
173 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)),
174 capture_buffer_(fullband_frame_length_ * 100,
175 1,
176 fullband_frame_length_ * 100,
177 1,
178 fullband_frame_length_ * 100,
179 1),
180 render_buffer_(fullband_frame_length_ * 100,
181 1,
182 fullband_frame_length_ * 100,
183 1,
184 fullband_frame_length_ * 100,
185 1) {}
186
187 // Verifies that the capture data is properly received by the block processor
188 // and that the processor data is properly passed to the EchoCanceller3
189 // output.
RunCaptureTransportVerificationTest()190 void RunCaptureTransportVerificationTest() {
191 EchoCanceller3 aec3(
192 EchoCanceller3Config(), sample_rate_hz_, 1, 1,
193 std::unique_ptr<BlockProcessor>(
194 new CaptureTransportVerificationProcessor(num_bands_)));
195
196 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
197 ++frame_index) {
198 aec3.AnalyzeCapture(&capture_buffer_);
199 OptionalBandSplit();
200 PopulateInputFrame(frame_length_, num_bands_, frame_index,
201 &capture_buffer_.split_bands(0)[0], 0);
202 PopulateInputFrame(frame_length_, frame_index,
203 &render_buffer_.channels()[0][0], 0);
204
205 aec3.AnalyzeRender(&render_buffer_);
206 aec3.ProcessCapture(&capture_buffer_, false);
207 EXPECT_TRUE(VerifyOutputFrameBitexactness(
208 frame_length_, num_bands_, frame_index,
209 &capture_buffer_.split_bands(0)[0], -64));
210 }
211 }
212
213 // Test method for testing that the render data is properly received by the
214 // block processor.
RunRenderTransportVerificationTest()215 void RunRenderTransportVerificationTest() {
216 EchoCanceller3 aec3(
217 EchoCanceller3Config(), sample_rate_hz_, 1, 1,
218 std::unique_ptr<BlockProcessor>(
219 new RenderTransportVerificationProcessor(num_bands_)));
220
221 std::vector<std::vector<float>> render_input(1);
222 std::vector<float> capture_output;
223 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
224 ++frame_index) {
225 aec3.AnalyzeCapture(&capture_buffer_);
226 OptionalBandSplit();
227 PopulateInputFrame(frame_length_, num_bands_, frame_index,
228 &capture_buffer_.split_bands(0)[0], 100);
229 PopulateInputFrame(frame_length_, num_bands_, frame_index,
230 &render_buffer_.split_bands(0)[0], 0);
231
232 for (size_t k = 0; k < frame_length_; ++k) {
233 render_input[0].push_back(render_buffer_.split_bands(0)[0][k]);
234 }
235 aec3.AnalyzeRender(&render_buffer_);
236 aec3.ProcessCapture(&capture_buffer_, false);
237 for (size_t k = 0; k < frame_length_; ++k) {
238 capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
239 }
240 }
241 HighPassFilter hp_filter(16000, 1);
242 hp_filter.Process(&render_input);
243
244 EXPECT_TRUE(
245 VerifyOutputFrameBitexactness(render_input[0], capture_output, -64));
246 }
247
248 // Verifies that information about echo path changes are properly propagated
249 // to the block processor.
250 // The cases tested are:
251 // -That no set echo path change flags are received when there is no echo path
252 // change.
253 // -That set echo path change flags are received and continues to be received
254 // as long as echo path changes are flagged.
255 // -That set echo path change flags are no longer received when echo path
256 // change events stop being flagged.
257 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky };
258
RunEchoPathChangeVerificationTest(EchoPathChangeTestVariant echo_path_change_test_variant)259 void RunEchoPathChangeVerificationTest(
260 EchoPathChangeTestVariant echo_path_change_test_variant) {
261 constexpr size_t kNumFullBlocksPerFrame = 160 / kBlockSize;
262 constexpr size_t kExpectedNumBlocksToProcess =
263 (kNumFramesToProcess * 160) / kBlockSize;
264 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
265 block_processor_mock(
266 new StrictMock<webrtc::test::MockBlockProcessor>());
267 EXPECT_CALL(*block_processor_mock, BufferRender(_))
268 .Times(kExpectedNumBlocksToProcess);
269 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
270
271 switch (echo_path_change_test_variant) {
272 case EchoPathChangeTestVariant::kNone:
273 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _, _))
274 .Times(kExpectedNumBlocksToProcess);
275 break;
276 case EchoPathChangeTestVariant::kOneSticky:
277 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _, _))
278 .Times(kExpectedNumBlocksToProcess);
279 break;
280 case EchoPathChangeTestVariant::kOneNonSticky:
281 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _, _))
282 .Times(kNumFullBlocksPerFrame);
283 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _, _))
284 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
285 break;
286 }
287
288 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1,
289 std::move(block_processor_mock));
290
291 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
292 ++frame_index) {
293 bool echo_path_change = false;
294 switch (echo_path_change_test_variant) {
295 case EchoPathChangeTestVariant::kNone:
296 break;
297 case EchoPathChangeTestVariant::kOneSticky:
298 echo_path_change = true;
299 break;
300 case EchoPathChangeTestVariant::kOneNonSticky:
301 if (frame_index == 0) {
302 echo_path_change = true;
303 }
304 break;
305 }
306
307 aec3.AnalyzeCapture(&capture_buffer_);
308 OptionalBandSplit();
309
310 PopulateInputFrame(frame_length_, num_bands_, frame_index,
311 &capture_buffer_.split_bands(0)[0], 0);
312 PopulateInputFrame(frame_length_, frame_index,
313 &render_buffer_.channels()[0][0], 0);
314
315 aec3.AnalyzeRender(&render_buffer_);
316 aec3.ProcessCapture(&capture_buffer_, echo_path_change);
317 }
318 }
319
320 // Test for verifying that echo leakage information is being properly passed
321 // to the processor.
322 // The cases tested are:
323 // -That no method calls are received when they should not.
324 // -That false values are received each time they are flagged.
325 // -That true values are received each time they are flagged.
326 // -That a false value is received when flagged after a true value has been
327 // flagged.
328 enum class EchoLeakageTestVariant {
329 kNone,
330 kFalseSticky,
331 kTrueSticky,
332 kTrueNonSticky
333 };
334
RunEchoLeakageVerificationTest(EchoLeakageTestVariant leakage_report_variant)335 void RunEchoLeakageVerificationTest(
336 EchoLeakageTestVariant leakage_report_variant) {
337 constexpr size_t kExpectedNumBlocksToProcess =
338 (kNumFramesToProcess * 160) / kBlockSize;
339 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
340 block_processor_mock(
341 new StrictMock<webrtc::test::MockBlockProcessor>());
342 EXPECT_CALL(*block_processor_mock, BufferRender(_))
343 .Times(kExpectedNumBlocksToProcess);
344 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _, _))
345 .Times(kExpectedNumBlocksToProcess);
346
347 switch (leakage_report_variant) {
348 case EchoLeakageTestVariant::kNone:
349 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
350 break;
351 case EchoLeakageTestVariant::kFalseSticky:
352 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
353 .Times(1);
354 break;
355 case EchoLeakageTestVariant::kTrueSticky:
356 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
357 .Times(1);
358 break;
359 case EchoLeakageTestVariant::kTrueNonSticky: {
360 ::testing::InSequence s;
361 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
362 .Times(1);
363 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
364 .Times(kNumFramesToProcess - 1);
365 } break;
366 }
367
368 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1,
369 std::move(block_processor_mock));
370
371 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
372 ++frame_index) {
373 switch (leakage_report_variant) {
374 case EchoLeakageTestVariant::kNone:
375 break;
376 case EchoLeakageTestVariant::kFalseSticky:
377 if (frame_index == 0) {
378 aec3.UpdateEchoLeakageStatus(false);
379 }
380 break;
381 case EchoLeakageTestVariant::kTrueSticky:
382 if (frame_index == 0) {
383 aec3.UpdateEchoLeakageStatus(true);
384 }
385 break;
386 case EchoLeakageTestVariant::kTrueNonSticky:
387 if (frame_index == 0) {
388 aec3.UpdateEchoLeakageStatus(true);
389 } else {
390 aec3.UpdateEchoLeakageStatus(false);
391 }
392 break;
393 }
394
395 aec3.AnalyzeCapture(&capture_buffer_);
396 OptionalBandSplit();
397
398 PopulateInputFrame(frame_length_, num_bands_, frame_index,
399 &capture_buffer_.split_bands(0)[0], 0);
400 PopulateInputFrame(frame_length_, frame_index,
401 &render_buffer_.channels()[0][0], 0);
402
403 aec3.AnalyzeRender(&render_buffer_);
404 aec3.ProcessCapture(&capture_buffer_, false);
405 }
406 }
407
408 // This verifies that saturation information is properly passed to the
409 // BlockProcessor.
410 // The cases tested are:
411 // -That no saturation event is passed to the processor if there is no
412 // saturation.
413 // -That one frame with one negative saturated sample value is reported to be
414 // saturated and that following non-saturated frames are properly reported as
415 // not being saturated.
416 // -That one frame with one positive saturated sample value is reported to be
417 // saturated and that following non-saturated frames are properly reported as
418 // not being saturated.
419 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive };
420
RunCaptureSaturationVerificationTest(SaturationTestVariant saturation_variant)421 void RunCaptureSaturationVerificationTest(
422 SaturationTestVariant saturation_variant) {
423 const size_t kNumFullBlocksPerFrame = 160 / kBlockSize;
424 const size_t kExpectedNumBlocksToProcess =
425 (kNumFramesToProcess * 160) / kBlockSize;
426 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
427 block_processor_mock(
428 new StrictMock<webrtc::test::MockBlockProcessor>());
429 EXPECT_CALL(*block_processor_mock, BufferRender(_))
430 .Times(kExpectedNumBlocksToProcess);
431 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
432
433 switch (saturation_variant) {
434 case SaturationTestVariant::kNone:
435 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _, _))
436 .Times(kExpectedNumBlocksToProcess);
437 break;
438 case SaturationTestVariant::kOneNegative: {
439 ::testing::InSequence s;
440 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _, _))
441 .Times(kNumFullBlocksPerFrame);
442 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _, _))
443 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
444 } break;
445 case SaturationTestVariant::kOnePositive: {
446 ::testing::InSequence s;
447 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _, _))
448 .Times(kNumFullBlocksPerFrame);
449 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _, _))
450 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
451 } break;
452 }
453
454 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1,
455 std::move(block_processor_mock));
456 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
457 ++frame_index) {
458 for (int k = 0; k < fullband_frame_length_; ++k) {
459 capture_buffer_.channels()[0][k] = 0.f;
460 }
461 switch (saturation_variant) {
462 case SaturationTestVariant::kNone:
463 break;
464 case SaturationTestVariant::kOneNegative:
465 if (frame_index == 0) {
466 capture_buffer_.channels()[0][10] = -32768.f;
467 }
468 break;
469 case SaturationTestVariant::kOnePositive:
470 if (frame_index == 0) {
471 capture_buffer_.channels()[0][10] = 32767.f;
472 }
473 break;
474 }
475
476 aec3.AnalyzeCapture(&capture_buffer_);
477 OptionalBandSplit();
478
479 PopulateInputFrame(frame_length_, num_bands_, frame_index,
480 &capture_buffer_.split_bands(0)[0], 0);
481 PopulateInputFrame(frame_length_, num_bands_, frame_index,
482 &render_buffer_.split_bands(0)[0], 0);
483
484 aec3.AnalyzeRender(&render_buffer_);
485 aec3.ProcessCapture(&capture_buffer_, false);
486 }
487 }
488
489 // This test verifies that the swapqueue is able to handle jitter in the
490 // capture and render API calls.
RunRenderSwapQueueVerificationTest()491 void RunRenderSwapQueueVerificationTest() {
492 const EchoCanceller3Config config;
493 EchoCanceller3 aec3(
494 config, sample_rate_hz_, 1, 1,
495 std::unique_ptr<BlockProcessor>(
496 new RenderTransportVerificationProcessor(num_bands_)));
497
498 std::vector<std::vector<float>> render_input(1);
499 std::vector<float> capture_output;
500
501 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
502 ++frame_index) {
503 if (sample_rate_hz_ > 16000) {
504 render_buffer_.SplitIntoFrequencyBands();
505 }
506 PopulateInputFrame(frame_length_, num_bands_, frame_index,
507 &render_buffer_.split_bands(0)[0], 0);
508
509 if (sample_rate_hz_ > 16000) {
510 render_buffer_.SplitIntoFrequencyBands();
511 }
512
513 for (size_t k = 0; k < frame_length_; ++k) {
514 render_input[0].push_back(render_buffer_.split_bands(0)[0][k]);
515 }
516 aec3.AnalyzeRender(&render_buffer_);
517 }
518
519 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
520 ++frame_index) {
521 aec3.AnalyzeCapture(&capture_buffer_);
522 if (sample_rate_hz_ > 16000) {
523 capture_buffer_.SplitIntoFrequencyBands();
524 }
525
526 PopulateInputFrame(frame_length_, num_bands_, frame_index,
527 &capture_buffer_.split_bands(0)[0], 0);
528
529 aec3.ProcessCapture(&capture_buffer_, false);
530 for (size_t k = 0; k < frame_length_; ++k) {
531 capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
532 }
533 }
534 HighPassFilter hp_filter(16000, 1);
535 hp_filter.Process(&render_input);
536
537 EXPECT_TRUE(
538 VerifyOutputFrameBitexactness(render_input[0], capture_output, -64));
539 }
540
541 // This test verifies that a buffer overrun in the render swapqueue is
542 // properly reported.
RunRenderPipelineSwapQueueOverrunReturnValueTest()543 void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
544 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, 1, 1);
545
546 constexpr size_t kRenderTransferQueueSize = 30;
547 for (size_t k = 0; k < 2; ++k) {
548 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
549 ++frame_index) {
550 if (sample_rate_hz_ > 16000) {
551 render_buffer_.SplitIntoFrequencyBands();
552 }
553 PopulateInputFrame(frame_length_, frame_index,
554 &render_buffer_.channels()[0][0], 0);
555
556 aec3.AnalyzeRender(&render_buffer_);
557 }
558 }
559 }
560
561 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
562 // Verifies the that the check for the number of bands in the AnalyzeRender
563 // input is correct by adjusting the sample rates of EchoCanceller3 and the
564 // input AudioBuffer to have a different number of bands.
RunAnalyzeRenderNumBandsCheckVerification()565 void RunAnalyzeRenderNumBandsCheckVerification() {
566 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
567 // way that the number of bands for the rates are different.
568 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
569 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, 1, 1);
570 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
571
572 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
573 }
574
575 // Verifies the that the check for the number of bands in the ProcessCapture
576 // input is correct by adjusting the sample rates of EchoCanceller3 and the
577 // input AudioBuffer to have a different number of bands.
RunProcessCaptureNumBandsCheckVerification()578 void RunProcessCaptureNumBandsCheckVerification() {
579 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
580 // way that the number of bands for the rates are different.
581 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
582 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, 1, 1);
583 PopulateInputFrame(frame_length_, num_bands_, 0,
584 &capture_buffer_.split_bands_f(0)[0], 100);
585 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
586 }
587
588 #endif
589
590 private:
OptionalBandSplit()591 void OptionalBandSplit() {
592 if (sample_rate_hz_ > 16000) {
593 capture_buffer_.SplitIntoFrequencyBands();
594 render_buffer_.SplitIntoFrequencyBands();
595 }
596 }
597
598 static constexpr size_t kNumFramesToProcess = 20;
599 const int sample_rate_hz_;
600 const size_t num_bands_;
601 const size_t frame_length_;
602 const int fullband_frame_length_;
603 AudioBuffer capture_buffer_;
604 AudioBuffer render_buffer_;
605
606 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester);
607 };
608
ProduceDebugText(int sample_rate_hz)609 std::string ProduceDebugText(int sample_rate_hz) {
610 rtc::StringBuilder ss;
611 ss << "Sample rate: " << sample_rate_hz;
612 return ss.Release();
613 }
614
ProduceDebugText(int sample_rate_hz,int variant)615 std::string ProduceDebugText(int sample_rate_hz, int variant) {
616 rtc::StringBuilder ss;
617 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant;
618 return ss.Release();
619 }
620
621 } // namespace
622
TEST(EchoCanceller3Buffering,CaptureBitexactness)623 TEST(EchoCanceller3Buffering, CaptureBitexactness) {
624 for (auto rate : {16000, 32000, 48000}) {
625 SCOPED_TRACE(ProduceDebugText(rate));
626 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest();
627 }
628 }
629
TEST(EchoCanceller3Buffering,RenderBitexactness)630 TEST(EchoCanceller3Buffering, RenderBitexactness) {
631 for (auto rate : {16000, 32000, 48000}) {
632 SCOPED_TRACE(ProduceDebugText(rate));
633 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest();
634 }
635 }
636
TEST(EchoCanceller3Buffering,RenderSwapQueue)637 TEST(EchoCanceller3Buffering, RenderSwapQueue) {
638 EchoCanceller3Tester(16000).RunRenderSwapQueueVerificationTest();
639 }
640
TEST(EchoCanceller3Buffering,RenderSwapQueueOverrunReturnValue)641 TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) {
642 for (auto rate : {16000, 32000, 48000}) {
643 SCOPED_TRACE(ProduceDebugText(rate));
644 EchoCanceller3Tester(rate)
645 .RunRenderPipelineSwapQueueOverrunReturnValueTest();
646 }
647 }
648
TEST(EchoCanceller3Messaging,CaptureSaturation)649 TEST(EchoCanceller3Messaging, CaptureSaturation) {
650 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone,
651 EchoCanceller3Tester::SaturationTestVariant::kOneNegative,
652 EchoCanceller3Tester::SaturationTestVariant::kOnePositive};
653 for (auto rate : {16000, 32000, 48000}) {
654 for (auto variant : variants) {
655 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
656 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant);
657 }
658 }
659 }
660
TEST(EchoCanceller3Messaging,EchoPathChange)661 TEST(EchoCanceller3Messaging, EchoPathChange) {
662 auto variants = {
663 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone,
664 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky,
665 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky};
666 for (auto rate : {16000, 32000, 48000}) {
667 for (auto variant : variants) {
668 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
669 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant);
670 }
671 }
672 }
673
TEST(EchoCanceller3Messaging,EchoLeakage)674 TEST(EchoCanceller3Messaging, EchoLeakage) {
675 auto variants = {
676 EchoCanceller3Tester::EchoLeakageTestVariant::kNone,
677 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky,
678 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky,
679 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky};
680 for (auto rate : {16000, 32000, 48000}) {
681 for (auto variant : variants) {
682 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
683 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant);
684 }
685 }
686 }
687
688 // Tests the parameter functionality for the field trial override for the
689 // default_len parameter.
TEST(EchoCanceller3FieldTrials,Aec3SuppressorEpStrengthDefaultLenOverride)690 TEST(EchoCanceller3FieldTrials, Aec3SuppressorEpStrengthDefaultLenOverride) {
691 EchoCanceller3Config default_config;
692 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
693 ASSERT_EQ(default_config.ep_strength.default_len,
694 adjusted_config.ep_strength.default_len);
695
696 webrtc::test::ScopedFieldTrials field_trials(
697 "WebRTC-Aec3SuppressorEpStrengthDefaultLenOverride/-0.02/");
698 adjusted_config = AdjustConfig(default_config);
699
700 ASSERT_NE(default_config.ep_strength.default_len,
701 adjusted_config.ep_strength.default_len);
702 EXPECT_FLOAT_EQ(-0.02f, adjusted_config.ep_strength.default_len);
703 }
704
705 // Tests the parameter functionality for the field trial override for the
706 // anti-howling gain.
TEST(EchoCanceller3FieldTrials,Aec3SuppressorAntiHowlingGainOverride)707 TEST(EchoCanceller3FieldTrials, Aec3SuppressorAntiHowlingGainOverride) {
708 EchoCanceller3Config default_config;
709 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
710 ASSERT_EQ(
711 default_config.suppressor.high_bands_suppression.anti_howling_gain,
712 adjusted_config.suppressor.high_bands_suppression.anti_howling_gain);
713
714 webrtc::test::ScopedFieldTrials field_trials(
715 "WebRTC-Aec3SuppressorAntiHowlingGainOverride/0.02/");
716 adjusted_config = AdjustConfig(default_config);
717
718 ASSERT_NE(
719 default_config.suppressor.high_bands_suppression.anti_howling_gain,
720 adjusted_config.suppressor.high_bands_suppression.anti_howling_gain);
721 EXPECT_FLOAT_EQ(
722 0.02f,
723 adjusted_config.suppressor.high_bands_suppression.anti_howling_gain);
724 }
725
726 // Tests the field trial override for the enforcement of a low active render
727 // limit.
TEST(EchoCanceller3FieldTrials,Aec3EnforceLowActiveRenderLimit)728 TEST(EchoCanceller3FieldTrials, Aec3EnforceLowActiveRenderLimit) {
729 EchoCanceller3Config default_config;
730 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
731 ASSERT_EQ(default_config.render_levels.active_render_limit,
732 adjusted_config.render_levels.active_render_limit);
733
734 webrtc::test::ScopedFieldTrials field_trials(
735 "WebRTC-Aec3EnforceLowActiveRenderLimit/Enabled/");
736 adjusted_config = AdjustConfig(default_config);
737
738 ASSERT_NE(default_config.render_levels.active_render_limit,
739 adjusted_config.render_levels.active_render_limit);
740 EXPECT_FLOAT_EQ(50.f, adjusted_config.render_levels.active_render_limit);
741 }
742
743 // Testing the field trial-based override of the suppressor parameters for a
744 // joint passing of all parameters.
TEST(EchoCanceller3FieldTrials,Aec3SuppressorTuningOverrideAllParams)745 TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideAllParams) {
746 webrtc::test::ScopedFieldTrials field_trials(
747 "WebRTC-Aec3SuppressorTuningOverride/"
748 "nearend_tuning_mask_lf_enr_transparent:0.1,nearend_tuning_mask_lf_enr_"
749 "suppress:0.2,nearend_tuning_mask_hf_enr_transparent:0.3,nearend_tuning_"
750 "mask_hf_enr_suppress:0.4,nearend_tuning_max_inc_factor:0.5,nearend_"
751 "tuning_max_dec_factor_lf:0.6,normal_tuning_mask_lf_enr_transparent:0.7,"
752 "normal_tuning_mask_lf_enr_suppress:0.8,normal_tuning_mask_hf_enr_"
753 "transparent:0.9,normal_tuning_mask_hf_enr_suppress:1.0,normal_tuning_"
754 "max_inc_factor:1.1,normal_tuning_max_dec_factor_lf:1.2,dominant_nearend_"
755 "detection_enr_threshold:1.3,dominant_nearend_detection_enr_exit_"
756 "threshold:1.4,dominant_nearend_detection_snr_threshold:1.5,dominant_"
757 "nearend_detection_hold_duration:10,dominant_nearend_detection_trigger_"
758 "threshold:11,ep_strength_default_len:1.6/");
759
760 EchoCanceller3Config default_config;
761 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
762
763 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent,
764 default_config.suppressor.nearend_tuning.mask_lf.enr_transparent);
765 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_suppress,
766 default_config.suppressor.nearend_tuning.mask_lf.enr_suppress);
767 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_hf.enr_transparent,
768 default_config.suppressor.nearend_tuning.mask_hf.enr_transparent);
769 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_hf.enr_suppress,
770 default_config.suppressor.nearend_tuning.mask_hf.enr_suppress);
771 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.max_inc_factor,
772 default_config.suppressor.nearend_tuning.max_inc_factor);
773 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.max_dec_factor_lf,
774 default_config.suppressor.nearend_tuning.max_dec_factor_lf);
775 ASSERT_NE(adjusted_config.suppressor.normal_tuning.mask_lf.enr_transparent,
776 default_config.suppressor.normal_tuning.mask_lf.enr_transparent);
777 ASSERT_NE(adjusted_config.suppressor.normal_tuning.mask_lf.enr_suppress,
778 default_config.suppressor.normal_tuning.mask_lf.enr_suppress);
779 ASSERT_NE(adjusted_config.suppressor.normal_tuning.mask_hf.enr_transparent,
780 default_config.suppressor.normal_tuning.mask_hf.enr_transparent);
781 ASSERT_NE(adjusted_config.suppressor.normal_tuning.mask_hf.enr_suppress,
782 default_config.suppressor.normal_tuning.mask_hf.enr_suppress);
783 ASSERT_NE(adjusted_config.suppressor.normal_tuning.max_inc_factor,
784 default_config.suppressor.normal_tuning.max_inc_factor);
785 ASSERT_NE(adjusted_config.suppressor.normal_tuning.max_dec_factor_lf,
786 default_config.suppressor.normal_tuning.max_dec_factor_lf);
787 ASSERT_NE(adjusted_config.suppressor.dominant_nearend_detection.enr_threshold,
788 default_config.suppressor.dominant_nearend_detection.enr_threshold);
789 ASSERT_NE(
790 adjusted_config.suppressor.dominant_nearend_detection.enr_exit_threshold,
791 default_config.suppressor.dominant_nearend_detection.enr_exit_threshold);
792 ASSERT_NE(adjusted_config.suppressor.dominant_nearend_detection.snr_threshold,
793 default_config.suppressor.dominant_nearend_detection.snr_threshold);
794 ASSERT_NE(adjusted_config.suppressor.dominant_nearend_detection.hold_duration,
795 default_config.suppressor.dominant_nearend_detection.hold_duration);
796 ASSERT_NE(
797 adjusted_config.suppressor.dominant_nearend_detection.trigger_threshold,
798 default_config.suppressor.dominant_nearend_detection.trigger_threshold);
799 ASSERT_NE(adjusted_config.ep_strength.default_len,
800 default_config.ep_strength.default_len);
801
802 EXPECT_FLOAT_EQ(
803 adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent, 0.1);
804 EXPECT_FLOAT_EQ(
805 adjusted_config.suppressor.nearend_tuning.mask_lf.enr_suppress, 0.2);
806 EXPECT_FLOAT_EQ(
807 adjusted_config.suppressor.nearend_tuning.mask_hf.enr_transparent, 0.3);
808 EXPECT_FLOAT_EQ(
809 adjusted_config.suppressor.nearend_tuning.mask_hf.enr_suppress, 0.4);
810 EXPECT_FLOAT_EQ(adjusted_config.suppressor.nearend_tuning.max_inc_factor,
811 0.5);
812 EXPECT_FLOAT_EQ(adjusted_config.suppressor.nearend_tuning.max_dec_factor_lf,
813 0.6);
814 EXPECT_FLOAT_EQ(
815 adjusted_config.suppressor.normal_tuning.mask_lf.enr_transparent, 0.7);
816 EXPECT_FLOAT_EQ(adjusted_config.suppressor.normal_tuning.mask_lf.enr_suppress,
817 0.8);
818 EXPECT_FLOAT_EQ(
819 adjusted_config.suppressor.normal_tuning.mask_hf.enr_transparent, 0.9);
820 EXPECT_FLOAT_EQ(adjusted_config.suppressor.normal_tuning.mask_hf.enr_suppress,
821 1.0);
822 EXPECT_FLOAT_EQ(adjusted_config.suppressor.normal_tuning.max_inc_factor, 1.1);
823 EXPECT_FLOAT_EQ(adjusted_config.suppressor.normal_tuning.max_dec_factor_lf,
824 1.2);
825 EXPECT_FLOAT_EQ(
826 adjusted_config.suppressor.dominant_nearend_detection.enr_threshold, 1.3);
827 EXPECT_FLOAT_EQ(
828 adjusted_config.suppressor.dominant_nearend_detection.enr_exit_threshold,
829 1.4);
830 EXPECT_FLOAT_EQ(
831 adjusted_config.suppressor.dominant_nearend_detection.snr_threshold, 1.5);
832 EXPECT_EQ(adjusted_config.suppressor.dominant_nearend_detection.hold_duration,
833 10);
834 EXPECT_EQ(
835 adjusted_config.suppressor.dominant_nearend_detection.trigger_threshold,
836 11);
837 EXPECT_FLOAT_EQ(adjusted_config.ep_strength.default_len, 1.6);
838 }
839
840 // Testing the field trial-based override of the suppressor parameters for
841 // passing one parameter.
TEST(EchoCanceller3FieldTrials,Aec3SuppressorTuningOverrideOneParam)842 TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideOneParam) {
843 webrtc::test::ScopedFieldTrials field_trials(
844 "WebRTC-Aec3SuppressorTuningOverride/nearend_tuning_max_inc_factor:0.5/");
845
846 EchoCanceller3Config default_config;
847 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
848
849 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent,
850 default_config.suppressor.nearend_tuning.mask_lf.enr_transparent);
851 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_suppress,
852 default_config.suppressor.nearend_tuning.mask_lf.enr_suppress);
853 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_hf.enr_transparent,
854 default_config.suppressor.nearend_tuning.mask_hf.enr_transparent);
855 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_hf.enr_suppress,
856 default_config.suppressor.nearend_tuning.mask_hf.enr_suppress);
857 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.max_dec_factor_lf,
858 default_config.suppressor.nearend_tuning.max_dec_factor_lf);
859 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.mask_lf.enr_transparent,
860 default_config.suppressor.normal_tuning.mask_lf.enr_transparent);
861 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.mask_lf.enr_suppress,
862 default_config.suppressor.normal_tuning.mask_lf.enr_suppress);
863 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.mask_hf.enr_transparent,
864 default_config.suppressor.normal_tuning.mask_hf.enr_transparent);
865 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.mask_hf.enr_suppress,
866 default_config.suppressor.normal_tuning.mask_hf.enr_suppress);
867 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.max_inc_factor,
868 default_config.suppressor.normal_tuning.max_inc_factor);
869 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.max_dec_factor_lf,
870 default_config.suppressor.normal_tuning.max_dec_factor_lf);
871 ASSERT_EQ(adjusted_config.suppressor.dominant_nearend_detection.enr_threshold,
872 default_config.suppressor.dominant_nearend_detection.enr_threshold);
873 ASSERT_EQ(
874 adjusted_config.suppressor.dominant_nearend_detection.enr_exit_threshold,
875 default_config.suppressor.dominant_nearend_detection.enr_exit_threshold);
876 ASSERT_EQ(adjusted_config.suppressor.dominant_nearend_detection.snr_threshold,
877 default_config.suppressor.dominant_nearend_detection.snr_threshold);
878 ASSERT_EQ(adjusted_config.suppressor.dominant_nearend_detection.hold_duration,
879 default_config.suppressor.dominant_nearend_detection.hold_duration);
880 ASSERT_EQ(
881 adjusted_config.suppressor.dominant_nearend_detection.trigger_threshold,
882 default_config.suppressor.dominant_nearend_detection.trigger_threshold);
883
884 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.max_inc_factor,
885 default_config.suppressor.nearend_tuning.max_inc_factor);
886
887 EXPECT_FLOAT_EQ(adjusted_config.suppressor.nearend_tuning.max_inc_factor,
888 0.5);
889 }
890
891 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
892
TEST(EchoCanceller3InputCheckDeathTest,WrongCaptureNumBandsCheckVerification)893 TEST(EchoCanceller3InputCheckDeathTest, WrongCaptureNumBandsCheckVerification) {
894 for (auto rate : {16000, 32000, 48000}) {
895 SCOPED_TRACE(ProduceDebugText(rate));
896 EchoCanceller3Tester(rate).RunProcessCaptureNumBandsCheckVerification();
897 }
898 }
899
900 // Verifiers that the verification for null input to the capture processing api
901 // call works.
TEST(EchoCanceller3InputCheckDeathTest,NullCaptureProcessingParameter)902 TEST(EchoCanceller3InputCheckDeathTest, NullCaptureProcessingParameter) {
903 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 16000, 1, 1)
904 .ProcessCapture(nullptr, false),
905 "");
906 }
907
908 // Verifies the check for correct sample rate.
909 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
910 // tests on test bots has been fixed.
TEST(EchoCanceller3InputCheckDeathTest,DISABLED_WrongSampleRate)911 TEST(EchoCanceller3InputCheckDeathTest, DISABLED_WrongSampleRate) {
912 ApmDataDumper data_dumper(0);
913 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8001, 1, 1), "");
914 }
915
916 #endif
917
918 } // namespace webrtc
919