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