block_processor_unittest.cc (15252B)
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/block_processor.h" 12 13 #include <cstddef> 14 #include <memory> 15 #include <optional> 16 #include <string> 17 #include <utility> 18 19 #include "api/array_view.h" 20 #include "api/audio/echo_canceller3_config.h" 21 #include "api/environment/environment.h" 22 #include "api/environment/environment_factory.h" 23 #include "modules/audio_processing/aec3/aec3_common.h" 24 #include "modules/audio_processing/aec3/block.h" 25 #include "modules/audio_processing/aec3/delay_estimate.h" 26 #include "modules/audio_processing/aec3/echo_path_variability.h" 27 #include "modules/audio_processing/aec3/mock/mock_echo_remover.h" 28 #include "modules/audio_processing/aec3/mock/mock_render_delay_buffer.h" 29 #include "modules/audio_processing/aec3/mock/mock_render_delay_controller.h" 30 #include "modules/audio_processing/aec3/render_buffer.h" 31 #include "modules/audio_processing/aec3/render_delay_buffer.h" 32 #include "modules/audio_processing/test/echo_canceller_test_tools.h" 33 #include "rtc_base/checks.h" 34 #include "rtc_base/random.h" 35 #include "rtc_base/strings/string_builder.h" 36 #include "test/gmock.h" 37 #include "test/gtest.h" 38 39 namespace webrtc { 40 namespace { 41 42 using ::testing::_; 43 using ::testing::AtLeast; 44 using ::testing::NiceMock; 45 using ::testing::Return; 46 using ::testing::StrictMock; 47 48 // Verifies that the basic BlockProcessor functionality works and that the API 49 // methods are callable. 50 void RunBasicSetupAndApiCallTest(const Environment& env, 51 int sample_rate_hz, 52 int num_iterations) { 53 constexpr size_t kNumRenderChannels = 1; 54 constexpr size_t kNumCaptureChannels = 1; 55 56 std::unique_ptr<BlockProcessor> block_processor = BlockProcessor::Create( 57 env, EchoCanceller3Config(), sample_rate_hz, kNumRenderChannels, 58 kNumCaptureChannels, /*neural_residual_echo_estimator=*/nullptr); 59 Block block(NumBandsForRate(sample_rate_hz), kNumRenderChannels, 1000.f); 60 for (int k = 0; k < num_iterations; ++k) { 61 block_processor->BufferRender(block); 62 block_processor->ProcessCapture(false, false, nullptr, &block); 63 block_processor->UpdateEchoLeakageStatus(false); 64 } 65 } 66 67 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 68 void RunRenderBlockSizeVerificationTest(const Environment& env, 69 int sample_rate_hz) { 70 constexpr size_t kNumRenderChannels = 1; 71 constexpr size_t kNumCaptureChannels = 1; 72 73 std::unique_ptr<BlockProcessor> block_processor = BlockProcessor::Create( 74 env, EchoCanceller3Config(), sample_rate_hz, kNumRenderChannels, 75 kNumCaptureChannels, /*neural_residual_echo_estimator=*/nullptr); 76 Block block(NumBandsForRate(sample_rate_hz), kNumRenderChannels); 77 78 EXPECT_DEATH(block_processor->BufferRender(block), ""); 79 } 80 81 void RunRenderNumBandsVerificationTest(const Environment& env, 82 int sample_rate_hz) { 83 constexpr size_t kNumRenderChannels = 1; 84 constexpr size_t kNumCaptureChannels = 1; 85 86 const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3 87 ? NumBandsForRate(sample_rate_hz) + 1 88 : 1; 89 std::unique_ptr<BlockProcessor> block_processor = BlockProcessor::Create( 90 env, EchoCanceller3Config(), sample_rate_hz, kNumRenderChannels, 91 kNumCaptureChannels, /*neural_residual_echo_estimator=*/nullptr); 92 Block block(wrong_num_bands, kNumRenderChannels); 93 94 EXPECT_DEATH(block_processor->BufferRender(block), ""); 95 } 96 97 void RunCaptureNumBandsVerificationTest(const Environment& env, 98 int sample_rate_hz) { 99 constexpr size_t kNumRenderChannels = 1; 100 constexpr size_t kNumCaptureChannels = 1; 101 102 const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3 103 ? NumBandsForRate(sample_rate_hz) + 1 104 : 1; 105 std::unique_ptr<BlockProcessor> block_processor = BlockProcessor::Create( 106 env, EchoCanceller3Config(), sample_rate_hz, kNumRenderChannels, 107 kNumCaptureChannels, /*neural_residual_echo_estimator=*/nullptr); 108 Block block(wrong_num_bands, kNumRenderChannels); 109 110 EXPECT_DEATH(block_processor->ProcessCapture(false, false, nullptr, &block), 111 ""); 112 } 113 #endif 114 115 std::string ProduceDebugText(int sample_rate_hz) { 116 StringBuilder ss; 117 ss << "Sample rate: " << sample_rate_hz; 118 return ss.Release(); 119 } 120 121 void FillSampleVector(int call_counter, int delay, ArrayView<float> samples) { 122 for (size_t i = 0; i < samples.size(); ++i) { 123 samples[i] = (call_counter - delay) * 10000.0f + i; 124 } 125 } 126 127 } // namespace 128 129 // Verifies that the delay controller functionality is properly integrated with 130 // the render delay buffer inside block processor. 131 // TODO(peah): Activate the unittest once the required code has been landed. 132 TEST(BlockProcessor, DISABLED_DelayControllerIntegration) { 133 constexpr size_t kNumRenderChannels = 1; 134 constexpr size_t kNumCaptureChannels = 1; 135 constexpr size_t kNumBlocks = 310; 136 constexpr size_t kDelayInSamples = 640; 137 constexpr size_t kDelayHeadroom = 1; 138 constexpr size_t kDelayInBlocks = 139 kDelayInSamples / kBlockSize - kDelayHeadroom; 140 const Environment env = CreateEnvironment(); 141 Random random_generator(42U); 142 for (auto rate : {16000, 32000, 48000}) { 143 SCOPED_TRACE(ProduceDebugText(rate)); 144 std::unique_ptr<testing::StrictMock<test::MockRenderDelayBuffer>> 145 render_delay_buffer_mock( 146 new StrictMock<test::MockRenderDelayBuffer>(rate, 1)); 147 EXPECT_CALL(*render_delay_buffer_mock, Insert(_)) 148 .Times(kNumBlocks) 149 .WillRepeatedly(Return(RenderDelayBuffer::BufferingEvent::kNone)); 150 EXPECT_CALL(*render_delay_buffer_mock, AlignFromDelay(kDelayInBlocks)) 151 .Times(AtLeast(1)); 152 EXPECT_CALL(*render_delay_buffer_mock, MaxDelay()).WillOnce(Return(30)); 153 EXPECT_CALL(*render_delay_buffer_mock, Delay()) 154 .Times(kNumBlocks + 1) 155 .WillRepeatedly(Return(0)); 156 std::unique_ptr<BlockProcessor> block_processor = BlockProcessor::Create( 157 env, EchoCanceller3Config(), rate, kNumRenderChannels, 158 kNumCaptureChannels, std::move(render_delay_buffer_mock), 159 /*neural_residual_echo_estimator=*/nullptr); 160 161 Block render_block(NumBandsForRate(rate), kNumRenderChannels); 162 Block capture_block(NumBandsForRate(rate), kNumCaptureChannels); 163 DelayBuffer<float> signal_delay_buffer(kDelayInSamples); 164 for (size_t k = 0; k < kNumBlocks; ++k) { 165 RandomizeSampleVector(&random_generator, 166 render_block.View(/*band=*/0, /*capture=*/0)); 167 signal_delay_buffer.Delay(render_block.View(/*band=*/0, /*capture=*/0), 168 capture_block.View(/*band=*/0, /*capture=*/0)); 169 block_processor->BufferRender(render_block); 170 block_processor->ProcessCapture(false, false, nullptr, &capture_block); 171 } 172 } 173 } 174 175 // Verifies that BlockProcessor submodules are called in a proper manner. 176 TEST(BlockProcessor, DISABLED_SubmoduleIntegration) { 177 constexpr size_t kNumBlocks = 310; 178 constexpr size_t kNumRenderChannels = 1; 179 constexpr size_t kNumCaptureChannels = 1; 180 181 Random random_generator(42U); 182 for (auto rate : {16000, 32000, 48000}) { 183 SCOPED_TRACE(ProduceDebugText(rate)); 184 std::unique_ptr<testing::StrictMock<test::MockRenderDelayBuffer>> 185 render_delay_buffer_mock( 186 new StrictMock<test::MockRenderDelayBuffer>(rate, 1)); 187 std::unique_ptr<::testing::StrictMock<test::MockRenderDelayController>> 188 render_delay_controller_mock( 189 new StrictMock<test::MockRenderDelayController>()); 190 std::unique_ptr<testing::StrictMock<test::MockEchoRemover>> 191 echo_remover_mock(new StrictMock<test::MockEchoRemover>()); 192 193 EXPECT_CALL(*render_delay_buffer_mock, Insert(_)) 194 .Times(kNumBlocks - 1) 195 .WillRepeatedly(Return(RenderDelayBuffer::BufferingEvent::kNone)); 196 EXPECT_CALL(*render_delay_buffer_mock, PrepareCaptureProcessing()) 197 .Times(kNumBlocks); 198 EXPECT_CALL(*render_delay_buffer_mock, AlignFromDelay(9)).Times(AtLeast(1)); 199 EXPECT_CALL(*render_delay_buffer_mock, Delay()) 200 .Times(kNumBlocks) 201 .WillRepeatedly(Return(0)); 202 EXPECT_CALL(*render_delay_controller_mock, GetDelay(_, _, _)) 203 .Times(kNumBlocks); 204 EXPECT_CALL(*echo_remover_mock, ProcessCapture(_, _, _, _, _, _)) 205 .Times(kNumBlocks); 206 EXPECT_CALL(*echo_remover_mock, UpdateEchoLeakageStatus(_)) 207 .Times(kNumBlocks); 208 209 std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create( 210 EchoCanceller3Config(), rate, kNumRenderChannels, kNumCaptureChannels, 211 std::move(render_delay_buffer_mock), 212 std::move(render_delay_controller_mock), std::move(echo_remover_mock))); 213 214 Block render_block(NumBandsForRate(rate), kNumRenderChannels); 215 Block capture_block(NumBandsForRate(rate), kNumCaptureChannels); 216 DelayBuffer<float> signal_delay_buffer(640); 217 for (size_t k = 0; k < kNumBlocks; ++k) { 218 RandomizeSampleVector(&random_generator, 219 render_block.View(/*band=*/0, /*capture=*/0)); 220 signal_delay_buffer.Delay(render_block.View(/*band=*/0, /*capture=*/0), 221 capture_block.View(/*band=*/0, /*capture=*/0)); 222 block_processor->BufferRender(render_block); 223 block_processor->ProcessCapture(false, false, nullptr, &capture_block); 224 block_processor->UpdateEchoLeakageStatus(false); 225 } 226 } 227 } 228 229 TEST(BlockProcessor, BasicSetupAndApiCalls) { 230 const Environment env = CreateEnvironment(); 231 for (auto rate : {16000, 32000, 48000}) { 232 SCOPED_TRACE(ProduceDebugText(rate)); 233 RunBasicSetupAndApiCallTest(env, rate, 1); 234 } 235 } 236 237 TEST(BlockProcessor, TestLongerCall) { 238 RunBasicSetupAndApiCallTest(CreateEnvironment(), 16000, 239 20 * kNumBlocksPerSecond); 240 } 241 242 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 243 // TODO(gustaf): Re-enable the test once the issue with memory leaks during 244 // DEATH tests on test bots has been fixed. 245 TEST(BlockProcessorDeathTest, DISABLED_VerifyRenderBlockSizeCheck) { 246 const Environment env = CreateEnvironment(); 247 for (auto rate : {16000, 32000, 48000}) { 248 SCOPED_TRACE(ProduceDebugText(rate)); 249 RunRenderBlockSizeVerificationTest(env, rate); 250 } 251 } 252 253 TEST(BlockProcessorDeathTest, VerifyRenderNumBandsCheck) { 254 const Environment env = CreateEnvironment(); 255 for (auto rate : {16000, 32000, 48000}) { 256 SCOPED_TRACE(ProduceDebugText(rate)); 257 RunRenderNumBandsVerificationTest(env, rate); 258 } 259 } 260 261 // TODO(peah): Verify the check for correct number of bands in the capture 262 // signal. 263 TEST(BlockProcessorDeathTest, VerifyCaptureNumBandsCheck) { 264 const Environment env = CreateEnvironment(); 265 for (auto rate : {16000, 32000, 48000}) { 266 SCOPED_TRACE(ProduceDebugText(rate)); 267 RunCaptureNumBandsVerificationTest(env, rate); 268 } 269 } 270 271 // Verifiers that the verification for null ProcessCapture input works. 272 TEST(BlockProcessorDeathTest, NullProcessCaptureParameter) { 273 EXPECT_DEATH( 274 BlockProcessor::Create(CreateEnvironment(), EchoCanceller3Config(), 16000, 275 1, 1, /*neural_residual_echo_estimator=*/nullptr) 276 ->ProcessCapture(false, false, nullptr, nullptr), 277 ""); 278 } 279 280 // Verifies the check for correct sample rate. 281 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH 282 // tests on test bots has been fixed. 283 TEST(BlockProcessor, DISABLED_WrongSampleRate) { 284 EXPECT_DEATH( 285 BlockProcessor::Create(CreateEnvironment(), EchoCanceller3Config(), 8001, 286 1, 1, /*neural_residual_echo_estimator=*/nullptr), 287 ""); 288 } 289 290 #endif 291 292 // Verifies that external delay estimator delays are applied correctly when a 293 // call begins with a sequence of capture blocks. 294 TEST(BlockProcessor, ExternalDelayAppliedCorrectlyWithInitialCaptureCalls) { 295 constexpr int kNumRenderChannels = 1; 296 constexpr int kNumCaptureChannels = 1; 297 constexpr int kSampleRateHz = 16000; 298 299 EchoCanceller3Config config; 300 config.delay.use_external_delay_estimator = true; 301 302 std::unique_ptr<RenderDelayBuffer> delay_buffer( 303 RenderDelayBuffer::Create(config, kSampleRateHz, kNumRenderChannels)); 304 305 std::unique_ptr<testing::NiceMock<test::MockEchoRemover>> echo_remover_mock( 306 new NiceMock<test::MockEchoRemover>()); 307 test::MockEchoRemover* echo_remover_mock_pointer = echo_remover_mock.get(); 308 309 std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create( 310 config, kSampleRateHz, kNumRenderChannels, kNumCaptureChannels, 311 std::move(delay_buffer), /*delay_controller=*/nullptr, 312 std::move(echo_remover_mock))); 313 314 Block render_block(NumBandsForRate(kSampleRateHz), kNumRenderChannels); 315 Block capture_block(NumBandsForRate(kSampleRateHz), kNumCaptureChannels); 316 317 // Process... 318 // - 10 capture calls, where no render data is available, 319 // - 10 render calls, populating the buffer, 320 // - 2 capture calls, verifying that the delay was applied correctly. 321 constexpr int kDelayInBlocks = 5; 322 constexpr int kDelayInMs = 20; 323 block_processor->SetAudioBufferDelay(kDelayInMs); 324 325 int capture_call_counter = 0; 326 int render_call_counter = 0; 327 for (size_t k = 0; k < 10; ++k) { 328 FillSampleVector(++capture_call_counter, kDelayInBlocks, 329 capture_block.View(/*band=*/0, /*capture=*/0)); 330 block_processor->ProcessCapture(false, false, nullptr, &capture_block); 331 } 332 for (size_t k = 0; k < 10; ++k) { 333 FillSampleVector(++render_call_counter, 0, 334 render_block.View(/*band=*/0, /*capture=*/0)); 335 block_processor->BufferRender(render_block); 336 } 337 338 EXPECT_CALL(*echo_remover_mock_pointer, ProcessCapture) 339 .WillRepeatedly([](EchoPathVariability /*echo_path_variability*/, 340 bool /*capture_signal_saturation*/, 341 const std::optional<DelayEstimate>& /*external_delay*/, 342 RenderBuffer* render_buffer, Block* /*linear_output*/, 343 Block* capture) { 344 const auto& render = render_buffer->GetBlock(0); 345 const auto render_view = render.View(/*band=*/0, /*channel=*/0); 346 const auto capture_view = capture->View(/*band=*/0, /*channel=*/0); 347 for (size_t i = 0; i < kBlockSize; ++i) { 348 EXPECT_FLOAT_EQ(render_view[i], capture_view[i]); 349 } 350 }); 351 352 FillSampleVector(++capture_call_counter, kDelayInBlocks, 353 capture_block.View(/*band=*/0, /*capture=*/0)); 354 block_processor->ProcessCapture(false, false, nullptr, &capture_block); 355 356 FillSampleVector(++capture_call_counter, kDelayInBlocks, 357 capture_block.View(/*band=*/0, /*capture=*/0)); 358 block_processor->ProcessCapture(false, false, nullptr, &capture_block); 359 } 360 361 } // namespace webrtc