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
112 CaptureTransportVerificationProcessor() = delete;
113 CaptureTransportVerificationProcessor(
114 const CaptureTransportVerificationProcessor&) = delete;
115 CaptureTransportVerificationProcessor& operator=(
116 const CaptureTransportVerificationProcessor&) = delete;
117
118 ~CaptureTransportVerificationProcessor() override = default;
119
ProcessCapture(bool level_change,bool saturated_microphone_signal,Block * linear_output,Block * capture_block)120 void ProcessCapture(bool level_change,
121 bool saturated_microphone_signal,
122 Block* linear_output,
123 Block* capture_block) override {}
124
BufferRender(const Block & block)125 void BufferRender(const Block& block) override {}
126
UpdateEchoLeakageStatus(bool leakage_detected)127 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
128
GetMetrics(EchoControl::Metrics * metrics) const129 void GetMetrics(EchoControl::Metrics* metrics) const override {}
130
SetAudioBufferDelay(int delay_ms)131 void SetAudioBufferDelay(int delay_ms) override {}
132
SetCaptureOutputUsage(bool capture_output_used)133 void SetCaptureOutputUsage(bool capture_output_used) {}
134 };
135
136 // Class for testing that the render data is properly received by the block
137 // processor.
138 class RenderTransportVerificationProcessor : public BlockProcessor {
139 public:
RenderTransportVerificationProcessor(size_t num_bands)140 explicit RenderTransportVerificationProcessor(size_t num_bands) {}
141
142 RenderTransportVerificationProcessor() = delete;
143 RenderTransportVerificationProcessor(
144 const RenderTransportVerificationProcessor&) = delete;
145 RenderTransportVerificationProcessor& operator=(
146 const RenderTransportVerificationProcessor&) = delete;
147
148 ~RenderTransportVerificationProcessor() override = default;
149
ProcessCapture(bool level_change,bool saturated_microphone_signal,Block * linear_output,Block * capture_block)150 void ProcessCapture(bool level_change,
151 bool saturated_microphone_signal,
152 Block* linear_output,
153 Block* capture_block) override {
154 Block render_block = received_render_blocks_.front();
155 received_render_blocks_.pop_front();
156 capture_block->Swap(render_block);
157 }
158
BufferRender(const Block & block)159 void BufferRender(const Block& block) override {
160 received_render_blocks_.push_back(block);
161 }
162
UpdateEchoLeakageStatus(bool leakage_detected)163 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
164
GetMetrics(EchoControl::Metrics * metrics) const165 void GetMetrics(EchoControl::Metrics* metrics) const override {}
166
SetAudioBufferDelay(int delay_ms)167 void SetAudioBufferDelay(int delay_ms) override {}
168
SetCaptureOutputUsage(bool capture_output_used)169 void SetCaptureOutputUsage(bool capture_output_used) {}
170
171 private:
172 std::deque<Block> received_render_blocks_;
173 };
174
ProduceDebugText(int sample_rate_hz)175 std::string ProduceDebugText(int sample_rate_hz) {
176 rtc::StringBuilder ss;
177 ss << "Sample rate: " << sample_rate_hz;
178 return ss.Release();
179 }
180
ProduceDebugText(int sample_rate_hz,int variant)181 std::string ProduceDebugText(int sample_rate_hz, int variant) {
182 rtc::StringBuilder ss;
183 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant;
184 return ss.Release();
185 }
186
RunAecInStereo(AudioBuffer & buffer,EchoCanceller3 & aec3,float channel_0_value,float channel_1_value)187 void RunAecInStereo(AudioBuffer& buffer,
188 EchoCanceller3& aec3,
189 float channel_0_value,
190 float channel_1_value) {
191 rtc::ArrayView<float> data_channel_0(&buffer.channels()[0][0],
192 buffer.num_frames());
193 std::fill(data_channel_0.begin(), data_channel_0.end(), channel_0_value);
194 rtc::ArrayView<float> data_channel_1(&buffer.channels()[1][0],
195 buffer.num_frames());
196 std::fill(data_channel_1.begin(), data_channel_1.end(), channel_1_value);
197 aec3.AnalyzeRender(&buffer);
198 aec3.AnalyzeCapture(&buffer);
199 aec3.ProcessCapture(&buffer, /*level_change=*/false);
200 }
201
RunAecInSMono(AudioBuffer & buffer,EchoCanceller3 & aec3,float channel_0_value)202 void RunAecInSMono(AudioBuffer& buffer,
203 EchoCanceller3& aec3,
204 float channel_0_value) {
205 rtc::ArrayView<float> data_channel_0(&buffer.channels()[0][0],
206 buffer.num_frames());
207 std::fill(data_channel_0.begin(), data_channel_0.end(), channel_0_value);
208 aec3.AnalyzeRender(&buffer);
209 aec3.AnalyzeCapture(&buffer);
210 aec3.ProcessCapture(&buffer, /*level_change=*/false);
211 }
212
213 } // namespace
214
215 class EchoCanceller3Tester {
216 public:
EchoCanceller3Tester(int sample_rate_hz)217 explicit EchoCanceller3Tester(int sample_rate_hz)
218 : sample_rate_hz_(sample_rate_hz),
219 num_bands_(NumBandsForRate(sample_rate_hz_)),
220 frame_length_(160),
221 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)),
222 capture_buffer_(fullband_frame_length_ * 100,
223 1,
224 fullband_frame_length_ * 100,
225 1,
226 fullband_frame_length_ * 100,
227 1),
228 render_buffer_(fullband_frame_length_ * 100,
229 1,
230 fullband_frame_length_ * 100,
231 1,
232 fullband_frame_length_ * 100,
233 1) {}
234
235 EchoCanceller3Tester() = delete;
236 EchoCanceller3Tester(const EchoCanceller3Tester&) = delete;
237 EchoCanceller3Tester& operator=(const EchoCanceller3Tester&) = delete;
238
239 // Verifies that the capture data is properly received by the block processor
240 // and that the processor data is properly passed to the EchoCanceller3
241 // output.
RunCaptureTransportVerificationTest()242 void RunCaptureTransportVerificationTest() {
243 EchoCanceller3 aec3(EchoCanceller3Config(),
244 /*multichannel_config=*/absl::nullopt, sample_rate_hz_,
245 1, 1);
246 aec3.SetBlockProcessorForTesting(
247 std::make_unique<CaptureTransportVerificationProcessor>(num_bands_));
248
249 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
250 ++frame_index) {
251 aec3.AnalyzeCapture(&capture_buffer_);
252 OptionalBandSplit();
253 PopulateInputFrame(frame_length_, num_bands_, frame_index,
254 &capture_buffer_.split_bands(0)[0], 0);
255 PopulateInputFrame(frame_length_, frame_index,
256 &render_buffer_.channels()[0][0], 0);
257
258 aec3.AnalyzeRender(&render_buffer_);
259 aec3.ProcessCapture(&capture_buffer_, false);
260 EXPECT_TRUE(VerifyOutputFrameBitexactness(
261 frame_length_, num_bands_, frame_index,
262 &capture_buffer_.split_bands(0)[0], -64));
263 }
264 }
265
266 // Test method for testing that the render data is properly received by the
267 // block processor.
RunRenderTransportVerificationTest()268 void RunRenderTransportVerificationTest() {
269 EchoCanceller3 aec3(EchoCanceller3Config(),
270 /*multichannel_config=*/absl::nullopt, sample_rate_hz_,
271 1, 1);
272 aec3.SetBlockProcessorForTesting(
273 std::make_unique<RenderTransportVerificationProcessor>(num_bands_));
274
275 std::vector<std::vector<float>> render_input(1);
276 std::vector<float> capture_output;
277 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
278 ++frame_index) {
279 aec3.AnalyzeCapture(&capture_buffer_);
280 OptionalBandSplit();
281 PopulateInputFrame(frame_length_, num_bands_, frame_index,
282 &capture_buffer_.split_bands(0)[0], 100);
283 PopulateInputFrame(frame_length_, num_bands_, frame_index,
284 &render_buffer_.split_bands(0)[0], 0);
285
286 for (size_t k = 0; k < frame_length_; ++k) {
287 render_input[0].push_back(render_buffer_.split_bands(0)[0][k]);
288 }
289 aec3.AnalyzeRender(&render_buffer_);
290 aec3.ProcessCapture(&capture_buffer_, false);
291 for (size_t k = 0; k < frame_length_; ++k) {
292 capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
293 }
294 }
295
296 EXPECT_TRUE(
297 VerifyOutputFrameBitexactness(render_input[0], capture_output, -64));
298 }
299
300 // Verifies that information about echo path changes are properly propagated
301 // to the block processor.
302 // The cases tested are:
303 // -That no set echo path change flags are received when there is no echo path
304 // change.
305 // -That set echo path change flags are received and continues to be received
306 // as long as echo path changes are flagged.
307 // -That set echo path change flags are no longer received when echo path
308 // change events stop being flagged.
309 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky };
310
RunEchoPathChangeVerificationTest(EchoPathChangeTestVariant echo_path_change_test_variant)311 void RunEchoPathChangeVerificationTest(
312 EchoPathChangeTestVariant echo_path_change_test_variant) {
313 constexpr size_t kNumFullBlocksPerFrame = 160 / kBlockSize;
314 constexpr size_t kExpectedNumBlocksToProcess =
315 (kNumFramesToProcess * 160) / kBlockSize;
316 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
317 block_processor_mock(
318 new StrictMock<webrtc::test::MockBlockProcessor>());
319 EXPECT_CALL(*block_processor_mock, BufferRender(_))
320 .Times(kExpectedNumBlocksToProcess);
321 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
322
323 switch (echo_path_change_test_variant) {
324 case EchoPathChangeTestVariant::kNone:
325 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _, _))
326 .Times(kExpectedNumBlocksToProcess);
327 break;
328 case EchoPathChangeTestVariant::kOneSticky:
329 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _, _))
330 .Times(kExpectedNumBlocksToProcess);
331 break;
332 case EchoPathChangeTestVariant::kOneNonSticky:
333 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _, _))
334 .Times(kNumFullBlocksPerFrame);
335 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _, _))
336 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
337 break;
338 }
339
340 EchoCanceller3 aec3(EchoCanceller3Config(),
341 /*multichannel_config=*/absl::nullopt, sample_rate_hz_,
342 1, 1);
343 aec3.SetBlockProcessorForTesting(std::move(block_processor_mock));
344
345 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
346 ++frame_index) {
347 bool echo_path_change = false;
348 switch (echo_path_change_test_variant) {
349 case EchoPathChangeTestVariant::kNone:
350 break;
351 case EchoPathChangeTestVariant::kOneSticky:
352 echo_path_change = true;
353 break;
354 case EchoPathChangeTestVariant::kOneNonSticky:
355 if (frame_index == 0) {
356 echo_path_change = true;
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(0)[0], 0);
366 PopulateInputFrame(frame_length_, frame_index,
367 &render_buffer_.channels()[0][0], 0);
368
369 aec3.AnalyzeRender(&render_buffer_);
370 aec3.ProcessCapture(&capture_buffer_, echo_path_change);
371 }
372 }
373
374 // Test for verifying that echo leakage information is being properly passed
375 // to the processor.
376 // The cases tested are:
377 // -That no method calls are received when they should not.
378 // -That false values are received each time they are flagged.
379 // -That true values are received each time they are flagged.
380 // -That a false value is received when flagged after a true value has been
381 // flagged.
382 enum class EchoLeakageTestVariant {
383 kNone,
384 kFalseSticky,
385 kTrueSticky,
386 kTrueNonSticky
387 };
388
RunEchoLeakageVerificationTest(EchoLeakageTestVariant leakage_report_variant)389 void RunEchoLeakageVerificationTest(
390 EchoLeakageTestVariant leakage_report_variant) {
391 constexpr size_t kExpectedNumBlocksToProcess =
392 (kNumFramesToProcess * 160) / kBlockSize;
393 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
394 block_processor_mock(
395 new StrictMock<webrtc::test::MockBlockProcessor>());
396 EXPECT_CALL(*block_processor_mock, BufferRender(_))
397 .Times(kExpectedNumBlocksToProcess);
398 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _, _))
399 .Times(kExpectedNumBlocksToProcess);
400
401 switch (leakage_report_variant) {
402 case EchoLeakageTestVariant::kNone:
403 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
404 break;
405 case EchoLeakageTestVariant::kFalseSticky:
406 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
407 .Times(1);
408 break;
409 case EchoLeakageTestVariant::kTrueSticky:
410 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
411 .Times(1);
412 break;
413 case EchoLeakageTestVariant::kTrueNonSticky: {
414 ::testing::InSequence s;
415 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
416 .Times(1);
417 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
418 .Times(kNumFramesToProcess - 1);
419 } break;
420 }
421
422 EchoCanceller3 aec3(EchoCanceller3Config(),
423 /*multichannel_config=*/absl::nullopt, sample_rate_hz_,
424 1, 1);
425 aec3.SetBlockProcessorForTesting(std::move(block_processor_mock));
426
427 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
428 ++frame_index) {
429 switch (leakage_report_variant) {
430 case EchoLeakageTestVariant::kNone:
431 break;
432 case EchoLeakageTestVariant::kFalseSticky:
433 if (frame_index == 0) {
434 aec3.UpdateEchoLeakageStatus(false);
435 }
436 break;
437 case EchoLeakageTestVariant::kTrueSticky:
438 if (frame_index == 0) {
439 aec3.UpdateEchoLeakageStatus(true);
440 }
441 break;
442 case EchoLeakageTestVariant::kTrueNonSticky:
443 if (frame_index == 0) {
444 aec3.UpdateEchoLeakageStatus(true);
445 } else {
446 aec3.UpdateEchoLeakageStatus(false);
447 }
448 break;
449 }
450
451 aec3.AnalyzeCapture(&capture_buffer_);
452 OptionalBandSplit();
453
454 PopulateInputFrame(frame_length_, num_bands_, frame_index,
455 &capture_buffer_.split_bands(0)[0], 0);
456 PopulateInputFrame(frame_length_, frame_index,
457 &render_buffer_.channels()[0][0], 0);
458
459 aec3.AnalyzeRender(&render_buffer_);
460 aec3.ProcessCapture(&capture_buffer_, false);
461 }
462 }
463
464 // This verifies that saturation information is properly passed to the
465 // BlockProcessor.
466 // The cases tested are:
467 // -That no saturation event is passed to the processor if there is no
468 // saturation.
469 // -That one frame with one negative saturated sample value is reported to be
470 // saturated and that following non-saturated frames are properly reported as
471 // not being saturated.
472 // -That one frame with one positive saturated sample value is reported to be
473 // saturated and that following non-saturated frames are properly reported as
474 // not being saturated.
475 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive };
476
RunCaptureSaturationVerificationTest(SaturationTestVariant saturation_variant)477 void RunCaptureSaturationVerificationTest(
478 SaturationTestVariant saturation_variant) {
479 const size_t kNumFullBlocksPerFrame = 160 / kBlockSize;
480 const size_t kExpectedNumBlocksToProcess =
481 (kNumFramesToProcess * 160) / kBlockSize;
482 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
483 block_processor_mock(
484 new StrictMock<webrtc::test::MockBlockProcessor>());
485 EXPECT_CALL(*block_processor_mock, BufferRender(_))
486 .Times(kExpectedNumBlocksToProcess);
487 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
488
489 switch (saturation_variant) {
490 case SaturationTestVariant::kNone:
491 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _, _))
492 .Times(kExpectedNumBlocksToProcess);
493 break;
494 case SaturationTestVariant::kOneNegative: {
495 ::testing::InSequence s;
496 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _, _))
497 .Times(kNumFullBlocksPerFrame);
498 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _, _))
499 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
500 } break;
501 case SaturationTestVariant::kOnePositive: {
502 ::testing::InSequence s;
503 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _, _))
504 .Times(kNumFullBlocksPerFrame);
505 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _, _))
506 .Times(kExpectedNumBlocksToProcess - kNumFullBlocksPerFrame);
507 } break;
508 }
509
510 EchoCanceller3 aec3(EchoCanceller3Config(),
511 /*multichannel_config=*/absl::nullopt, sample_rate_hz_,
512 1, 1);
513 aec3.SetBlockProcessorForTesting(std::move(block_processor_mock));
514 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
515 ++frame_index) {
516 for (int k = 0; k < fullband_frame_length_; ++k) {
517 capture_buffer_.channels()[0][k] = 0.f;
518 }
519 switch (saturation_variant) {
520 case SaturationTestVariant::kNone:
521 break;
522 case SaturationTestVariant::kOneNegative:
523 if (frame_index == 0) {
524 capture_buffer_.channels()[0][10] = -32768.f;
525 }
526 break;
527 case SaturationTestVariant::kOnePositive:
528 if (frame_index == 0) {
529 capture_buffer_.channels()[0][10] = 32767.f;
530 }
531 break;
532 }
533
534 aec3.AnalyzeCapture(&capture_buffer_);
535 OptionalBandSplit();
536
537 PopulateInputFrame(frame_length_, num_bands_, frame_index,
538 &capture_buffer_.split_bands(0)[0], 0);
539 PopulateInputFrame(frame_length_, num_bands_, frame_index,
540 &render_buffer_.split_bands(0)[0], 0);
541
542 aec3.AnalyzeRender(&render_buffer_);
543 aec3.ProcessCapture(&capture_buffer_, false);
544 }
545 }
546
547 // This test verifies that the swapqueue is able to handle jitter in the
548 // capture and render API calls.
RunRenderSwapQueueVerificationTest()549 void RunRenderSwapQueueVerificationTest() {
550 const EchoCanceller3Config config;
551 EchoCanceller3 aec3(config, /*multichannel_config=*/absl::nullopt,
552 sample_rate_hz_, 1, 1);
553 aec3.SetBlockProcessorForTesting(
554 std::make_unique<RenderTransportVerificationProcessor>(num_bands_));
555
556 std::vector<std::vector<float>> render_input(1);
557 std::vector<float> capture_output;
558
559 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
560 ++frame_index) {
561 if (sample_rate_hz_ > 16000) {
562 render_buffer_.SplitIntoFrequencyBands();
563 }
564 PopulateInputFrame(frame_length_, num_bands_, frame_index,
565 &render_buffer_.split_bands(0)[0], 0);
566
567 if (sample_rate_hz_ > 16000) {
568 render_buffer_.SplitIntoFrequencyBands();
569 }
570
571 for (size_t k = 0; k < frame_length_; ++k) {
572 render_input[0].push_back(render_buffer_.split_bands(0)[0][k]);
573 }
574 aec3.AnalyzeRender(&render_buffer_);
575 }
576
577 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
578 ++frame_index) {
579 aec3.AnalyzeCapture(&capture_buffer_);
580 if (sample_rate_hz_ > 16000) {
581 capture_buffer_.SplitIntoFrequencyBands();
582 }
583
584 PopulateInputFrame(frame_length_, num_bands_, frame_index,
585 &capture_buffer_.split_bands(0)[0], 0);
586
587 aec3.ProcessCapture(&capture_buffer_, false);
588 for (size_t k = 0; k < frame_length_; ++k) {
589 capture_output.push_back(capture_buffer_.split_bands(0)[0][k]);
590 }
591 }
592
593 EXPECT_TRUE(
594 VerifyOutputFrameBitexactness(render_input[0], capture_output, -64));
595 }
596
597 // This test verifies that a buffer overrun in the render swapqueue is
598 // properly reported.
RunRenderPipelineSwapQueueOverrunReturnValueTest()599 void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
600 EchoCanceller3 aec3(EchoCanceller3Config(),
601 /*multichannel_config=*/absl::nullopt, sample_rate_hz_,
602 1, 1);
603
604 constexpr size_t kRenderTransferQueueSize = 30;
605 for (size_t k = 0; k < 2; ++k) {
606 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
607 ++frame_index) {
608 if (sample_rate_hz_ > 16000) {
609 render_buffer_.SplitIntoFrequencyBands();
610 }
611 PopulateInputFrame(frame_length_, frame_index,
612 &render_buffer_.channels()[0][0], 0);
613
614 aec3.AnalyzeRender(&render_buffer_);
615 }
616 }
617 }
618
619 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
620 // Verifies the that the check for the number of bands in the AnalyzeRender
621 // input is correct by adjusting the sample rates of EchoCanceller3 and the
622 // input AudioBuffer to have a different number of bands.
RunAnalyzeRenderNumBandsCheckVerification()623 void RunAnalyzeRenderNumBandsCheckVerification() {
624 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
625 // way that the number of bands for the rates are different.
626 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
627 EchoCanceller3 aec3(EchoCanceller3Config(),
628 /*multichannel_config=*/absl::nullopt,
629 aec3_sample_rate_hz, 1, 1);
630 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
631
632 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
633 }
634
635 // Verifies the that the check for the number of bands in the ProcessCapture
636 // input is correct by adjusting the sample rates of EchoCanceller3 and the
637 // input AudioBuffer to have a different number of bands.
RunProcessCaptureNumBandsCheckVerification()638 void RunProcessCaptureNumBandsCheckVerification() {
639 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
640 // way that the number of bands for the rates are different.
641 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
642 EchoCanceller3 aec3(EchoCanceller3Config(),
643 /*multichannel_config=*/absl::nullopt,
644 aec3_sample_rate_hz, 1, 1);
645 PopulateInputFrame(frame_length_, num_bands_, 0,
646 &capture_buffer_.split_bands_f(0)[0], 100);
647 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
648 }
649
650 #endif
651
652 private:
OptionalBandSplit()653 void OptionalBandSplit() {
654 if (sample_rate_hz_ > 16000) {
655 capture_buffer_.SplitIntoFrequencyBands();
656 render_buffer_.SplitIntoFrequencyBands();
657 }
658 }
659
660 static constexpr size_t kNumFramesToProcess = 20;
661 const int sample_rate_hz_;
662 const size_t num_bands_;
663 const size_t frame_length_;
664 const int fullband_frame_length_;
665 AudioBuffer capture_buffer_;
666 AudioBuffer render_buffer_;
667 };
668
TEST(EchoCanceller3Buffering,CaptureBitexactness)669 TEST(EchoCanceller3Buffering, CaptureBitexactness) {
670 for (auto rate : {16000, 32000, 48000}) {
671 SCOPED_TRACE(ProduceDebugText(rate));
672 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest();
673 }
674 }
675
TEST(EchoCanceller3Buffering,RenderBitexactness)676 TEST(EchoCanceller3Buffering, RenderBitexactness) {
677 for (auto rate : {16000, 32000, 48000}) {
678 SCOPED_TRACE(ProduceDebugText(rate));
679 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest();
680 }
681 }
682
TEST(EchoCanceller3Buffering,RenderSwapQueue)683 TEST(EchoCanceller3Buffering, RenderSwapQueue) {
684 EchoCanceller3Tester(16000).RunRenderSwapQueueVerificationTest();
685 }
686
TEST(EchoCanceller3Buffering,RenderSwapQueueOverrunReturnValue)687 TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) {
688 for (auto rate : {16000, 32000, 48000}) {
689 SCOPED_TRACE(ProduceDebugText(rate));
690 EchoCanceller3Tester(rate)
691 .RunRenderPipelineSwapQueueOverrunReturnValueTest();
692 }
693 }
694
TEST(EchoCanceller3Messaging,CaptureSaturation)695 TEST(EchoCanceller3Messaging, CaptureSaturation) {
696 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone,
697 EchoCanceller3Tester::SaturationTestVariant::kOneNegative,
698 EchoCanceller3Tester::SaturationTestVariant::kOnePositive};
699 for (auto rate : {16000, 32000, 48000}) {
700 for (auto variant : variants) {
701 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
702 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant);
703 }
704 }
705 }
706
TEST(EchoCanceller3Messaging,EchoPathChange)707 TEST(EchoCanceller3Messaging, EchoPathChange) {
708 auto variants = {
709 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone,
710 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky,
711 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky};
712 for (auto rate : {16000, 32000, 48000}) {
713 for (auto variant : variants) {
714 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
715 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant);
716 }
717 }
718 }
719
TEST(EchoCanceller3Messaging,EchoLeakage)720 TEST(EchoCanceller3Messaging, EchoLeakage) {
721 auto variants = {
722 EchoCanceller3Tester::EchoLeakageTestVariant::kNone,
723 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky,
724 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky,
725 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky};
726 for (auto rate : {16000, 32000, 48000}) {
727 for (auto variant : variants) {
728 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
729 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant);
730 }
731 }
732 }
733
734 // Tests the parameter functionality for the field trial override for the
735 // anti-howling gain.
TEST(EchoCanceller3FieldTrials,Aec3SuppressorAntiHowlingGainOverride)736 TEST(EchoCanceller3FieldTrials, Aec3SuppressorAntiHowlingGainOverride) {
737 EchoCanceller3Config default_config;
738 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
739 ASSERT_EQ(
740 default_config.suppressor.high_bands_suppression.anti_howling_gain,
741 adjusted_config.suppressor.high_bands_suppression.anti_howling_gain);
742
743 webrtc::test::ScopedFieldTrials field_trials(
744 "WebRTC-Aec3SuppressorAntiHowlingGainOverride/0.02/");
745 adjusted_config = AdjustConfig(default_config);
746
747 ASSERT_NE(
748 default_config.suppressor.high_bands_suppression.anti_howling_gain,
749 adjusted_config.suppressor.high_bands_suppression.anti_howling_gain);
750 EXPECT_FLOAT_EQ(
751 0.02f,
752 adjusted_config.suppressor.high_bands_suppression.anti_howling_gain);
753 }
754
755 // Tests the field trial override for the enforcement of a low active render
756 // limit.
TEST(EchoCanceller3FieldTrials,Aec3EnforceLowActiveRenderLimit)757 TEST(EchoCanceller3FieldTrials, Aec3EnforceLowActiveRenderLimit) {
758 EchoCanceller3Config default_config;
759 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
760 ASSERT_EQ(default_config.render_levels.active_render_limit,
761 adjusted_config.render_levels.active_render_limit);
762
763 webrtc::test::ScopedFieldTrials field_trials(
764 "WebRTC-Aec3EnforceLowActiveRenderLimit/Enabled/");
765 adjusted_config = AdjustConfig(default_config);
766
767 ASSERT_NE(default_config.render_levels.active_render_limit,
768 adjusted_config.render_levels.active_render_limit);
769 EXPECT_FLOAT_EQ(50.f, adjusted_config.render_levels.active_render_limit);
770 }
771
772 // Testing the field trial-based override of the suppressor parameters for a
773 // joint passing of all parameters.
TEST(EchoCanceller3FieldTrials,Aec3SuppressorTuningOverrideAllParams)774 TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideAllParams) {
775 webrtc::test::ScopedFieldTrials field_trials(
776 "WebRTC-Aec3SuppressorTuningOverride/"
777 "nearend_tuning_mask_lf_enr_transparent:0.1,nearend_tuning_mask_lf_enr_"
778 "suppress:0.2,nearend_tuning_mask_hf_enr_transparent:0.3,nearend_tuning_"
779 "mask_hf_enr_suppress:0.4,nearend_tuning_max_inc_factor:0.5,nearend_"
780 "tuning_max_dec_factor_lf:0.6,normal_tuning_mask_lf_enr_transparent:0.7,"
781 "normal_tuning_mask_lf_enr_suppress:0.8,normal_tuning_mask_hf_enr_"
782 "transparent:0.9,normal_tuning_mask_hf_enr_suppress:1.0,normal_tuning_"
783 "max_inc_factor:1.1,normal_tuning_max_dec_factor_lf:1.2,dominant_nearend_"
784 "detection_enr_threshold:1.3,dominant_nearend_detection_enr_exit_"
785 "threshold:1.4,dominant_nearend_detection_snr_threshold:1.5,dominant_"
786 "nearend_detection_hold_duration:10,dominant_nearend_detection_trigger_"
787 "threshold:11/");
788
789 EchoCanceller3Config default_config;
790 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
791
792 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent,
793 default_config.suppressor.nearend_tuning.mask_lf.enr_transparent);
794 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_suppress,
795 default_config.suppressor.nearend_tuning.mask_lf.enr_suppress);
796 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_hf.enr_transparent,
797 default_config.suppressor.nearend_tuning.mask_hf.enr_transparent);
798 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.mask_hf.enr_suppress,
799 default_config.suppressor.nearend_tuning.mask_hf.enr_suppress);
800 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.max_inc_factor,
801 default_config.suppressor.nearend_tuning.max_inc_factor);
802 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.max_dec_factor_lf,
803 default_config.suppressor.nearend_tuning.max_dec_factor_lf);
804 ASSERT_NE(adjusted_config.suppressor.normal_tuning.mask_lf.enr_transparent,
805 default_config.suppressor.normal_tuning.mask_lf.enr_transparent);
806 ASSERT_NE(adjusted_config.suppressor.normal_tuning.mask_lf.enr_suppress,
807 default_config.suppressor.normal_tuning.mask_lf.enr_suppress);
808 ASSERT_NE(adjusted_config.suppressor.normal_tuning.mask_hf.enr_transparent,
809 default_config.suppressor.normal_tuning.mask_hf.enr_transparent);
810 ASSERT_NE(adjusted_config.suppressor.normal_tuning.mask_hf.enr_suppress,
811 default_config.suppressor.normal_tuning.mask_hf.enr_suppress);
812 ASSERT_NE(adjusted_config.suppressor.normal_tuning.max_inc_factor,
813 default_config.suppressor.normal_tuning.max_inc_factor);
814 ASSERT_NE(adjusted_config.suppressor.normal_tuning.max_dec_factor_lf,
815 default_config.suppressor.normal_tuning.max_dec_factor_lf);
816 ASSERT_NE(adjusted_config.suppressor.dominant_nearend_detection.enr_threshold,
817 default_config.suppressor.dominant_nearend_detection.enr_threshold);
818 ASSERT_NE(
819 adjusted_config.suppressor.dominant_nearend_detection.enr_exit_threshold,
820 default_config.suppressor.dominant_nearend_detection.enr_exit_threshold);
821 ASSERT_NE(adjusted_config.suppressor.dominant_nearend_detection.snr_threshold,
822 default_config.suppressor.dominant_nearend_detection.snr_threshold);
823 ASSERT_NE(adjusted_config.suppressor.dominant_nearend_detection.hold_duration,
824 default_config.suppressor.dominant_nearend_detection.hold_duration);
825 ASSERT_NE(
826 adjusted_config.suppressor.dominant_nearend_detection.trigger_threshold,
827 default_config.suppressor.dominant_nearend_detection.trigger_threshold);
828
829 EXPECT_FLOAT_EQ(
830 adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent, 0.1);
831 EXPECT_FLOAT_EQ(
832 adjusted_config.suppressor.nearend_tuning.mask_lf.enr_suppress, 0.2);
833 EXPECT_FLOAT_EQ(
834 adjusted_config.suppressor.nearend_tuning.mask_hf.enr_transparent, 0.3);
835 EXPECT_FLOAT_EQ(
836 adjusted_config.suppressor.nearend_tuning.mask_hf.enr_suppress, 0.4);
837 EXPECT_FLOAT_EQ(adjusted_config.suppressor.nearend_tuning.max_inc_factor,
838 0.5);
839 EXPECT_FLOAT_EQ(adjusted_config.suppressor.nearend_tuning.max_dec_factor_lf,
840 0.6);
841 EXPECT_FLOAT_EQ(
842 adjusted_config.suppressor.normal_tuning.mask_lf.enr_transparent, 0.7);
843 EXPECT_FLOAT_EQ(adjusted_config.suppressor.normal_tuning.mask_lf.enr_suppress,
844 0.8);
845 EXPECT_FLOAT_EQ(
846 adjusted_config.suppressor.normal_tuning.mask_hf.enr_transparent, 0.9);
847 EXPECT_FLOAT_EQ(adjusted_config.suppressor.normal_tuning.mask_hf.enr_suppress,
848 1.0);
849 EXPECT_FLOAT_EQ(adjusted_config.suppressor.normal_tuning.max_inc_factor, 1.1);
850 EXPECT_FLOAT_EQ(adjusted_config.suppressor.normal_tuning.max_dec_factor_lf,
851 1.2);
852 EXPECT_FLOAT_EQ(
853 adjusted_config.suppressor.dominant_nearend_detection.enr_threshold, 1.3);
854 EXPECT_FLOAT_EQ(
855 adjusted_config.suppressor.dominant_nearend_detection.enr_exit_threshold,
856 1.4);
857 EXPECT_FLOAT_EQ(
858 adjusted_config.suppressor.dominant_nearend_detection.snr_threshold, 1.5);
859 EXPECT_EQ(adjusted_config.suppressor.dominant_nearend_detection.hold_duration,
860 10);
861 EXPECT_EQ(
862 adjusted_config.suppressor.dominant_nearend_detection.trigger_threshold,
863 11);
864 }
865
866 // Testing the field trial-based override of the suppressor parameters for
867 // passing one parameter.
TEST(EchoCanceller3FieldTrials,Aec3SuppressorTuningOverrideOneParam)868 TEST(EchoCanceller3FieldTrials, Aec3SuppressorTuningOverrideOneParam) {
869 webrtc::test::ScopedFieldTrials field_trials(
870 "WebRTC-Aec3SuppressorTuningOverride/nearend_tuning_max_inc_factor:0.5/");
871
872 EchoCanceller3Config default_config;
873 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
874
875 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_transparent,
876 default_config.suppressor.nearend_tuning.mask_lf.enr_transparent);
877 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_lf.enr_suppress,
878 default_config.suppressor.nearend_tuning.mask_lf.enr_suppress);
879 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_hf.enr_transparent,
880 default_config.suppressor.nearend_tuning.mask_hf.enr_transparent);
881 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.mask_hf.enr_suppress,
882 default_config.suppressor.nearend_tuning.mask_hf.enr_suppress);
883 ASSERT_EQ(adjusted_config.suppressor.nearend_tuning.max_dec_factor_lf,
884 default_config.suppressor.nearend_tuning.max_dec_factor_lf);
885 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.mask_lf.enr_transparent,
886 default_config.suppressor.normal_tuning.mask_lf.enr_transparent);
887 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.mask_lf.enr_suppress,
888 default_config.suppressor.normal_tuning.mask_lf.enr_suppress);
889 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.mask_hf.enr_transparent,
890 default_config.suppressor.normal_tuning.mask_hf.enr_transparent);
891 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.mask_hf.enr_suppress,
892 default_config.suppressor.normal_tuning.mask_hf.enr_suppress);
893 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.max_inc_factor,
894 default_config.suppressor.normal_tuning.max_inc_factor);
895 ASSERT_EQ(adjusted_config.suppressor.normal_tuning.max_dec_factor_lf,
896 default_config.suppressor.normal_tuning.max_dec_factor_lf);
897 ASSERT_EQ(adjusted_config.suppressor.dominant_nearend_detection.enr_threshold,
898 default_config.suppressor.dominant_nearend_detection.enr_threshold);
899 ASSERT_EQ(
900 adjusted_config.suppressor.dominant_nearend_detection.enr_exit_threshold,
901 default_config.suppressor.dominant_nearend_detection.enr_exit_threshold);
902 ASSERT_EQ(adjusted_config.suppressor.dominant_nearend_detection.snr_threshold,
903 default_config.suppressor.dominant_nearend_detection.snr_threshold);
904 ASSERT_EQ(adjusted_config.suppressor.dominant_nearend_detection.hold_duration,
905 default_config.suppressor.dominant_nearend_detection.hold_duration);
906 ASSERT_EQ(
907 adjusted_config.suppressor.dominant_nearend_detection.trigger_threshold,
908 default_config.suppressor.dominant_nearend_detection.trigger_threshold);
909
910 ASSERT_NE(adjusted_config.suppressor.nearend_tuning.max_inc_factor,
911 default_config.suppressor.nearend_tuning.max_inc_factor);
912
913 EXPECT_FLOAT_EQ(adjusted_config.suppressor.nearend_tuning.max_inc_factor,
914 0.5);
915 }
916
917 // Testing the field trial-based that override the exponential decay parameters.
TEST(EchoCanceller3FieldTrials,Aec3UseNearendReverb)918 TEST(EchoCanceller3FieldTrials, Aec3UseNearendReverb) {
919 webrtc::test::ScopedFieldTrials field_trials(
920 "WebRTC-Aec3UseNearendReverbLen/default_len:0.9,nearend_len:0.8/");
921 EchoCanceller3Config default_config;
922 EchoCanceller3Config adjusted_config = AdjustConfig(default_config);
923 EXPECT_FLOAT_EQ(adjusted_config.ep_strength.default_len, 0.9);
924 EXPECT_FLOAT_EQ(adjusted_config.ep_strength.nearend_len, 0.8);
925 }
926
TEST(EchoCanceller3,DetectionOfProperStereo)927 TEST(EchoCanceller3, DetectionOfProperStereo) {
928 constexpr int kSampleRateHz = 16000;
929 constexpr int kNumChannels = 2;
930 AudioBuffer buffer(/*input_rate=*/kSampleRateHz,
931 /*input_num_channels=*/kNumChannels,
932 /*input_rate=*/kSampleRateHz,
933 /*buffer_num_channels=*/kNumChannels,
934 /*output_rate=*/kSampleRateHz,
935 /*output_num_channels=*/kNumChannels);
936
937 constexpr size_t kNumBlocksForMonoConfig = 1;
938 constexpr size_t kNumBlocksForSurroundConfig = 2;
939 EchoCanceller3Config mono_config;
940 absl::optional<EchoCanceller3Config> multichannel_config;
941
942 mono_config.multi_channel.detect_stereo_content = true;
943 mono_config.multi_channel.stereo_detection_threshold = 0.0f;
944 mono_config.multi_channel.stereo_detection_hysteresis_seconds = 0.0f;
945 multichannel_config = mono_config;
946 mono_config.filter.coarse_initial.length_blocks = kNumBlocksForMonoConfig;
947 multichannel_config->filter.coarse_initial.length_blocks =
948 kNumBlocksForSurroundConfig;
949
950 EchoCanceller3 aec3(mono_config, multichannel_config,
951 /*sample_rate_hz=*/kSampleRateHz,
952 /*num_render_channels=*/kNumChannels,
953 /*num_capture_input_channels=*/kNumChannels);
954
955 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
956 EXPECT_EQ(
957 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
958 kNumBlocksForMonoConfig);
959
960 RunAecInStereo(buffer, aec3, 100.0f, 100.0f);
961 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
962 EXPECT_EQ(
963 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
964 kNumBlocksForMonoConfig);
965
966 RunAecInStereo(buffer, aec3, 100.0f, 101.0f);
967 EXPECT_TRUE(aec3.StereoRenderProcessingActiveForTesting());
968 EXPECT_EQ(
969 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
970 kNumBlocksForSurroundConfig);
971 }
972
TEST(EchoCanceller3,DetectionOfProperStereoUsingThreshold)973 TEST(EchoCanceller3, DetectionOfProperStereoUsingThreshold) {
974 constexpr int kSampleRateHz = 16000;
975 constexpr int kNumChannels = 2;
976 AudioBuffer buffer(/*input_rate=*/kSampleRateHz,
977 /*input_num_channels=*/kNumChannels,
978 /*input_rate=*/kSampleRateHz,
979 /*buffer_num_channels=*/kNumChannels,
980 /*output_rate=*/kSampleRateHz,
981 /*output_num_channels=*/kNumChannels);
982
983 constexpr size_t kNumBlocksForMonoConfig = 1;
984 constexpr size_t kNumBlocksForSurroundConfig = 2;
985 EchoCanceller3Config mono_config;
986 absl::optional<EchoCanceller3Config> multichannel_config;
987
988 constexpr float kStereoDetectionThreshold = 2.0f;
989 mono_config.multi_channel.detect_stereo_content = true;
990 mono_config.multi_channel.stereo_detection_threshold =
991 kStereoDetectionThreshold;
992 mono_config.multi_channel.stereo_detection_hysteresis_seconds = 0.0f;
993 multichannel_config = mono_config;
994 mono_config.filter.coarse_initial.length_blocks = kNumBlocksForMonoConfig;
995 multichannel_config->filter.coarse_initial.length_blocks =
996 kNumBlocksForSurroundConfig;
997
998 EchoCanceller3 aec3(mono_config, multichannel_config,
999 /*sample_rate_hz=*/kSampleRateHz,
1000 /*num_render_channels=*/kNumChannels,
1001 /*num_capture_input_channels=*/kNumChannels);
1002
1003 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
1004 EXPECT_EQ(
1005 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1006 kNumBlocksForMonoConfig);
1007
1008 RunAecInStereo(buffer, aec3, 100.0f,
1009 100.0f + kStereoDetectionThreshold - 1.0f);
1010 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
1011 EXPECT_EQ(
1012 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1013 kNumBlocksForMonoConfig);
1014
1015 RunAecInStereo(buffer, aec3, 100.0f,
1016 100.0f + kStereoDetectionThreshold + 10.0f);
1017 EXPECT_TRUE(aec3.StereoRenderProcessingActiveForTesting());
1018 EXPECT_EQ(
1019 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1020 kNumBlocksForSurroundConfig);
1021 }
1022
TEST(EchoCanceller3,DetectionOfProperStereoUsingHysteresis)1023 TEST(EchoCanceller3, DetectionOfProperStereoUsingHysteresis) {
1024 constexpr int kSampleRateHz = 16000;
1025 constexpr int kNumChannels = 2;
1026 AudioBuffer buffer(/*input_rate=*/kSampleRateHz,
1027 /*input_num_channels=*/kNumChannels,
1028 /*input_rate=*/kSampleRateHz,
1029 /*buffer_num_channels=*/kNumChannels,
1030 /*output_rate=*/kSampleRateHz,
1031 /*output_num_channels=*/kNumChannels);
1032
1033 constexpr size_t kNumBlocksForMonoConfig = 1;
1034 constexpr size_t kNumBlocksForSurroundConfig = 2;
1035 EchoCanceller3Config mono_config;
1036 absl::optional<EchoCanceller3Config> surround_config;
1037
1038 mono_config.multi_channel.detect_stereo_content = true;
1039 mono_config.multi_channel.stereo_detection_hysteresis_seconds = 0.5f;
1040 surround_config = mono_config;
1041 mono_config.filter.coarse_initial.length_blocks = kNumBlocksForMonoConfig;
1042 surround_config->filter.coarse_initial.length_blocks =
1043 kNumBlocksForSurroundConfig;
1044
1045 EchoCanceller3 aec3(mono_config, surround_config,
1046 /*sample_rate_hz=*/kSampleRateHz,
1047 /*num_render_channels=*/kNumChannels,
1048 /*num_capture_input_channels=*/kNumChannels);
1049
1050 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
1051 EXPECT_EQ(
1052 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1053 kNumBlocksForMonoConfig);
1054
1055 RunAecInStereo(buffer, aec3, 100.0f, 100.0f);
1056 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
1057 EXPECT_EQ(
1058 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1059 kNumBlocksForMonoConfig);
1060
1061 constexpr int kNumFramesPerSecond = 100;
1062 for (int k = 0;
1063 k < static_cast<int>(
1064 kNumFramesPerSecond *
1065 mono_config.multi_channel.stereo_detection_hysteresis_seconds);
1066 ++k) {
1067 RunAecInStereo(buffer, aec3, 100.0f, 101.0f);
1068 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
1069 EXPECT_EQ(
1070 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1071 kNumBlocksForMonoConfig);
1072 }
1073
1074 RunAecInStereo(buffer, aec3, 100.0f, 101.0f);
1075 EXPECT_TRUE(aec3.StereoRenderProcessingActiveForTesting());
1076 EXPECT_EQ(
1077 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1078 kNumBlocksForSurroundConfig);
1079 }
1080
TEST(EchoCanceller3,StereoContentDetectionForMonoSignals)1081 TEST(EchoCanceller3, StereoContentDetectionForMonoSignals) {
1082 constexpr int kSampleRateHz = 16000;
1083 constexpr int kNumChannels = 2;
1084 AudioBuffer buffer(/*input_rate=*/kSampleRateHz,
1085 /*input_num_channels=*/kNumChannels,
1086 /*input_rate=*/kSampleRateHz,
1087 /*buffer_num_channels=*/kNumChannels,
1088 /*output_rate=*/kSampleRateHz,
1089 /*output_num_channels=*/kNumChannels);
1090
1091 constexpr size_t kNumBlocksForMonoConfig = 1;
1092 constexpr size_t kNumBlocksForSurroundConfig = 2;
1093 EchoCanceller3Config mono_config;
1094 absl::optional<EchoCanceller3Config> multichannel_config;
1095
1096 for (bool detect_stereo_content : {false, true}) {
1097 mono_config.multi_channel.detect_stereo_content = detect_stereo_content;
1098 multichannel_config = mono_config;
1099 mono_config.filter.coarse_initial.length_blocks = kNumBlocksForMonoConfig;
1100 multichannel_config->filter.coarse_initial.length_blocks =
1101 kNumBlocksForSurroundConfig;
1102
1103 AudioBuffer mono_buffer(/*input_rate=*/kSampleRateHz,
1104 /*input_num_channels=*/1,
1105 /*input_rate=*/kSampleRateHz,
1106 /*buffer_num_channels=*/1,
1107 /*output_rate=*/kSampleRateHz,
1108 /*output_num_channels=*/1);
1109
1110 EchoCanceller3 aec3(mono_config, multichannel_config,
1111 /*sample_rate_hz=*/kSampleRateHz,
1112 /*num_render_channels=*/1,
1113 /*num_capture_input_channels=*/1);
1114
1115 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
1116 EXPECT_EQ(
1117 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1118 kNumBlocksForMonoConfig);
1119
1120 RunAecInSMono(mono_buffer, aec3, 100.0f);
1121 EXPECT_FALSE(aec3.StereoRenderProcessingActiveForTesting());
1122 EXPECT_EQ(
1123 aec3.GetActiveConfigForTesting().filter.coarse_initial.length_blocks,
1124 kNumBlocksForMonoConfig);
1125 }
1126 }
1127
1128 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
1129
TEST(EchoCanceller3InputCheckDeathTest,WrongCaptureNumBandsCheckVerification)1130 TEST(EchoCanceller3InputCheckDeathTest, WrongCaptureNumBandsCheckVerification) {
1131 for (auto rate : {16000, 32000, 48000}) {
1132 SCOPED_TRACE(ProduceDebugText(rate));
1133 EchoCanceller3Tester(rate).RunProcessCaptureNumBandsCheckVerification();
1134 }
1135 }
1136
1137 // Verifiers that the verification for null input to the capture processing api
1138 // call works.
TEST(EchoCanceller3InputCheckDeathTest,NullCaptureProcessingParameter)1139 TEST(EchoCanceller3InputCheckDeathTest, NullCaptureProcessingParameter) {
1140 EXPECT_DEATH(
1141 EchoCanceller3(EchoCanceller3Config(),
1142 /*multichannel_config_=*/absl::nullopt, 16000, 1, 1)
1143 .ProcessCapture(nullptr, false),
1144 "");
1145 }
1146
1147 // Verifies the check for correct sample rate.
1148 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
1149 // tests on test bots has been fixed.
TEST(EchoCanceller3InputCheckDeathTest,DISABLED_WrongSampleRate)1150 TEST(EchoCanceller3InputCheckDeathTest, DISABLED_WrongSampleRate) {
1151 ApmDataDumper data_dumper(0);
1152 EXPECT_DEATH(
1153 EchoCanceller3(EchoCanceller3Config(),
1154 /*multichannel_config_=*/absl::nullopt, 8001, 1, 1),
1155 "");
1156 }
1157
1158 #endif
1159
1160 } // namespace webrtc
1161