OLD | NEW |
---|---|
(Empty) | |
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 <deque> | |
12 #include <memory> | |
13 #include <string> | |
14 #include <vector> | |
15 | |
16 #include "webrtc/modules/audio_processing/aec3/aec3_constants.h" | |
17 #include "webrtc/modules/audio_processing/aec3/block_processor.h" | |
18 #include "webrtc/modules/audio_processing/aec3/echo_canceller3.h" | |
hlundin-webrtc
2016/12/22 10:23:57
This goes to the top.
peah-webrtc
2016/12/22 16:40:04
Done.
| |
19 #include "webrtc/modules/audio_processing/aec3/frame_blocker.h" | |
20 #include "webrtc/modules/audio_processing/aec3/mock/mock_block_processor.h" | |
21 #include "webrtc/modules/audio_processing/audio_buffer.h" | |
22 #include "webrtc/test/gmock.h" | |
23 #include "webrtc/test/gtest.h" | |
24 | |
25 namespace webrtc { | |
26 namespace { | |
27 | |
28 using testing::StrictMock; | |
29 | |
30 // Populates the frame with linearly increasing sample values for each band, | |
31 // with a band-specific offset, in order to allow simple bitexactness | |
32 // verification for each band. | |
33 void PopulateInputFrame(size_t frame_length, | |
34 size_t num_bands, | |
35 size_t frame_index, | |
36 float* const* frame, | |
37 int offset) { | |
38 for (size_t k = 0; k < num_bands; ++k) { | |
39 for (size_t i = 0; i < frame_length; ++i) { | |
40 float value = static_cast<int>(frame_index * frame_length + i) + offset; | |
41 frame[k][i] = (value > 0 ? 5000 * k + value : 0); | |
42 } | |
43 } | |
44 } | |
45 | |
46 // Verifies the that samples in the output frame are identical to the samples | |
47 // that were produced for the input frame, with an offset in order to compensate | |
48 // for buffering delays. | |
49 bool VerifyOutputFrameBitexactness(size_t frame_length, | |
50 size_t num_bands, | |
51 size_t frame_index, | |
52 const float* const* frame, | |
53 int offset) { | |
54 float reference_frame_data[num_bands][frame_length]; | |
55 float* reference_frame[num_bands]; | |
56 for (size_t k = 0; k < num_bands; ++k) { | |
57 reference_frame[k] = &reference_frame_data[k][0]; | |
58 } | |
59 | |
60 PopulateInputFrame(frame_length, num_bands, frame_index, reference_frame, | |
61 offset); | |
62 for (size_t k = 0; k < num_bands; ++k) { | |
63 for (size_t i = 0; i < frame_length; ++i) { | |
64 if (reference_frame[k][i] != frame[k][i]) { | |
65 return false; | |
66 } | |
67 } | |
68 } | |
69 | |
70 return true; | |
71 } | |
72 | |
73 // Class for testing that the capture data is properly received by the block | |
74 // processor and that the processor data is properly passed to the | |
75 // EchoCanceller3 output. | |
76 class CaptureTransportVerificationProcessor : public BlockProcessor { | |
77 public: | |
78 explicit CaptureTransportVerificationProcessor(size_t num_bands) {} | |
hlundin-webrtc
2016/12/22 10:23:57
= defualt?
peah-webrtc
2016/12/22 16:40:04
That does not seem to work (the compiler says "onl
| |
79 ~CaptureTransportVerificationProcessor() override = default; | |
80 | |
81 void ProcessCapture(bool known_echo_path_change, | |
82 bool saturated_microphone_signal, | |
83 std::vector<std::vector<float>>* capture_block) override { | |
84 } | |
85 | |
86 bool BufferRender(std::vector<std::vector<float>>* block) override { | |
87 return false; | |
88 } | |
89 | |
90 void ReportEchoLeakage(bool leakage_detected) override {} | |
91 | |
92 private: | |
93 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor); | |
94 }; | |
95 | |
96 // Class for testing that the render data is properly received by the block | |
97 // processor. | |
98 class RenderTransportVerificationProcessor : public BlockProcessor { | |
99 public: | |
100 explicit RenderTransportVerificationProcessor(size_t num_bands) {} | |
101 ~RenderTransportVerificationProcessor() override = default; | |
102 | |
103 void ProcessCapture(bool known_echo_path_change, | |
104 bool saturated_microphone_signal, | |
105 std::vector<std::vector<float>>* capture_block) override { | |
106 std::vector<std::vector<float>> render_block = | |
107 received_render_blocks_.front(); | |
108 received_render_blocks_.pop_front(); | |
109 capture_block->swap(render_block); | |
110 } | |
111 | |
112 bool BufferRender(std::vector<std::vector<float>>* block) override { | |
113 received_render_blocks_.push_back(*block); | |
114 return false; | |
115 } | |
116 | |
117 void ReportEchoLeakage(bool leakage_detected) override {} | |
118 | |
119 private: | |
120 std::deque<std::vector<std::vector<float>>> received_render_blocks_; | |
121 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor); | |
122 }; | |
123 | |
124 class EchoCanceller3Tester { | |
125 public: | |
126 explicit EchoCanceller3Tester(int sample_rate_hz) | |
127 : sample_rate_hz_(sample_rate_hz), | |
128 num_bands_(NumBandsForRate(sample_rate_hz_)), | |
129 frame_length_(sample_rate_hz_ == 8000 ? 80 : 160), | |
130 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)), | |
131 capture_buffer_(fullband_frame_length_, | |
132 1, | |
133 fullband_frame_length_, | |
134 1, | |
135 fullband_frame_length_), | |
136 render_buffer_(fullband_frame_length_, | |
137 1, | |
138 fullband_frame_length_, | |
139 1, | |
140 fullband_frame_length_) {} | |
141 | |
142 // Verifies that the capture data is properly received by the block processor | |
143 // and that the processor data is properly passed to the EchoCanceller3 | |
144 // output. | |
145 void RunCaptureTransportVerificationTest() { | |
146 EchoCanceller3 aec3( | |
147 sample_rate_hz_, false, | |
148 std::unique_ptr<BlockProcessor>( | |
149 new CaptureTransportVerificationProcessor(num_bands_))); | |
150 | |
151 for (size_t frame_index = 0; frame_index < kNumFramesToProcess; | |
152 ++frame_index) { | |
153 aec3.AnalyzeCapture(&capture_buffer_); | |
154 OptionalBandSplit(); | |
155 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
156 &capture_buffer_.split_bands_f(0)[0], 0); | |
157 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
158 &render_buffer_.split_bands_f(0)[0], 100); | |
159 | |
160 EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); | |
161 aec3.ProcessCapture(&capture_buffer_, false); | |
162 EXPECT_TRUE(VerifyOutputFrameBitexactness( | |
163 frame_length_, num_bands_, frame_index, | |
164 &capture_buffer_.split_bands_f(0)[0], -64)); | |
165 } | |
166 } | |
167 | |
168 // Test method for testing that the render data is properly received by the | |
169 // block processor. | |
170 void RunRenderTransportVerificationTest() { | |
171 EchoCanceller3 aec3( | |
172 sample_rate_hz_, false, | |
173 std::unique_ptr<BlockProcessor>( | |
174 new RenderTransportVerificationProcessor(num_bands_))); | |
175 | |
176 for (size_t frame_index = 0; frame_index < kNumFramesToProcess; | |
177 ++frame_index) { | |
178 aec3.AnalyzeCapture(&capture_buffer_); | |
179 OptionalBandSplit(); | |
180 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
181 &capture_buffer_.split_bands_f(0)[0], 100); | |
182 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
183 &render_buffer_.split_bands_f(0)[0], 0); | |
184 | |
185 EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); | |
186 aec3.ProcessCapture(&capture_buffer_, false); | |
187 EXPECT_TRUE(VerifyOutputFrameBitexactness( | |
188 frame_length_, num_bands_, frame_index, | |
189 &capture_buffer_.split_bands_f(0)[0], -64)); | |
190 } | |
191 } | |
192 | |
193 // Verifies that information about echo path changes are properly propagated | |
194 // to the block processor. | |
195 // The cases tested are: | |
196 // -That no set echo path change flags are received when there is no echo path | |
197 // change. | |
198 // -That set echo path change flags are received and continues to be received | |
199 // as long as echo path changes are flagged. | |
200 // -That set echo path change flags are no longer received when echo path | |
201 // change events stop being flagged. | |
202 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky }; | |
203 | |
204 void RunEchoPathChangeVerificationTest( | |
205 EchoPathChangeTestVariant echo_path_change_test_variant) { | |
206 const size_t num_full_blocks_per_frame = | |
207 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize; | |
208 const size_t expected_num_block_to_process = | |
209 (kNumFramesToProcess * | |
210 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) / | |
211 kBlockSize; | |
212 testing::StrictMock<webrtc::test::MockBlockProcessor>* | |
213 block_processor_mock = | |
214 new StrictMock<webrtc::test::MockBlockProcessor>(); | |
215 EXPECT_CALL(*block_processor_mock, BufferRender(testing::_)) | |
hlundin-webrtc
2016/12/22 10:23:57
Add a using testing::_ and simplify all of these t
peah-webrtc
2016/12/22 16:40:04
Great suggestion!
Done.
| |
216 .Times(expected_num_block_to_process); | |
217 EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(testing::_)).Times(0); | |
218 | |
219 switch (echo_path_change_test_variant) { | |
220 case EchoPathChangeTestVariant::kNone: | |
221 EXPECT_CALL(*block_processor_mock, | |
222 ProcessCapture(false, testing::_, testing::_)) | |
223 .Times(expected_num_block_to_process); | |
224 break; | |
225 case EchoPathChangeTestVariant::kOneSticky: | |
226 EXPECT_CALL(*block_processor_mock, | |
227 ProcessCapture(true, testing::_, testing::_)) | |
228 .Times(expected_num_block_to_process); | |
229 break; | |
230 case EchoPathChangeTestVariant::kOneNonSticky: | |
231 EXPECT_CALL(*block_processor_mock, | |
232 ProcessCapture(true, testing::_, testing::_)) | |
233 .Times(num_full_blocks_per_frame); | |
234 EXPECT_CALL(*block_processor_mock, | |
235 ProcessCapture(false, testing::_, testing::_)) | |
236 .Times(expected_num_block_to_process - num_full_blocks_per_frame); | |
237 break; | |
238 } | |
239 | |
240 EchoCanceller3 aec3(sample_rate_hz_, false, | |
241 std::unique_ptr<BlockProcessor>(block_processor_mock)); | |
242 block_processor_mock = nullptr; | |
hlundin-webrtc
2016/12/22 10:23:56
Looks like you want to make block_processor_mock a
peah-webrtc
2016/12/22 16:40:04
Thanks! That's much better!
Done.
| |
243 | |
244 for (size_t frame_index = 0; frame_index < kNumFramesToProcess; | |
245 ++frame_index) { | |
246 bool echo_path_change = false; | |
247 switch (echo_path_change_test_variant) { | |
248 case EchoPathChangeTestVariant::kNone: | |
249 break; | |
250 case EchoPathChangeTestVariant::kOneSticky: | |
251 echo_path_change = true; | |
252 break; | |
253 case EchoPathChangeTestVariant::kOneNonSticky: | |
254 if (frame_index == 0) { | |
255 echo_path_change = true; | |
256 } | |
257 break; | |
258 } | |
259 | |
260 aec3.AnalyzeCapture(&capture_buffer_); | |
261 OptionalBandSplit(); | |
262 | |
263 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
264 &capture_buffer_.split_bands_f(0)[0], 0); | |
265 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
266 &render_buffer_.split_bands_f(0)[0], 0); | |
267 | |
268 EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); | |
269 aec3.ProcessCapture(&capture_buffer_, echo_path_change); | |
270 } | |
271 } | |
272 | |
273 // Test for verifying that echo leakage information is being properly passed | |
274 // to the processor. | |
275 // The cases tested are: | |
276 // -That no method calls are received when they should not. | |
277 // -That false values are received each time they are flagged. | |
278 // -That true values are received each time they are flagged. | |
279 // -That a false value is received when flagged after a true value has been | |
280 // flagged. | |
281 enum class EchoLeakageTestVariant { | |
282 kNone, | |
283 kFalseSticky, | |
284 kTrueSticky, | |
285 kTrueNonSticky | |
286 }; | |
287 | |
288 void RunEchoLeakageVerificationTest( | |
289 EchoLeakageTestVariant leakage_report_variant) { | |
290 const size_t expected_num_block_to_process = | |
291 (kNumFramesToProcess * | |
292 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) / | |
293 kBlockSize; | |
294 testing::StrictMock<webrtc::test::MockBlockProcessor>* | |
295 block_processor_mock = | |
296 new StrictMock<webrtc::test::MockBlockProcessor>(); | |
297 EXPECT_CALL(*block_processor_mock, BufferRender(testing::_)) | |
298 .Times(expected_num_block_to_process); | |
299 EXPECT_CALL(*block_processor_mock, | |
300 ProcessCapture(testing::_, testing::_, testing::_)) | |
301 .Times(expected_num_block_to_process); | |
302 | |
303 switch (leakage_report_variant) { | |
304 case EchoLeakageTestVariant::kNone: | |
305 EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(testing::_)) | |
306 .Times(0); | |
307 break; | |
308 case EchoLeakageTestVariant::kFalseSticky: | |
309 EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(false)).Times(1); | |
310 break; | |
311 case EchoLeakageTestVariant::kTrueSticky: | |
312 EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(true)).Times(1); | |
313 break; | |
314 case EchoLeakageTestVariant::kTrueNonSticky: | |
315 EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(true)).Times(1); | |
hlundin-webrtc
2016/12/22 10:23:56
I think you will want to enforce the order of the
peah-webrtc
2016/12/22 16:40:04
Great point! Thanks!
Done.
| |
316 EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(false)) | |
317 .Times(kNumFramesToProcess - 1); | |
318 break; | |
319 } | |
320 | |
321 EchoCanceller3 aec3(sample_rate_hz_, false, | |
322 std::unique_ptr<BlockProcessor>(block_processor_mock)); | |
323 block_processor_mock = nullptr; | |
hlundin-webrtc
2016/12/22 10:23:57
Same here.
peah-webrtc
2016/12/22 16:40:04
Done.
| |
324 | |
325 for (size_t frame_index = 0; frame_index < kNumFramesToProcess; | |
326 ++frame_index) { | |
327 switch (leakage_report_variant) { | |
328 case EchoLeakageTestVariant::kNone: | |
329 break; | |
330 case EchoLeakageTestVariant::kFalseSticky: | |
331 if (frame_index == 0) { | |
332 aec3.ReportEchoLeakage(false); | |
333 } | |
334 break; | |
335 case EchoLeakageTestVariant::kTrueSticky: | |
336 if (frame_index == 0) { | |
337 aec3.ReportEchoLeakage(true); | |
338 } | |
339 break; | |
340 case EchoLeakageTestVariant::kTrueNonSticky: | |
341 if (frame_index == 0) { | |
342 aec3.ReportEchoLeakage(true); | |
343 } else { | |
344 aec3.ReportEchoLeakage(false); | |
345 } | |
346 break; | |
347 } | |
348 | |
349 aec3.AnalyzeCapture(&capture_buffer_); | |
350 OptionalBandSplit(); | |
351 | |
352 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
353 &capture_buffer_.split_bands_f(0)[0], 0); | |
354 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
355 &render_buffer_.split_bands_f(0)[0], 0); | |
356 | |
357 EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); | |
358 aec3.ProcessCapture(&capture_buffer_, false); | |
359 } | |
360 } | |
361 | |
362 // This verifies that saturation information is properly passed to the | |
363 // BlockProcessor. | |
364 // The cases tested are: | |
365 // -That no saturation event is passed to the processor if there is no | |
366 // saturation. | |
367 // -That one frame with one negative saturated sample value is reported to be | |
368 // saturated and that following non-saturated frames are properly reported as | |
369 // not being saturated. | |
370 // -That one frame with one positive saturated sample value is reported to be | |
371 // saturated and that following non-saturated frames are properly reported as | |
372 // not being saturated. | |
373 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive }; | |
374 | |
375 void RunCaptureSaturationVerificationTest( | |
376 SaturationTestVariant saturation_variant) { | |
377 const size_t num_full_blocks_per_frame = | |
378 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize; | |
379 const size_t expected_num_block_to_process = | |
380 (kNumFramesToProcess * | |
381 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) / | |
382 kBlockSize; | |
383 testing::StrictMock<webrtc::test::MockBlockProcessor>* | |
384 block_processor_mock = | |
385 new StrictMock<webrtc::test::MockBlockProcessor>(); | |
386 EXPECT_CALL(*block_processor_mock, BufferRender(testing::_)) | |
387 .Times(expected_num_block_to_process); | |
388 EXPECT_CALL(*block_processor_mock, ReportEchoLeakage(testing::_)).Times(0); | |
389 | |
390 switch (saturation_variant) { | |
391 case SaturationTestVariant::kNone: | |
392 EXPECT_CALL(*block_processor_mock, | |
393 ProcessCapture(testing::_, false, testing::_)) | |
394 .Times(expected_num_block_to_process); | |
395 break; | |
396 case SaturationTestVariant::kOneNegative: | |
397 EXPECT_CALL(*block_processor_mock, | |
398 ProcessCapture(testing::_, true, testing::_)) | |
399 .Times(num_full_blocks_per_frame); | |
400 EXPECT_CALL(*block_processor_mock, | |
401 ProcessCapture(testing::_, false, testing::_)) | |
402 .Times(expected_num_block_to_process - num_full_blocks_per_frame); | |
403 break; | |
404 case SaturationTestVariant::kOnePositive: | |
405 EXPECT_CALL(*block_processor_mock, | |
hlundin-webrtc
2016/12/22 10:23:56
Enforce order here too.
peah-webrtc
2016/12/22 16:40:04
Done.
| |
406 ProcessCapture(testing::_, true, testing::_)) | |
407 .Times(num_full_blocks_per_frame); | |
408 EXPECT_CALL(*block_processor_mock, | |
409 ProcessCapture(testing::_, false, testing::_)) | |
410 .Times(expected_num_block_to_process - num_full_blocks_per_frame); | |
411 break; | |
412 } | |
413 | |
414 EchoCanceller3 aec3(sample_rate_hz_, false, | |
415 std::unique_ptr<BlockProcessor>(block_processor_mock)); | |
416 block_processor_mock = nullptr; | |
hlundin-webrtc
2016/12/22 10:23:57
unique_ptr
peah-webrtc
2016/12/22 16:40:04
Done.
| |
417 | |
418 for (size_t frame_index = 0; frame_index < kNumFramesToProcess; | |
419 ++frame_index) { | |
420 for (int k = 0; k < fullband_frame_length_; ++k) { | |
421 capture_buffer_.channels_f()[0][k] = 0.f; | |
422 } | |
423 switch (saturation_variant) { | |
424 case SaturationTestVariant::kNone: | |
425 break; | |
426 case SaturationTestVariant::kOneNegative: | |
427 if (frame_index == 0) { | |
428 capture_buffer_.channels_f()[0][10] = -32768.f; | |
429 } | |
430 break; | |
431 case SaturationTestVariant::kOnePositive: | |
432 if (frame_index == 0) { | |
433 capture_buffer_.channels_f()[0][10] = 32767.f; | |
434 } | |
435 break; | |
436 } | |
437 | |
438 aec3.AnalyzeCapture(&capture_buffer_); | |
439 OptionalBandSplit(); | |
440 | |
441 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
442 &capture_buffer_.split_bands_f(0)[0], 0); | |
443 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
444 &render_buffer_.split_bands_f(0)[0], 0); | |
445 | |
446 EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); | |
447 aec3.ProcessCapture(&capture_buffer_, false); | |
448 } | |
449 } | |
450 | |
451 // This test verifies that the swapqueue is able to handle jitter in the | |
452 // capture and render API calls. | |
453 void RunRenderSwapQueueVerificationTest() { | |
454 EchoCanceller3 aec3( | |
455 sample_rate_hz_, false, | |
456 std::unique_ptr<BlockProcessor>( | |
457 new RenderTransportVerificationProcessor(num_bands_))); | |
458 | |
459 constexpr size_t kSwapQueueLength = 30; | |
460 for (size_t frame_index = 0; frame_index < kSwapQueueLength; | |
461 ++frame_index) { | |
462 if (sample_rate_hz_ > 16000) { | |
463 render_buffer_.SplitIntoFrequencyBands(); | |
464 } | |
465 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
466 &render_buffer_.split_bands_f(0)[0], 0); | |
467 | |
468 EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); | |
469 } | |
470 | |
471 for (size_t frame_index = 0; frame_index < kSwapQueueLength; | |
472 ++frame_index) { | |
473 aec3.AnalyzeCapture(&capture_buffer_); | |
474 if (sample_rate_hz_ > 16000) { | |
475 capture_buffer_.SplitIntoFrequencyBands(); | |
476 } | |
477 | |
478 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
479 &capture_buffer_.split_bands_f(0)[0], 0); | |
480 | |
481 aec3.ProcessCapture(&capture_buffer_, false); | |
482 EXPECT_TRUE(VerifyOutputFrameBitexactness( | |
483 frame_length_, num_bands_, frame_index, | |
484 &capture_buffer_.split_bands_f(0)[0], -64)); | |
485 } | |
486 } | |
487 | |
488 // This test verifies that a buffer overrun in the render swapqueue is | |
489 // properly reported. | |
490 void RunRenderPipelineSwapQueueOverrunReturnValueTest() { | |
491 EchoCanceller3 aec3(sample_rate_hz_, false); | |
492 | |
493 constexpr size_t kSwapQueueLength = 30; | |
494 for (size_t k = 0; k < 2; ++k) { | |
495 for (size_t frame_index = 0; frame_index < kSwapQueueLength; | |
496 ++frame_index) { | |
497 if (sample_rate_hz_ > 16000) { | |
498 render_buffer_.SplitIntoFrequencyBands(); | |
499 } | |
500 PopulateInputFrame(frame_length_, num_bands_, frame_index, | |
501 &render_buffer_.split_bands_f(0)[0], 0); | |
502 | |
503 if (k == 0) { | |
504 EXPECT_TRUE(aec3.AnalyzeRender(&render_buffer_)); | |
505 } else { | |
506 EXPECT_FALSE(aec3.AnalyzeRender(&render_buffer_)); | |
507 } | |
508 } | |
509 } | |
510 } | |
511 | |
512 private: | |
513 void OptionalBandSplit() { | |
514 if (sample_rate_hz_ > 16000) { | |
515 capture_buffer_.SplitIntoFrequencyBands(); | |
516 render_buffer_.SplitIntoFrequencyBands(); | |
517 } | |
518 } | |
519 | |
520 static constexpr size_t kNumFramesToProcess = 20; | |
521 const int sample_rate_hz_; | |
522 const size_t num_bands_; | |
523 const size_t frame_length_; | |
524 const int fullband_frame_length_; | |
525 AudioBuffer capture_buffer_; | |
526 AudioBuffer render_buffer_; | |
527 | |
528 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester); | |
529 }; | |
530 | |
531 std::string ProduceDebugText(int sample_rate_hz) { | |
532 std::ostringstream ss; | |
hlundin-webrtc
2016/12/22 10:23:57
Won't you have to #include something?
peah-webrtc
2016/12/22 16:40:04
Good find! It must have been indirectly included.
| |
533 ss << "Sample rate: " << sample_rate_hz; | |
534 return ss.str(); | |
535 } | |
536 | |
537 std::string ProduceDebugText(int sample_rate_hz, int variant) { | |
538 std::ostringstream ss; | |
539 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant; | |
540 return ss.str(); | |
541 } | |
542 | |
543 } // namespace | |
544 | |
545 TEST(EchoCanceller3Buffering, CaptureBitexactness) { | |
546 for (auto rate : {8000, 16000, 32000, 48000}) { | |
547 SCOPED_TRACE(ProduceDebugText(rate)); | |
548 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest(); | |
549 } | |
550 } | |
551 | |
552 TEST(EchoCanceller3Buffering, RenderBitexactness) { | |
553 for (auto rate : {8000, 16000, 32000, 48000}) { | |
554 SCOPED_TRACE(ProduceDebugText(rate)); | |
555 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest(); | |
556 } | |
557 } | |
558 | |
559 TEST(EchoCanceller3Buffering, RenderSwapQueue) { | |
560 for (auto rate : {8000, 16000, 32000, 48000}) { | |
561 SCOPED_TRACE(ProduceDebugText(rate)); | |
562 EchoCanceller3Tester(rate).RunRenderSwapQueueVerificationTest(); | |
563 } | |
564 } | |
565 | |
566 TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) { | |
567 for (auto rate : {8000, 16000, 32000, 48000}) { | |
568 SCOPED_TRACE(ProduceDebugText(rate)); | |
569 EchoCanceller3Tester(rate) | |
570 .RunRenderPipelineSwapQueueOverrunReturnValueTest(); | |
571 } | |
572 } | |
573 | |
574 TEST(EchoCanceller3Messaging, CaptureSaturation) { | |
575 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone, | |
576 EchoCanceller3Tester::SaturationTestVariant::kOneNegative, | |
577 EchoCanceller3Tester::SaturationTestVariant::kOnePositive}; | |
578 for (auto rate : {8000, 16000, 32000, 48000}) { | |
579 for (auto variant : variants) { | |
580 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant))); | |
581 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant); | |
582 } | |
583 } | |
584 } | |
585 | |
586 TEST(EchoCanceller3Messaging, EchoPathChange) { | |
587 auto variants = { | |
588 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone, | |
589 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky, | |
590 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky}; | |
591 for (auto rate : {8000, 16000, 32000, 48000}) { | |
592 for (auto variant : variants) { | |
593 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant))); | |
594 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant); | |
595 } | |
596 } | |
597 } | |
598 | |
599 TEST(EchoCanceller3Messaging, EchoLeakage) { | |
600 auto variants = { | |
601 EchoCanceller3Tester::EchoLeakageTestVariant::kNone, | |
602 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky, | |
603 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky, | |
604 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky}; | |
605 for (auto rate : {8000, 16000, 32000, 48000}) { | |
606 for (auto variant : variants) { | |
607 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant))); | |
608 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant); | |
609 } | |
610 } | |
611 } | |
612 | |
613 } // namespace webrtc | |
OLD | NEW |