1 /*
2 * Copyright (c) 2017 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/render_delay_controller.h"
12
13 #include <algorithm>
14 #include <memory>
15 #include <sstream>
16 #include <string>
17 #include <vector>
18
19 #include "modules/audio_processing/aec3/aec3_common.h"
20 #include "modules/audio_processing/aec3/block_processor.h"
21 #include "modules/audio_processing/aec3/decimator.h"
22 #include "modules/audio_processing/aec3/render_delay_buffer.h"
23 #include "modules/audio_processing/logging/apm_data_dumper.h"
24 #include "modules/audio_processing/test/echo_canceller_test_tools.h"
25 #include "rtc_base/random.h"
26 #include "test/gtest.h"
27
28 namespace webrtc {
29 namespace {
30
ProduceDebugText(int sample_rate_hz)31 std::string ProduceDebugText(int sample_rate_hz) {
32 std::ostringstream ss;
33 ss << "Sample rate: " << sample_rate_hz;
34 return ss.str();
35 }
36
ProduceDebugText(int sample_rate_hz,size_t delay)37 std::string ProduceDebugText(int sample_rate_hz, size_t delay) {
38 std::ostringstream ss;
39 ss << ProduceDebugText(sample_rate_hz) << ", Delay: " << delay;
40 return ss.str();
41 }
42
43 constexpr size_t kDownSamplingFactors[] = {2, 4, 8};
44
45 } // namespace
46
47 // Verifies the output of GetDelay when there are no AnalyzeRender calls.
TEST(RenderDelayController,NoRenderSignal)48 TEST(RenderDelayController, NoRenderSignal) {
49 std::vector<float> block(kBlockSize, 0.f);
50 for (size_t num_matched_filters = 4; num_matched_filters == 10;
51 num_matched_filters++) {
52 for (auto down_sampling_factor : kDownSamplingFactors) {
53 for (auto rate : {8000, 16000, 32000, 48000}) {
54 SCOPED_TRACE(ProduceDebugText(rate));
55 std::unique_ptr<RenderDelayBuffer> delay_buffer(
56 RenderDelayBuffer::Create(
57 NumBandsForRate(rate), down_sampling_factor,
58 GetDownSampledBufferSize(down_sampling_factor,
59 num_matched_filters),
60 GetRenderDelayBufferSize(down_sampling_factor,
61 num_matched_filters)));
62 std::unique_ptr<RenderDelayController> delay_controller(
63 RenderDelayController::Create(EchoCanceller3Config(), rate));
64 for (size_t k = 0; k < 100; ++k) {
65 EXPECT_EQ(kMinEchoPathDelayBlocks,
66 delay_controller->GetDelay(
67 delay_buffer->GetDownsampledRenderBuffer(), block));
68 }
69 }
70 }
71 }
72 }
73
74 // Verifies the basic API call sequence.
TEST(RenderDelayController,BasicApiCalls)75 TEST(RenderDelayController, BasicApiCalls) {
76 std::vector<float> capture_block(kBlockSize, 0.f);
77 size_t delay_blocks = 0;
78 for (size_t num_matched_filters = 4; num_matched_filters == 10;
79 num_matched_filters++) {
80 for (auto down_sampling_factor : kDownSamplingFactors) {
81 for (auto rate : {8000, 16000, 32000, 48000}) {
82 std::vector<std::vector<float>> render_block(
83 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
84 std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
85 RenderDelayBuffer::Create(
86 NumBandsForRate(rate), down_sampling_factor,
87 GetDownSampledBufferSize(down_sampling_factor,
88 num_matched_filters),
89 GetRenderDelayBufferSize(down_sampling_factor,
90 num_matched_filters)));
91 std::unique_ptr<RenderDelayController> delay_controller(
92 RenderDelayController::Create(EchoCanceller3Config(), rate));
93 for (size_t k = 0; k < 10; ++k) {
94 render_delay_buffer->Insert(render_block);
95 render_delay_buffer->UpdateBuffers();
96 delay_blocks = delay_controller->GetDelay(
97 render_delay_buffer->GetDownsampledRenderBuffer(), capture_block);
98 }
99 EXPECT_FALSE(delay_controller->AlignmentHeadroomSamples());
100 EXPECT_EQ(kMinEchoPathDelayBlocks, delay_blocks);
101 }
102 }
103 }
104 }
105
106 // Verifies that the RenderDelayController is able to align the signals for
107 // simple timeshifts between the signals.
TEST(RenderDelayController,Alignment)108 TEST(RenderDelayController, Alignment) {
109 Random random_generator(42U);
110 std::vector<float> capture_block(kBlockSize, 0.f);
111 size_t delay_blocks = 0;
112 for (size_t num_matched_filters = 4; num_matched_filters == 10;
113 num_matched_filters++) {
114 for (auto down_sampling_factor : kDownSamplingFactors) {
115 for (auto rate : {8000, 16000, 32000, 48000}) {
116 std::vector<std::vector<float>> render_block(
117 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
118
119 for (size_t delay_samples : {15, 50, 150, 200, 800, 4000}) {
120 SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
121 std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
122 RenderDelayBuffer::Create(
123 NumBandsForRate(rate), down_sampling_factor,
124 GetDownSampledBufferSize(down_sampling_factor,
125 num_matched_filters),
126 GetRenderDelayBufferSize(down_sampling_factor,
127 num_matched_filters)));
128 std::unique_ptr<RenderDelayController> delay_controller(
129 RenderDelayController::Create(EchoCanceller3Config(), rate));
130 DelayBuffer<float> signal_delay_buffer(delay_samples);
131 for (size_t k = 0; k < (400 + delay_samples / kBlockSize); ++k) {
132 RandomizeSampleVector(&random_generator, render_block[0]);
133 signal_delay_buffer.Delay(render_block[0], capture_block);
134 render_delay_buffer->Insert(render_block);
135 render_delay_buffer->UpdateBuffers();
136 delay_blocks = delay_controller->GetDelay(
137 render_delay_buffer->GetDownsampledRenderBuffer(),
138 capture_block);
139 }
140
141 constexpr int kDelayHeadroomBlocks = 1;
142 size_t expected_delay_blocks =
143 std::max(0, static_cast<int>(delay_samples / kBlockSize) -
144 kDelayHeadroomBlocks);
145
146 EXPECT_EQ(expected_delay_blocks, delay_blocks);
147
148 const rtc::Optional<size_t> headroom_samples =
149 delay_controller->AlignmentHeadroomSamples();
150 ASSERT_TRUE(headroom_samples);
151 EXPECT_NEAR(delay_samples - delay_blocks * kBlockSize,
152 *headroom_samples, 4);
153 }
154 }
155 }
156 }
157 }
158
159 // Verifies that the RenderDelayController is able to properly handle noncausal
160 // delays.
TEST(RenderDelayController,NonCausalAlignment)161 TEST(RenderDelayController, NonCausalAlignment) {
162 Random random_generator(42U);
163 size_t delay_blocks = 0;
164 for (size_t num_matched_filters = 4; num_matched_filters == 10;
165 num_matched_filters++) {
166 for (auto down_sampling_factor : kDownSamplingFactors) {
167 for (auto rate : {8000, 16000, 32000, 48000}) {
168 std::vector<std::vector<float>> render_block(
169 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
170 std::vector<std::vector<float>> capture_block(
171 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
172
173 for (int delay_samples : {-15, -50, -150, -200}) {
174 SCOPED_TRACE(ProduceDebugText(rate, -delay_samples));
175 std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
176 RenderDelayBuffer::Create(
177 NumBandsForRate(rate), down_sampling_factor,
178 GetDownSampledBufferSize(down_sampling_factor,
179 num_matched_filters),
180 GetRenderDelayBufferSize(down_sampling_factor,
181 num_matched_filters)));
182 std::unique_ptr<RenderDelayController> delay_controller(
183 RenderDelayController::Create(EchoCanceller3Config(), rate));
184 DelayBuffer<float> signal_delay_buffer(-delay_samples);
185 for (int k = 0;
186 k < (400 - delay_samples / static_cast<int>(kBlockSize)); ++k) {
187 RandomizeSampleVector(&random_generator, capture_block[0]);
188 signal_delay_buffer.Delay(capture_block[0], render_block[0]);
189 render_delay_buffer->Insert(render_block);
190 render_delay_buffer->UpdateBuffers();
191 delay_blocks = delay_controller->GetDelay(
192 render_delay_buffer->GetDownsampledRenderBuffer(),
193 capture_block[0]);
194 }
195
196 EXPECT_EQ(0u, delay_blocks);
197
198 const rtc::Optional<size_t> headroom_samples =
199 delay_controller->AlignmentHeadroomSamples();
200 ASSERT_FALSE(headroom_samples);
201 }
202 }
203 }
204 }
205 }
206
207 // Verifies that the RenderDelayController is able to align the signals for
208 // simple timeshifts between the signals when there is jitter in the API calls.
TEST(RenderDelayController,AlignmentWithJitter)209 TEST(RenderDelayController, AlignmentWithJitter) {
210 Random random_generator(42U);
211 std::vector<float> capture_block(kBlockSize, 0.f);
212 for (size_t num_matched_filters = 4; num_matched_filters == 10;
213 num_matched_filters++) {
214 for (auto down_sampling_factor : kDownSamplingFactors) {
215 for (auto rate : {8000, 16000, 32000, 48000}) {
216 std::vector<std::vector<float>> render_block(
217 NumBandsForRate(rate), std::vector<float>(kBlockSize, 0.f));
218 for (size_t delay_samples : {15, 50, 300, 800}) {
219 size_t delay_blocks = 0;
220 SCOPED_TRACE(ProduceDebugText(rate, delay_samples));
221 std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
222 RenderDelayBuffer::Create(
223 NumBandsForRate(rate), down_sampling_factor,
224 GetDownSampledBufferSize(down_sampling_factor,
225 num_matched_filters),
226 GetRenderDelayBufferSize(down_sampling_factor,
227 num_matched_filters)));
228 std::unique_ptr<RenderDelayController> delay_controller(
229 RenderDelayController::Create(EchoCanceller3Config(), rate));
230 DelayBuffer<float> signal_delay_buffer(delay_samples);
231 for (size_t j = 0; j < (1000 + delay_samples / kBlockSize) /
232 kMaxApiCallsJitterBlocks +
233 1;
234 ++j) {
235 std::vector<std::vector<float>> capture_block_buffer;
236 for (size_t k = 0; k < (kMaxApiCallsJitterBlocks - 1); ++k) {
237 RandomizeSampleVector(&random_generator, render_block[0]);
238 signal_delay_buffer.Delay(render_block[0], capture_block);
239 capture_block_buffer.push_back(capture_block);
240 render_delay_buffer->Insert(render_block);
241 }
242 for (size_t k = 0; k < (kMaxApiCallsJitterBlocks - 1); ++k) {
243 render_delay_buffer->UpdateBuffers();
244 delay_blocks = delay_controller->GetDelay(
245 render_delay_buffer->GetDownsampledRenderBuffer(),
246 capture_block_buffer[k]);
247 }
248 }
249
250 constexpr int kDelayHeadroomBlocks = 1;
251 size_t expected_delay_blocks =
252 std::max(0, static_cast<int>(delay_samples / kBlockSize) -
253 kDelayHeadroomBlocks);
254 if (expected_delay_blocks < 2) {
255 expected_delay_blocks = 0;
256 }
257
258 EXPECT_EQ(expected_delay_blocks, delay_blocks);
259
260 const rtc::Optional<size_t> headroom_samples =
261 delay_controller->AlignmentHeadroomSamples();
262 ASSERT_TRUE(headroom_samples);
263 EXPECT_NEAR(delay_samples - delay_blocks * kBlockSize,
264 *headroom_samples, 4);
265 }
266 }
267 }
268 }
269 }
270
271 // Verifies the initial value for the AlignmentHeadroomSamples.
TEST(RenderDelayController,InitialHeadroom)272 TEST(RenderDelayController, InitialHeadroom) {
273 std::vector<float> render_block(kBlockSize, 0.f);
274 std::vector<float> capture_block(kBlockSize, 0.f);
275 for (size_t num_matched_filters = 4; num_matched_filters == 10;
276 num_matched_filters++) {
277 for (auto down_sampling_factor : kDownSamplingFactors) {
278 for (auto rate : {8000, 16000, 32000, 48000}) {
279 SCOPED_TRACE(ProduceDebugText(rate));
280 std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
281 RenderDelayBuffer::Create(
282 NumBandsForRate(rate), down_sampling_factor,
283 GetDownSampledBufferSize(down_sampling_factor,
284 num_matched_filters),
285 GetRenderDelayBufferSize(down_sampling_factor,
286 num_matched_filters)));
287 std::unique_ptr<RenderDelayController> delay_controller(
288 RenderDelayController::Create(EchoCanceller3Config(), rate));
289 EXPECT_FALSE(delay_controller->AlignmentHeadroomSamples());
290 }
291 }
292 }
293 }
294
295 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
296
297 // Verifies the check for the capture signal block size.
TEST(RenderDelayController,WrongCaptureSize)298 TEST(RenderDelayController, WrongCaptureSize) {
299 std::vector<float> block(kBlockSize - 1, 0.f);
300 for (auto rate : {8000, 16000, 32000, 48000}) {
301 SCOPED_TRACE(ProduceDebugText(rate));
302 std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
303 RenderDelayBuffer::Create(NumBandsForRate(rate), 4,
304 GetDownSampledBufferSize(4, 4),
305 GetRenderDelayBufferSize(4, 4)));
306 EXPECT_DEATH(
307 std::unique_ptr<RenderDelayController>(
308 RenderDelayController::Create(EchoCanceller3Config(), rate))
309 ->GetDelay(render_delay_buffer->GetDownsampledRenderBuffer(),
310 block),
311 "");
312 }
313 }
314
315 // Verifies the check for correct sample rate.
316 // TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
317 // tests on test bots has been fixed.
TEST(RenderDelayController,DISABLED_WrongSampleRate)318 TEST(RenderDelayController, DISABLED_WrongSampleRate) {
319 for (auto rate : {-1, 0, 8001, 16001}) {
320 SCOPED_TRACE(ProduceDebugText(rate));
321 std::unique_ptr<RenderDelayBuffer> render_delay_buffer(
322 RenderDelayBuffer::Create(NumBandsForRate(rate), 4,
323 GetDownSampledBufferSize(4, 4),
324 GetRenderDelayBufferSize(4, 4)));
325 EXPECT_DEATH(
326 std::unique_ptr<RenderDelayController>(
327 RenderDelayController::Create(EchoCanceller3Config(), rate)),
328 "");
329 }
330 }
331
332 #endif
333
334 } // namespace webrtc
335