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