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::Return;
34 using ::testing::StrictMock;
35
36 // Verifies that the basic BlockProcessor functionality works and that the API
37 // methods are callable.
RunBasicSetupAndApiCallTest(int sample_rate_hz,int num_iterations)38 void RunBasicSetupAndApiCallTest(int sample_rate_hz, int num_iterations) {
39 constexpr size_t kNumRenderChannels = 1;
40 constexpr size_t kNumCaptureChannels = 1;
41
42 std::unique_ptr<BlockProcessor> block_processor(
43 BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
44 kNumRenderChannels, kNumCaptureChannels));
45 std::vector<std::vector<std::vector<float>>> block(
46 NumBandsForRate(sample_rate_hz),
47 std::vector<std::vector<float>>(kNumRenderChannels,
48 std::vector<float>(kBlockSize, 1000.f)));
49 for (int k = 0; k < num_iterations; ++k) {
50 block_processor->BufferRender(block);
51 block_processor->ProcessCapture(false, false, nullptr, &block);
52 block_processor->UpdateEchoLeakageStatus(false);
53 }
54 }
55
56 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
RunRenderBlockSizeVerificationTest(int sample_rate_hz)57 void RunRenderBlockSizeVerificationTest(int sample_rate_hz) {
58 constexpr size_t kNumRenderChannels = 1;
59 constexpr size_t kNumCaptureChannels = 1;
60
61 std::unique_ptr<BlockProcessor> block_processor(
62 BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
63 kNumRenderChannels, kNumCaptureChannels));
64 std::vector<std::vector<std::vector<float>>> block(
65 NumBandsForRate(sample_rate_hz),
66 std::vector<std::vector<float>>(kNumRenderChannels,
67 std::vector<float>(kBlockSize - 1, 0.f)));
68
69 EXPECT_DEATH(block_processor->BufferRender(block), "");
70 }
71
RunCaptureBlockSizeVerificationTest(int sample_rate_hz)72 void RunCaptureBlockSizeVerificationTest(int sample_rate_hz) {
73 constexpr size_t kNumRenderChannels = 1;
74 constexpr size_t kNumCaptureChannels = 1;
75
76 std::unique_ptr<BlockProcessor> block_processor(
77 BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
78 kNumRenderChannels, kNumCaptureChannels));
79 std::vector<std::vector<std::vector<float>>> block(
80 NumBandsForRate(sample_rate_hz),
81 std::vector<std::vector<float>>(kNumRenderChannels,
82 std::vector<float>(kBlockSize - 1, 0.f)));
83
84 EXPECT_DEATH(block_processor->ProcessCapture(false, false, nullptr, &block),
85 "");
86 }
87
RunRenderNumBandsVerificationTest(int sample_rate_hz)88 void RunRenderNumBandsVerificationTest(int sample_rate_hz) {
89 constexpr size_t kNumRenderChannels = 1;
90 constexpr size_t kNumCaptureChannels = 1;
91
92 const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
93 ? NumBandsForRate(sample_rate_hz) + 1
94 : 1;
95 std::unique_ptr<BlockProcessor> block_processor(
96 BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
97 kNumRenderChannels, kNumCaptureChannels));
98 std::vector<std::vector<std::vector<float>>> block(
99 wrong_num_bands,
100 std::vector<std::vector<float>>(kNumRenderChannels,
101 std::vector<float>(kBlockSize, 0.f)));
102
103 EXPECT_DEATH(block_processor->BufferRender(block), "");
104 }
105
RunCaptureNumBandsVerificationTest(int sample_rate_hz)106 void RunCaptureNumBandsVerificationTest(int sample_rate_hz) {
107 constexpr size_t kNumRenderChannels = 1;
108 constexpr size_t kNumCaptureChannels = 1;
109
110 const size_t wrong_num_bands = NumBandsForRate(sample_rate_hz) < 3
111 ? NumBandsForRate(sample_rate_hz) + 1
112 : 1;
113 std::unique_ptr<BlockProcessor> block_processor(
114 BlockProcessor::Create(EchoCanceller3Config(), sample_rate_hz,
115 kNumRenderChannels, kNumCaptureChannels));
116 std::vector<std::vector<std::vector<float>>> block(
117 wrong_num_bands,
118 std::vector<std::vector<float>>(kNumRenderChannels,
119 std::vector<float>(kBlockSize, 0.f)));
120
121 EXPECT_DEATH(block_processor->ProcessCapture(false, false, nullptr, &block),
122 "");
123 }
124 #endif
125
ProduceDebugText(int sample_rate_hz)126 std::string ProduceDebugText(int sample_rate_hz) {
127 rtc::StringBuilder ss;
128 ss << "Sample rate: " << sample_rate_hz;
129 return ss.Release();
130 }
131
132 } // namespace
133
134 // Verifies that the delay controller functionality is properly integrated with
135 // the render delay buffer inside block processor.
136 // TODO(peah): Activate the unittest once the required code has been landed.
TEST(BlockProcessor,DISABLED_DelayControllerIntegration)137 TEST(BlockProcessor, DISABLED_DelayControllerIntegration) {
138 constexpr size_t kNumRenderChannels = 1;
139 constexpr size_t kNumCaptureChannels = 1;
140 constexpr size_t kNumBlocks = 310;
141 constexpr size_t kDelayInSamples = 640;
142 constexpr size_t kDelayHeadroom = 1;
143 constexpr size_t kDelayInBlocks =
144 kDelayInSamples / kBlockSize - kDelayHeadroom;
145 Random random_generator(42U);
146 for (auto rate : {16000, 32000, 48000}) {
147 SCOPED_TRACE(ProduceDebugText(rate));
148 std::unique_ptr<testing::StrictMock<webrtc::test::MockRenderDelayBuffer>>
149 render_delay_buffer_mock(
150 new StrictMock<webrtc::test::MockRenderDelayBuffer>(rate, 1));
151 EXPECT_CALL(*render_delay_buffer_mock, Insert(_))
152 .Times(kNumBlocks)
153 .WillRepeatedly(Return(RenderDelayBuffer::BufferingEvent::kNone));
154 EXPECT_CALL(*render_delay_buffer_mock, AlignFromDelay(kDelayInBlocks))
155 .Times(AtLeast(1));
156 EXPECT_CALL(*render_delay_buffer_mock, MaxDelay()).WillOnce(Return(30));
157 EXPECT_CALL(*render_delay_buffer_mock, Delay())
158 .Times(kNumBlocks + 1)
159 .WillRepeatedly(Return(0));
160 std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
161 EchoCanceller3Config(), rate, kNumRenderChannels, kNumCaptureChannels,
162 std::move(render_delay_buffer_mock)));
163
164 std::vector<std::vector<std::vector<float>>> render_block(
165 NumBandsForRate(rate),
166 std::vector<std::vector<float>>(kNumRenderChannels,
167 std::vector<float>(kBlockSize, 0.f)));
168 std::vector<std::vector<std::vector<float>>> capture_block(
169 NumBandsForRate(rate),
170 std::vector<std::vector<float>>(kNumCaptureChannels,
171 std::vector<float>(kBlockSize, 0.f)));
172 DelayBuffer<float> signal_delay_buffer(kDelayInSamples);
173 for (size_t k = 0; k < kNumBlocks; ++k) {
174 RandomizeSampleVector(&random_generator, render_block[0][0]);
175 signal_delay_buffer.Delay(render_block[0][0], capture_block[0][0]);
176 block_processor->BufferRender(render_block);
177 block_processor->ProcessCapture(false, false, nullptr, &capture_block);
178 }
179 }
180 }
181
182 // Verifies that BlockProcessor submodules are called in a proper manner.
TEST(BlockProcessor,DISABLED_SubmoduleIntegration)183 TEST(BlockProcessor, DISABLED_SubmoduleIntegration) {
184 constexpr size_t kNumBlocks = 310;
185 constexpr size_t kNumRenderChannels = 1;
186 constexpr size_t kNumCaptureChannels = 1;
187
188 Random random_generator(42U);
189 for (auto rate : {16000, 32000, 48000}) {
190 SCOPED_TRACE(ProduceDebugText(rate));
191 std::unique_ptr<testing::StrictMock<webrtc::test::MockRenderDelayBuffer>>
192 render_delay_buffer_mock(
193 new StrictMock<webrtc::test::MockRenderDelayBuffer>(rate, 1));
194 std::unique_ptr<
195 ::testing::StrictMock<webrtc::test::MockRenderDelayController>>
196 render_delay_controller_mock(
197 new StrictMock<webrtc::test::MockRenderDelayController>());
198 std::unique_ptr<testing::StrictMock<webrtc::test::MockEchoRemover>>
199 echo_remover_mock(new StrictMock<webrtc::test::MockEchoRemover>());
200
201 EXPECT_CALL(*render_delay_buffer_mock, Insert(_))
202 .Times(kNumBlocks - 1)
203 .WillRepeatedly(Return(RenderDelayBuffer::BufferingEvent::kNone));
204 EXPECT_CALL(*render_delay_buffer_mock, PrepareCaptureProcessing())
205 .Times(kNumBlocks);
206 EXPECT_CALL(*render_delay_buffer_mock, AlignFromDelay(9)).Times(AtLeast(1));
207 EXPECT_CALL(*render_delay_buffer_mock, Delay())
208 .Times(kNumBlocks)
209 .WillRepeatedly(Return(0));
210 EXPECT_CALL(*render_delay_controller_mock, GetDelay(_, _, _))
211 .Times(kNumBlocks);
212 EXPECT_CALL(*echo_remover_mock, ProcessCapture(_, _, _, _, _, _))
213 .Times(kNumBlocks);
214 EXPECT_CALL(*echo_remover_mock, UpdateEchoLeakageStatus(_))
215 .Times(kNumBlocks);
216
217 std::unique_ptr<BlockProcessor> block_processor(BlockProcessor::Create(
218 EchoCanceller3Config(), rate, kNumRenderChannels, kNumCaptureChannels,
219 std::move(render_delay_buffer_mock),
220 std::move(render_delay_controller_mock), std::move(echo_remover_mock)));
221
222 std::vector<std::vector<std::vector<float>>> render_block(
223 NumBandsForRate(rate),
224 std::vector<std::vector<float>>(kNumRenderChannels,
225 std::vector<float>(kBlockSize, 0.f)));
226 std::vector<std::vector<std::vector<float>>> capture_block(
227 NumBandsForRate(rate),
228 std::vector<std::vector<float>>(kNumCaptureChannels,
229 std::vector<float>(kBlockSize, 0.f)));
230 DelayBuffer<float> signal_delay_buffer(640);
231 for (size_t k = 0; k < kNumBlocks; ++k) {
232 RandomizeSampleVector(&random_generator, render_block[0][0]);
233 signal_delay_buffer.Delay(render_block[0][0], capture_block[0][0]);
234 block_processor->BufferRender(render_block);
235 block_processor->ProcessCapture(false, false, nullptr, &capture_block);
236 block_processor->UpdateEchoLeakageStatus(false);
237 }
238 }
239 }
240
TEST(BlockProcessor,BasicSetupAndApiCalls)241 TEST(BlockProcessor, BasicSetupAndApiCalls) {
242 for (auto rate : {16000, 32000, 48000}) {
243 SCOPED_TRACE(ProduceDebugText(rate));
244 RunBasicSetupAndApiCallTest(rate, 1);
245 }
246 }
247
TEST(BlockProcessor,TestLongerCall)248 TEST(BlockProcessor, TestLongerCall) {
249 RunBasicSetupAndApiCallTest(16000, 20 * kNumBlocksPerSecond);
250 }
251
252 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
253 // TODO(gustaf): Re-enable the test once the issue with memory leaks during
254 // DEATH tests on test bots has been fixed.
TEST(BlockProcessorDeathTest,DISABLED_VerifyRenderBlockSizeCheck)255 TEST(BlockProcessorDeathTest, DISABLED_VerifyRenderBlockSizeCheck) {
256 for (auto rate : {16000, 32000, 48000}) {
257 SCOPED_TRACE(ProduceDebugText(rate));
258 RunRenderBlockSizeVerificationTest(rate);
259 }
260 }
261
TEST(BlockProcessorDeathTest,VerifyCaptureBlockSizeCheck)262 TEST(BlockProcessorDeathTest, VerifyCaptureBlockSizeCheck) {
263 for (auto rate : {16000, 32000, 48000}) {
264 SCOPED_TRACE(ProduceDebugText(rate));
265 RunCaptureBlockSizeVerificationTest(rate);
266 }
267 }
268
TEST(BlockProcessorDeathTest,VerifyRenderNumBandsCheck)269 TEST(BlockProcessorDeathTest, VerifyRenderNumBandsCheck) {
270 for (auto rate : {16000, 32000, 48000}) {
271 SCOPED_TRACE(ProduceDebugText(rate));
272 RunRenderNumBandsVerificationTest(rate);
273 }
274 }
275
276 // TODO(peah): Verify the check for correct number of bands in the capture
277 // signal.
TEST(BlockProcessorDeathTest,VerifyCaptureNumBandsCheck)278 TEST(BlockProcessorDeathTest, VerifyCaptureNumBandsCheck) {
279 for (auto rate : {16000, 32000, 48000}) {
280 SCOPED_TRACE(ProduceDebugText(rate));
281 RunCaptureNumBandsVerificationTest(rate);
282 }
283 }
284
285 // Verifiers that the verification for null ProcessCapture input works.
TEST(BlockProcessorDeathTest,NullProcessCaptureParameter)286 TEST(BlockProcessorDeathTest, NullProcessCaptureParameter) {
287 EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
288 BlockProcessor::Create(EchoCanceller3Config(), 16000, 1, 1))
289 ->ProcessCapture(false, false, nullptr, nullptr),
290 "");
291 }
292
293 // Verifies the check for correct sample rate.
294 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
295 // tests on test bots has been fixed.
TEST(BlockProcessor,DISABLED_WrongSampleRate)296 TEST(BlockProcessor, DISABLED_WrongSampleRate) {
297 EXPECT_DEATH(std::unique_ptr<BlockProcessor>(
298 BlockProcessor::Create(EchoCanceller3Config(), 8001, 1, 1)),
299 "");
300 }
301
302 #endif
303
304 } // namespace webrtc
305