OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | |
hlundin-webrtc
2017/01/18 13:08:51
2017
peah-webrtc
2017/01/19 15:33:07
Done.
| |
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 "webrtc/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 "webrtc/base/random.h" | |
20 #include "webrtc/modules/audio_processing/aec3/aec3_constants.h" | |
21 #include "webrtc/modules/audio_processing/aec3/render_delay_buffer.h" | |
22 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" | |
23 #include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h" | |
24 #include "webrtc/test/gtest.h" | |
25 | |
26 namespace webrtc { | |
27 namespace { | |
28 | |
29 std::string ProduceDebugText(int sample_rate_hz) { | |
30 std::ostringstream ss; | |
31 ss << "Sample rate: " << sample_rate_hz; | |
32 return ss.str(); | |
33 } | |
34 | |
35 std::string ProduceDebugText(int sample_rate_hz, size_t delay) { | |
36 std::ostringstream ss; | |
hlundin-webrtc
2017/01/18 13:08:51
I think you should be able to cascade these.
std:
peah-webrtc
2017/01/19 15:33:07
Done.
| |
37 ss << "Sample rate: " << sample_rate_hz; | |
38 ss << ", Delay: " << delay; | |
39 return ss.str(); | |
40 } | |
41 | |
42 std::string ProduceDebugText(int sample_rate_hz, | |
43 size_t delay, | |
44 size_t max_jitter) { | |
45 std::ostringstream ss; | |
hlundin-webrtc
2017/01/18 13:08:51
std::ostringstream ss(ProduceDebugText(sample_rate
peah-webrtc
2017/01/19 15:33:07
Done.
| |
46 ss << "Sample rate: " << sample_rate_hz; | |
47 ss << ", Delay: " << delay; | |
48 ss << ", Max Api call jitter: " << max_jitter; | |
49 return ss.str(); | |
50 } | |
51 | |
52 constexpr size_t kMaxApiCallJitter = 30; | |
53 | |
54 } // namespace | |
55 | |
56 // Verifies the output of SelectDelay when there are no AnalyzeRender calls. | |
57 TEST(RenderDelayController, NoRenderSignal) { | |
58 std::vector<float> block(kBlockSize, 0.f); | |
59 ApmDataDumper data_dumper(0); | |
60 for (auto rate : {8000, 16000, 32000, 48000}) { | |
61 SCOPED_TRACE(ProduceDebugText(rate)); | |
62 std::unique_ptr<RenderDelayBuffer> delay_buffer(RenderDelayBuffer::Create( | |
63 250, NumBandsForRate(rate), kMaxApiCallJitter)); | |
64 std::unique_ptr<RenderDelayController> delay_controller( | |
65 RenderDelayController::Create(&data_dumper, rate, *delay_buffer)); | |
66 for (size_t k = 0; k < 100; ++k) { | |
67 EXPECT_EQ(0u, delay_controller->SelectDelay(block)); | |
68 } | |
69 } | |
70 } | |
71 | |
72 // Verifies the behavior when there are too many AnalyzeRender calls. | |
73 TEST(RenderDelayController, RenderOverflow) { | |
74 std::vector<float> block(kBlockSize, 0.f); | |
75 ApmDataDumper data_dumper(0); | |
76 for (auto rate : {8000, 16000, 32000, 48000}) { | |
77 SCOPED_TRACE(ProduceDebugText(rate)); | |
78 std::unique_ptr<RenderDelayBuffer> delay_buffer(RenderDelayBuffer::Create( | |
79 250, NumBandsForRate(rate), kMaxApiCallJitter)); | |
80 std::unique_ptr<RenderDelayController> delay_controller( | |
81 RenderDelayController::Create(&data_dumper, rate, *delay_buffer)); | |
82 for (size_t k = 0; k < kMaxApiCallJitter; ++k) { | |
83 EXPECT_TRUE(delay_controller->AnalyzeRender(block)); | |
84 } | |
85 EXPECT_FALSE(delay_controller->AnalyzeRender(block)); | |
86 delay_controller->SelectDelay(block); | |
87 EXPECT_TRUE(delay_controller->AnalyzeRender(block)); | |
88 } | |
89 } | |
90 | |
91 // Verifies the basic API call sequence. | |
92 TEST(RenderDelayController, BasicApiCalls) { | |
93 std::vector<float> render_block(kBlockSize, 0.f); | |
94 std::vector<float> capture_block(kBlockSize, 0.f); | |
95 ApmDataDumper data_dumper(0); | |
96 size_t delay_blocks = 0; | |
97 for (auto rate : {8000, 16000, 32000, 48000}) { | |
98 std::unique_ptr<RenderDelayBuffer> render_delay_buffer( | |
99 RenderDelayBuffer::Create(50, NumBandsForRate(rate), | |
100 kMaxApiCallJitter)); | |
101 std::unique_ptr<RenderDelayController> delay_controller( | |
102 RenderDelayController::Create(&data_dumper, rate, | |
103 *render_delay_buffer)); | |
104 for (size_t k = 0; k < 10; ++k) { | |
105 EXPECT_TRUE(delay_controller->AnalyzeRender(render_block)); | |
106 delay_blocks = delay_controller->SelectDelay(capture_block); | |
107 } | |
108 EXPECT_FALSE(delay_controller->AlignmentHeadroom()); | |
109 EXPECT_EQ(0u, delay_blocks); | |
110 } | |
111 } | |
112 | |
113 // Verifies that the RenderDelayController is able to align the signals for | |
114 // simple timeshifts between the signals. | |
115 // TODO(peah): Activate the unittest once the required code has been landed. | |
116 TEST(RenderDelayController, DISABLED_Alignment) { | |
117 Random random_generator(42U); | |
118 std::vector<float> render_block(kBlockSize, 0.f); | |
119 std::vector<float> capture_block(kBlockSize, 0.f); | |
120 ApmDataDumper data_dumper(0); | |
121 size_t delay_blocks = 0; | |
122 for (auto rate : {8000, 16000, 32000, 48000}) { | |
123 for (size_t delay_samples : {0, 50, 150, 200, 800, 4000}) { | |
124 SCOPED_TRACE(ProduceDebugText(rate, delay_samples)); | |
125 std::unique_ptr<RenderDelayBuffer> render_delay_buffer( | |
126 RenderDelayBuffer::Create(250, NumBandsForRate(rate), | |
127 kMaxApiCallJitter)); | |
128 std::unique_ptr<RenderDelayController> delay_controller( | |
129 RenderDelayController::Create(&data_dumper, rate, | |
130 *render_delay_buffer)); | |
131 DelayBuffer<float> signal_delay_buffer(delay_samples); | |
132 for (size_t k = 0; k < (300 + delay_samples / kBlockSize); ++k) { | |
133 RandomizeSampleVector(&random_generator, render_block); | |
134 signal_delay_buffer.Delay(render_block, capture_block); | |
135 EXPECT_TRUE(delay_controller->AnalyzeRender(render_block)); | |
136 delay_blocks = delay_controller->SelectDelay(capture_block); | |
137 } | |
138 | |
139 constexpr int kDelayHeadroomBlocks = 1; | |
140 size_t expected_delay_blocks = | |
141 std::max(0, static_cast<int>(delay_samples / kBlockSize) - | |
142 kDelayHeadroomBlocks); | |
143 if (expected_delay_blocks < 2) { | |
144 expected_delay_blocks = 0; | |
145 } | |
146 | |
147 EXPECT_EQ(expected_delay_blocks, delay_blocks); | |
148 | |
149 const rtc::Optional<size_t> headroom_samples = | |
150 delay_controller->AlignmentHeadroom(); | |
151 EXPECT_TRUE(headroom_samples); | |
hlundin-webrtc
2017/01/18 13:08:50
ASSERT_TRUE
peah-webrtc
2017/01/19 15:33:07
Done.
| |
152 EXPECT_NEAR(delay_samples - delay_blocks * kBlockSize, *headroom_samples, | |
153 4); | |
154 } | |
155 } | |
156 } | |
157 | |
158 // Verifies that the RenderDelayController is able to align the signals for | |
159 // simple timeshifts between the signals when there is jitter in the API calls. | |
160 // TODO(peah): Activate the unittest once the required code has been landed. | |
161 TEST(RenderDelayController, DISABLED_AlignmentWithJitter) { | |
162 Random random_generator(42U); | |
163 std::vector<float> render_block(kBlockSize, 0.f); | |
164 std::vector<float> capture_block(kBlockSize, 0.f); | |
165 ApmDataDumper data_dumper(0); | |
166 for (auto rate : {8000, 16000, 32000, 48000}) { | |
167 for (size_t delay_samples : {0, 50, 800}) { | |
168 for (size_t max_jitter : {1, 9, 20}) { | |
169 size_t delay_blocks = 0; | |
170 SCOPED_TRACE(ProduceDebugText(rate, delay_samples, max_jitter)); | |
171 std::unique_ptr<RenderDelayBuffer> render_delay_buffer( | |
172 RenderDelayBuffer::Create(250, NumBandsForRate(rate), max_jitter)); | |
173 std::unique_ptr<RenderDelayController> delay_controller( | |
174 RenderDelayController::Create(&data_dumper, rate, | |
175 *render_delay_buffer)); | |
176 DelayBuffer<float> signal_delay_buffer(delay_samples); | |
177 for (size_t j = 0; | |
178 j < (300 + delay_samples / kBlockSize) / max_jitter + 1; ++j) { | |
179 std::vector<std::vector<float>> capture_block_buffer; | |
180 for (size_t k = 0; k < max_jitter; ++k) { | |
181 RandomizeSampleVector(&random_generator, render_block); | |
182 signal_delay_buffer.Delay(render_block, capture_block); | |
183 capture_block_buffer.push_back(capture_block); | |
184 EXPECT_TRUE(delay_controller->AnalyzeRender(render_block)); | |
185 } | |
186 for (size_t k = 0; k < max_jitter; ++k) { | |
187 delay_blocks = | |
188 delay_controller->SelectDelay(capture_block_buffer[k]); | |
189 } | |
190 } | |
191 | |
192 constexpr int kDelayHeadroomBlocks = 1; | |
193 size_t expected_delay_blocks = | |
194 std::max(0, static_cast<int>(delay_samples / kBlockSize) - | |
195 kDelayHeadroomBlocks); | |
196 if (expected_delay_blocks < 2) { | |
197 expected_delay_blocks = 0; | |
198 } | |
199 | |
200 EXPECT_EQ(expected_delay_blocks, delay_blocks); | |
201 | |
202 const rtc::Optional<size_t> headroom_samples = | |
203 delay_controller->AlignmentHeadroom(); | |
204 EXPECT_TRUE(headroom_samples); | |
hlundin-webrtc
2017/01/18 13:08:51
ASSERT_TRUE
peah-webrtc
2017/01/19 15:33:07
Done.
| |
205 EXPECT_NEAR(delay_samples - delay_blocks * kBlockSize, | |
206 *headroom_samples, 4); | |
207 } | |
208 } | |
209 } | |
210 } | |
211 | |
212 // Verifies the initial value for the AlignmentHeadroom. | |
213 TEST(RenderDelayController, InitialHeadroom) { | |
214 std::vector<float> render_block(kBlockSize, 0.f); | |
215 std::vector<float> capture_block(kBlockSize, 0.f); | |
216 ApmDataDumper data_dumper(0); | |
217 for (auto rate : {8000, 16000, 32000, 48000}) { | |
218 SCOPED_TRACE(ProduceDebugText(rate)); | |
219 std::unique_ptr<RenderDelayBuffer> render_delay_buffer( | |
220 RenderDelayBuffer::Create(250, NumBandsForRate(rate), | |
221 kMaxApiCallJitter)); | |
222 std::unique_ptr<RenderDelayController> delay_controller( | |
223 RenderDelayController::Create(&data_dumper, rate, | |
224 *render_delay_buffer)); | |
225 EXPECT_FALSE(delay_controller->AlignmentHeadroom()); | |
226 } | |
227 } | |
228 | |
229 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) | |
230 | |
231 // Verifes the check for null datadumper. | |
232 TEST(RenderDelayController, NullDataDumperCheck) { | |
233 for (auto rate : {8000, 16000, 32000, 48000}) { | |
234 SCOPED_TRACE(ProduceDebugText(rate)); | |
235 std::unique_ptr<RenderDelayBuffer> render_delay_buffer( | |
236 RenderDelayBuffer::Create(10, NumBandsForRate(rate), | |
237 kMaxApiCallJitter)); | |
238 EXPECT_DEATH( | |
239 std::unique_ptr<RenderDelayController>( | |
240 RenderDelayController::Create(nullptr, rate, *render_delay_buffer)), | |
241 ""); | |
242 } | |
243 } | |
244 | |
245 // Verifies the check for the capture signal block size. | |
246 TEST(RenderDelayController, WrongCaptureSize) { | |
247 std::vector<float> block(kBlockSize - 1, 0.f); | |
248 ApmDataDumper data_dumper(0); | |
249 for (auto rate : {8000, 16000, 32000, 48000}) { | |
250 SCOPED_TRACE(ProduceDebugText(rate)); | |
251 std::unique_ptr<RenderDelayBuffer> render_delay_buffer( | |
252 RenderDelayBuffer::Create(250, NumBandsForRate(rate), | |
253 kMaxApiCallJitter)); | |
254 EXPECT_DEATH(std::unique_ptr<RenderDelayController>( | |
255 RenderDelayController::Create(&data_dumper, rate, | |
256 *render_delay_buffer)) | |
257 ->SelectDelay(block), | |
258 ""); | |
259 } | |
260 } | |
261 | |
262 // Verifies the check for the render signal block size. | |
263 TEST(RenderDelayController, WrongRenderSize) { | |
264 std::vector<float> block(kBlockSize - 1, 0.f); | |
265 ApmDataDumper data_dumper(0); | |
266 for (auto rate : {8000, 16000, 32000, 48000}) { | |
267 SCOPED_TRACE(ProduceDebugText(rate)); | |
268 std::unique_ptr<RenderDelayBuffer> render_delay_buffer( | |
269 RenderDelayBuffer::Create(250, NumBandsForRate(rate), | |
270 kMaxApiCallJitter)); | |
271 EXPECT_DEATH(std::unique_ptr<RenderDelayController>( | |
272 RenderDelayController::Create(&data_dumper, rate, | |
273 *render_delay_buffer)) | |
274 ->AnalyzeRender(block), | |
275 ""); | |
276 } | |
277 } | |
278 | |
279 // Verifies the check for correct sample rate. | |
280 TEST(RenderDelayController, WrongSampleRate) { | |
281 ApmDataDumper data_dumper(0); | |
282 for (auto rate : {-1, 0, 8001, 16001}) { | |
283 SCOPED_TRACE(ProduceDebugText(rate)); | |
284 std::unique_ptr<RenderDelayBuffer> render_delay_buffer( | |
285 RenderDelayBuffer::Create(10, NumBandsForRate(rate), | |
286 kMaxApiCallJitter)); | |
287 EXPECT_DEATH( | |
288 std::unique_ptr<RenderDelayController>(RenderDelayController::Create( | |
289 &data_dumper, rate, *render_delay_buffer)), | |
290 ""); | |
291 } | |
292 } | |
293 | |
294 #endif | |
295 | |
296 } // namespace webrtc | |
OLD | NEW |