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