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