/* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/audio_processing/aec3/block_processor.h" #include #include #include #include #include "modules/audio_processing/aec3/aec3_common.h" #include "modules/audio_processing/aec3/mock/mock_echo_remover.h" #include "modules/audio_processing/aec3/mock/mock_render_delay_buffer.h" #include "modules/audio_processing/aec3/mock/mock_render_delay_controller.h" #include "modules/audio_processing/test/echo_canceller_test_tools.h" #include "rtc_base/checks.h" #include "rtc_base/random.h" #include "test/gmock.h" #include "test/gtest.h" namespace webrtc { namespace { using testing::AtLeast; using testing::Return; using testing::StrictMock; using testing::_; // Verifies that the basic BlockProcessor functionality works and that the API // methods are callable. void RunBasicSetupAndApiCallTest(int sample_rate_hz) { std::unique_ptr block_processor( BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz)); std::vector> block(NumBandsForRate(sample_rate_hz), std::vector(kBlockSize, 0.f)); block_processor->BufferRender(block); block_processor->ProcessCapture(false, false, &block); block_processor->UpdateEchoLeakageStatus(false); } #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) void RunRenderBlockSizeVerificationTest(int sample_rate_hz) { std::unique_ptr block_processor( BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz)); std::vector> block( NumBandsForRate(sample_rate_hz), std::vector(kBlockSize - 1, 0.f)); EXPECT_DEATH(block_processor->BufferRender(block), ""); } void RunCaptureBlockSizeVerificationTest(int sample_rate_hz) { std::unique_ptr block_processor( BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz)); std::vector> block( NumBandsForRate(sample_rate_hz), std::vector(kBlockSize - 1, 0.f)); EXPECT_DEATH(block_processor->ProcessCapture(false, false, &block), ""); } void RunRenderNumBandsVerificationTest(int sample_rate_hz) { const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3 ? NumBandsForRate(sample_rate_hz) + 1 : 1; std::unique_ptr block_processor( BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz)); std::vector> block(wrong_num_bands, std::vector(kBlockSize, 0.f)); EXPECT_DEATH(block_processor->BufferRender(block), ""); } void RunCaptureNumBandsVerificationTest(int sample_rate_hz) { const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3 ? NumBandsForRate(sample_rate_hz) + 1 : 1; std::unique_ptr block_processor( BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz)); std::vector> block(wrong_num_bands, std::vector(kBlockSize, 0.f)); EXPECT_DEATH(block_processor->ProcessCapture(false, false, &block), ""); } #endif std::string ProduceDebugText(int sample_rate_hz) { std::ostringstream ss; ss << "Sample rate: " << sample_rate_hz; return ss.str(); } } // namespace // Verifies that the delay controller functionality is properly integrated with // the render delay buffer inside block processor. // TODO(peah): Activate the unittest once the required code has been landed. TEST(BlockProcessor, DISABLED_DelayControllerIntegration) { constexpr size_t kNumBlocks = 310; constexpr size_t kDelayInSamples = 640; constexpr size_t kDelayHeadroom = 1; constexpr size_t kDelayInBlocks = kDelayInSamples / kBlockSize - kDelayHeadroom; Random random_generator(42U); for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); std::unique_ptr> render_delay_buffer_mock( new StrictMock(rate)); EXPECT_CALL(*render_delay_buffer_mock, Insert(_)) .Times(kNumBlocks) .WillRepeatedly(Return(RenderDelayBuffer::BufferingEvent::kNone)); EXPECT_CALL(*render_delay_buffer_mock, SetDelay(kDelayInBlocks)) .Times(AtLeast(1)); EXPECT_CALL(*render_delay_buffer_mock, MaxDelay()).WillOnce(Return(30)); EXPECT_CALL(*render_delay_buffer_mock, Delay()) .Times(kNumBlocks + 1) .WillRepeatedly(Return(0)); std::unique_ptr block_processor(BlockProcessor::Create( EchoCanceller3Config(), rate, std::move(render_delay_buffer_mock))); std::vector> render_block( NumBandsForRate(rate), std::vector(kBlockSize, 0.f)); std::vector> capture_block( NumBandsForRate(rate), std::vector(kBlockSize, 0.f)); DelayBuffer signal_delay_buffer(kDelayInSamples); for (size_t k = 0; k < kNumBlocks; ++k) { RandomizeSampleVector(&random_generator, render_block[0]); signal_delay_buffer.Delay(render_block[0], capture_block[0]); block_processor->BufferRender(render_block); block_processor->ProcessCapture(false, false, &capture_block); } } } // Verifies that BlockProcessor submodules are called in a proper manner. TEST(BlockProcessor, DISABLED_SubmoduleIntegration) { constexpr size_t kNumBlocks = 310; Random random_generator(42U); for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); std::unique_ptr> render_delay_buffer_mock( new StrictMock(rate)); std::unique_ptr< testing::StrictMock> render_delay_controller_mock( new StrictMock()); std::unique_ptr> echo_remover_mock(new StrictMock()); EXPECT_CALL(*render_delay_buffer_mock, Insert(_)) .Times(kNumBlocks - 1) .WillRepeatedly(Return(RenderDelayBuffer::BufferingEvent::kNone)); EXPECT_CALL(*render_delay_buffer_mock, PrepareCaptureProcessing()) .Times(kNumBlocks); EXPECT_CALL(*render_delay_buffer_mock, SetDelay(9)).Times(AtLeast(1)); EXPECT_CALL(*render_delay_buffer_mock, Delay()) .Times(kNumBlocks) .WillRepeatedly(Return(0)); EXPECT_CALL(*render_delay_controller_mock, GetDelay(_, _)) .Times(kNumBlocks); EXPECT_CALL(*echo_remover_mock, ProcessCapture(_, _, _, _)) .Times(kNumBlocks); EXPECT_CALL(*echo_remover_mock, UpdateEchoLeakageStatus(_)) .Times(kNumBlocks); std::unique_ptr block_processor(BlockProcessor::Create( EchoCanceller3Config(), rate, std::move(render_delay_buffer_mock), std::move(render_delay_controller_mock), std::move(echo_remover_mock))); std::vector> render_block( NumBandsForRate(rate), std::vector(kBlockSize, 0.f)); std::vector> capture_block( NumBandsForRate(rate), std::vector(kBlockSize, 0.f)); DelayBuffer signal_delay_buffer(640); for (size_t k = 0; k < kNumBlocks; ++k) { RandomizeSampleVector(&random_generator, render_block[0]); signal_delay_buffer.Delay(render_block[0], capture_block[0]); block_processor->BufferRender(render_block); block_processor->ProcessCapture(false, false, &capture_block); block_processor->UpdateEchoLeakageStatus(false); } } } TEST(BlockProcessor, BasicSetupAndApiCalls) { for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); RunBasicSetupAndApiCallTest(rate); } } #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) // TODO(gustaf): Re-enable the test once the issue with memory leaks during // DEATH tests on test bots has been fixed. TEST(BlockProcessor, DISABLED_VerifyRenderBlockSizeCheck) { for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); RunRenderBlockSizeVerificationTest(rate); } } TEST(BlockProcessor, VerifyCaptureBlockSizeCheck) { for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); RunCaptureBlockSizeVerificationTest(rate); } } TEST(BlockProcessor, VerifyRenderNumBandsCheck) { for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); RunRenderNumBandsVerificationTest(rate); } } // TODO(peah): Verify the check for correct number of bands in the capture // signal. TEST(BlockProcessor, VerifyCaptureNumBandsCheck) { for (auto rate : {8000, 16000, 32000, 48000}) { SCOPED_TRACE(ProduceDebugText(rate)); RunCaptureNumBandsVerificationTest(rate); } } // Verifiers that the verification for null ProcessCapture input works. TEST(BlockProcessor, NullProcessCaptureParameter) { EXPECT_DEATH(std::unique_ptr( BlockProcessor::Create(EchoCanceller3Config(), 8000)) ->ProcessCapture(false, false, nullptr), ""); } // Verifies the check for correct sample rate. // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH // tests on test bots has been fixed. TEST(BlockProcessor, DISABLED_WrongSampleRate) { EXPECT_DEATH(std::unique_ptr( BlockProcessor::Create(EchoCanceller3Config(), 8001)), ""); } #endif } // namespace webrtc