blob: 75de48b54738e7da9062562d5af152866c25900d [file] [log] [blame]
peahd0263542017-01-03 04:20:34 -08001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/audio_processing/aec3/echo_canceller3.h"
peahd0263542017-01-03 04:20:34 -080012
13#include <deque>
14#include <memory>
15#include <sstream>
16#include <string>
17#include <utility>
18#include <vector>
19
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/audio_processing/aec3/aec3_common.h"
21#include "modules/audio_processing/aec3/block_processor.h"
22#include "modules/audio_processing/aec3/frame_blocker.h"
23#include "modules/audio_processing/aec3/mock/mock_block_processor.h"
24#include "modules/audio_processing/audio_buffer.h"
25#include "test/gmock.h"
26#include "test/gtest.h"
peahd0263542017-01-03 04:20:34 -080027
28namespace webrtc {
29namespace {
30
31using testing::StrictMock;
32using testing::_;
33
34// Populates the frame with linearly increasing sample values for each band,
35// with a band-specific offset, in order to allow simple bitexactness
36// verification for each band.
37void PopulateInputFrame(size_t frame_length,
38 size_t num_bands,
39 size_t frame_index,
40 float* const* frame,
41 int offset) {
42 for (size_t k = 0; k < num_bands; ++k) {
43 for (size_t i = 0; i < frame_length; ++i) {
44 float value = static_cast<int>(frame_index * frame_length + i) + offset;
45 frame[k][i] = (value > 0 ? 5000 * k + value : 0);
46 }
47 }
48}
49
peah522d71b2017-02-23 05:16:26 -080050// Populates the frame with linearly increasing sample values.
51void PopulateInputFrame(size_t frame_length,
52 size_t frame_index,
53 float* frame,
54 int offset) {
55 for (size_t i = 0; i < frame_length; ++i) {
56 float value = static_cast<int>(frame_index * frame_length + i) + offset;
57 frame[i] = std::max(value, 0.f);
58 }
59}
60
peahd0263542017-01-03 04:20:34 -080061// Verifies the that samples in the output frame are identical to the samples
62// that were produced for the input frame, with an offset in order to compensate
63// for buffering delays.
64bool VerifyOutputFrameBitexactness(size_t frame_length,
65 size_t num_bands,
66 size_t frame_index,
67 const float* const* frame,
68 int offset) {
69 float reference_frame_data[kMaxNumBands][2 * kSubFrameLength];
70 float* reference_frame[kMaxNumBands];
71 for (size_t k = 0; k < num_bands; ++k) {
72 reference_frame[k] = &reference_frame_data[k][0];
73 }
74
75 PopulateInputFrame(frame_length, num_bands, frame_index, reference_frame,
76 offset);
77 for (size_t k = 0; k < num_bands; ++k) {
78 for (size_t i = 0; i < frame_length; ++i) {
79 if (reference_frame[k][i] != frame[k][i]) {
80 return false;
81 }
82 }
83 }
84
85 return true;
86}
87
88// Class for testing that the capture data is properly received by the block
89// processor and that the processor data is properly passed to the
90// EchoCanceller3 output.
91class CaptureTransportVerificationProcessor : public BlockProcessor {
92 public:
93 explicit CaptureTransportVerificationProcessor(size_t num_bands) {}
94 ~CaptureTransportVerificationProcessor() override = default;
95
peah69221db2017-01-27 03:28:19 -080096 void ProcessCapture(bool level_change,
peahd0263542017-01-03 04:20:34 -080097 bool saturated_microphone_signal,
98 std::vector<std::vector<float>>* capture_block) override {
99 }
100
peahcf02cf12017-04-05 14:18:07 -0700101 void BufferRender(const std::vector<std::vector<float>>& block) override {}
peahd0263542017-01-03 04:20:34 -0800102
peah69221db2017-01-27 03:28:19 -0800103 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800104
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100105 void GetMetrics(EchoControl::Metrics* metrics) const override {}
106
peahd0263542017-01-03 04:20:34 -0800107 private:
108 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
109};
110
111// Class for testing that the render data is properly received by the block
112// processor.
113class RenderTransportVerificationProcessor : public BlockProcessor {
114 public:
115 explicit RenderTransportVerificationProcessor(size_t num_bands) {}
116 ~RenderTransportVerificationProcessor() override = default;
117
peah69221db2017-01-27 03:28:19 -0800118 void ProcessCapture(bool level_change,
peahd0263542017-01-03 04:20:34 -0800119 bool saturated_microphone_signal,
120 std::vector<std::vector<float>>* capture_block) override {
121 std::vector<std::vector<float>> render_block =
122 received_render_blocks_.front();
123 received_render_blocks_.pop_front();
124 capture_block->swap(render_block);
125 }
126
peahcf02cf12017-04-05 14:18:07 -0700127 void BufferRender(const std::vector<std::vector<float>>& block) override {
128 received_render_blocks_.push_back(block);
peahd0263542017-01-03 04:20:34 -0800129 }
130
peah69221db2017-01-27 03:28:19 -0800131 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800132
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100133 void GetMetrics(EchoControl::Metrics* metrics) const override {}
134
peahd0263542017-01-03 04:20:34 -0800135 private:
136 std::deque<std::vector<std::vector<float>>> received_render_blocks_;
137 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor);
138};
139
140class EchoCanceller3Tester {
141 public:
142 explicit EchoCanceller3Tester(int sample_rate_hz)
143 : sample_rate_hz_(sample_rate_hz),
144 num_bands_(NumBandsForRate(sample_rate_hz_)),
145 frame_length_(sample_rate_hz_ == 8000 ? 80 : 160),
146 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)),
147 capture_buffer_(fullband_frame_length_,
148 1,
149 fullband_frame_length_,
150 1,
151 fullband_frame_length_),
152 render_buffer_(fullband_frame_length_,
153 1,
154 fullband_frame_length_,
155 1,
156 fullband_frame_length_) {}
157
158 // Verifies that the capture data is properly received by the block processor
159 // and that the processor data is properly passed to the EchoCanceller3
160 // output.
161 void RunCaptureTransportVerificationTest() {
162 EchoCanceller3 aec3(
163 sample_rate_hz_, false,
164 std::unique_ptr<BlockProcessor>(
165 new CaptureTransportVerificationProcessor(num_bands_)));
166
167 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
168 ++frame_index) {
169 aec3.AnalyzeCapture(&capture_buffer_);
170 OptionalBandSplit();
171 PopulateInputFrame(frame_length_, num_bands_, frame_index,
172 &capture_buffer_.split_bands_f(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800173 PopulateInputFrame(frame_length_, frame_index,
174 &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800175
peahcf02cf12017-04-05 14:18:07 -0700176 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800177 aec3.ProcessCapture(&capture_buffer_, false);
178 EXPECT_TRUE(VerifyOutputFrameBitexactness(
179 frame_length_, num_bands_, frame_index,
180 &capture_buffer_.split_bands_f(0)[0], -64));
181 }
182 }
183
184 // Test method for testing that the render data is properly received by the
185 // block processor.
186 void RunRenderTransportVerificationTest() {
187 EchoCanceller3 aec3(
188 sample_rate_hz_, false,
189 std::unique_ptr<BlockProcessor>(
190 new RenderTransportVerificationProcessor(num_bands_)));
191
192 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
193 ++frame_index) {
194 aec3.AnalyzeCapture(&capture_buffer_);
195 OptionalBandSplit();
196 PopulateInputFrame(frame_length_, num_bands_, frame_index,
197 &capture_buffer_.split_bands_f(0)[0], 100);
peahcf02cf12017-04-05 14:18:07 -0700198 PopulateInputFrame(frame_length_, num_bands_, frame_index,
199 &render_buffer_.split_bands_f(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800200
peahcf02cf12017-04-05 14:18:07 -0700201 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800202 aec3.ProcessCapture(&capture_buffer_, false);
203 EXPECT_TRUE(VerifyOutputFrameBitexactness(
peahcf02cf12017-04-05 14:18:07 -0700204 frame_length_, num_bands_, frame_index,
205 &capture_buffer_.split_bands_f(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800206 }
207 }
208
209 // Verifies that information about echo path changes are properly propagated
210 // to the block processor.
211 // The cases tested are:
212 // -That no set echo path change flags are received when there is no echo path
213 // change.
214 // -That set echo path change flags are received and continues to be received
215 // as long as echo path changes are flagged.
216 // -That set echo path change flags are no longer received when echo path
217 // change events stop being flagged.
218 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky };
219
220 void RunEchoPathChangeVerificationTest(
221 EchoPathChangeTestVariant echo_path_change_test_variant) {
222 const size_t num_full_blocks_per_frame =
223 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
224 const size_t expected_num_block_to_process =
225 (kNumFramesToProcess *
226 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
227 kBlockSize;
228 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
229 block_processor_mock(
230 new StrictMock<webrtc::test::MockBlockProcessor>());
231 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700232 .Times(expected_num_block_to_process);
peah69221db2017-01-27 03:28:19 -0800233 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800234
235 switch (echo_path_change_test_variant) {
236 case EchoPathChangeTestVariant::kNone:
237 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
238 .Times(expected_num_block_to_process);
239 break;
240 case EchoPathChangeTestVariant::kOneSticky:
241 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
242 .Times(expected_num_block_to_process);
243 break;
244 case EchoPathChangeTestVariant::kOneNonSticky:
245 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
246 .Times(num_full_blocks_per_frame);
247 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
248 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
249 break;
250 }
251
252 EchoCanceller3 aec3(sample_rate_hz_, false,
253 std::move(block_processor_mock));
254
255 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
256 ++frame_index) {
257 bool echo_path_change = false;
258 switch (echo_path_change_test_variant) {
259 case EchoPathChangeTestVariant::kNone:
260 break;
261 case EchoPathChangeTestVariant::kOneSticky:
262 echo_path_change = true;
263 break;
264 case EchoPathChangeTestVariant::kOneNonSticky:
265 if (frame_index == 0) {
266 echo_path_change = true;
267 }
268 break;
269 }
270
271 aec3.AnalyzeCapture(&capture_buffer_);
272 OptionalBandSplit();
273
274 PopulateInputFrame(frame_length_, num_bands_, frame_index,
275 &capture_buffer_.split_bands_f(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800276 PopulateInputFrame(frame_length_, frame_index,
277 &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800278
peahcf02cf12017-04-05 14:18:07 -0700279 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800280 aec3.ProcessCapture(&capture_buffer_, echo_path_change);
281 }
282 }
283
284 // Test for verifying that echo leakage information is being properly passed
285 // to the processor.
286 // The cases tested are:
287 // -That no method calls are received when they should not.
288 // -That false values are received each time they are flagged.
289 // -That true values are received each time they are flagged.
290 // -That a false value is received when flagged after a true value has been
291 // flagged.
292 enum class EchoLeakageTestVariant {
293 kNone,
294 kFalseSticky,
295 kTrueSticky,
296 kTrueNonSticky
297 };
298
299 void RunEchoLeakageVerificationTest(
300 EchoLeakageTestVariant leakage_report_variant) {
301 const size_t expected_num_block_to_process =
302 (kNumFramesToProcess *
303 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
304 kBlockSize;
305 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
306 block_processor_mock(
307 new StrictMock<webrtc::test::MockBlockProcessor>());
308 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700309 .Times(expected_num_block_to_process);
peahd0263542017-01-03 04:20:34 -0800310 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _))
311 .Times(expected_num_block_to_process);
312
313 switch (leakage_report_variant) {
314 case EchoLeakageTestVariant::kNone:
peah69221db2017-01-27 03:28:19 -0800315 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800316 break;
317 case EchoLeakageTestVariant::kFalseSticky:
peah69221db2017-01-27 03:28:19 -0800318 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
319 .Times(1);
peahd0263542017-01-03 04:20:34 -0800320 break;
321 case EchoLeakageTestVariant::kTrueSticky:
peah69221db2017-01-27 03:28:19 -0800322 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
323 .Times(1);
peahd0263542017-01-03 04:20:34 -0800324 break;
325 case EchoLeakageTestVariant::kTrueNonSticky: {
326 testing::InSequence s;
peah69221db2017-01-27 03:28:19 -0800327 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
328 .Times(1);
329 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
peahd0263542017-01-03 04:20:34 -0800330 .Times(kNumFramesToProcess - 1);
331 } break;
332 }
333
334 EchoCanceller3 aec3(sample_rate_hz_, false,
335 std::move(block_processor_mock));
336
337 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
338 ++frame_index) {
339 switch (leakage_report_variant) {
340 case EchoLeakageTestVariant::kNone:
341 break;
342 case EchoLeakageTestVariant::kFalseSticky:
343 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800344 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800345 }
346 break;
347 case EchoLeakageTestVariant::kTrueSticky:
348 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800349 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800350 }
351 break;
352 case EchoLeakageTestVariant::kTrueNonSticky:
353 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800354 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800355 } else {
peah69221db2017-01-27 03:28:19 -0800356 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800357 }
358 break;
359 }
360
361 aec3.AnalyzeCapture(&capture_buffer_);
362 OptionalBandSplit();
363
364 PopulateInputFrame(frame_length_, num_bands_, frame_index,
365 &capture_buffer_.split_bands_f(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800366 PopulateInputFrame(frame_length_, frame_index,
367 &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800368
peahcf02cf12017-04-05 14:18:07 -0700369 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800370 aec3.ProcessCapture(&capture_buffer_, false);
371 }
372 }
373
374 // This verifies that saturation information is properly passed to the
375 // BlockProcessor.
376 // The cases tested are:
377 // -That no saturation event is passed to the processor if there is no
378 // saturation.
379 // -That one frame with one negative saturated sample value is reported to be
380 // saturated and that following non-saturated frames are properly reported as
381 // not being saturated.
382 // -That one frame with one positive saturated sample value is reported to be
383 // saturated and that following non-saturated frames are properly reported as
384 // not being saturated.
385 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive };
386
387 void RunCaptureSaturationVerificationTest(
388 SaturationTestVariant saturation_variant) {
389 const size_t num_full_blocks_per_frame =
390 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
391 const size_t expected_num_block_to_process =
392 (kNumFramesToProcess *
393 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
394 kBlockSize;
395 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
396 block_processor_mock(
397 new StrictMock<webrtc::test::MockBlockProcessor>());
398 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700399 .Times(expected_num_block_to_process);
peah69221db2017-01-27 03:28:19 -0800400 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800401
402 switch (saturation_variant) {
403 case SaturationTestVariant::kNone:
404 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
405 .Times(expected_num_block_to_process);
406 break;
407 case SaturationTestVariant::kOneNegative: {
408 testing::InSequence s;
409 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
410 .Times(num_full_blocks_per_frame);
411 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
412 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
413 } break;
414 case SaturationTestVariant::kOnePositive: {
415 testing::InSequence s;
416 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
417 .Times(num_full_blocks_per_frame);
418 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
419 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
420 } break;
421 }
422
423 EchoCanceller3 aec3(sample_rate_hz_, false,
424 std::move(block_processor_mock));
peahd0263542017-01-03 04:20:34 -0800425 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
426 ++frame_index) {
427 for (int k = 0; k < fullband_frame_length_; ++k) {
428 capture_buffer_.channels_f()[0][k] = 0.f;
429 }
430 switch (saturation_variant) {
431 case SaturationTestVariant::kNone:
432 break;
433 case SaturationTestVariant::kOneNegative:
434 if (frame_index == 0) {
435 capture_buffer_.channels_f()[0][10] = -32768.f;
436 }
437 break;
438 case SaturationTestVariant::kOnePositive:
439 if (frame_index == 0) {
440 capture_buffer_.channels_f()[0][10] = 32767.f;
441 }
442 break;
443 }
444
445 aec3.AnalyzeCapture(&capture_buffer_);
446 OptionalBandSplit();
447
448 PopulateInputFrame(frame_length_, num_bands_, frame_index,
449 &capture_buffer_.split_bands_f(0)[0], 0);
peahcf02cf12017-04-05 14:18:07 -0700450 PopulateInputFrame(frame_length_, num_bands_, frame_index,
451 &render_buffer_.split_bands_f(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800452
peahcf02cf12017-04-05 14:18:07 -0700453 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800454 aec3.ProcessCapture(&capture_buffer_, false);
455 }
456 }
457
458 // This test verifies that the swapqueue is able to handle jitter in the
459 // capture and render API calls.
460 void RunRenderSwapQueueVerificationTest() {
461 EchoCanceller3 aec3(
462 sample_rate_hz_, false,
463 std::unique_ptr<BlockProcessor>(
464 new RenderTransportVerificationProcessor(num_bands_)));
465
peahcf02cf12017-04-05 14:18:07 -0700466 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
peahd0263542017-01-03 04:20:34 -0800467 ++frame_index) {
468 if (sample_rate_hz_ > 16000) {
469 render_buffer_.SplitIntoFrequencyBands();
470 }
peahcf02cf12017-04-05 14:18:07 -0700471 PopulateInputFrame(frame_length_, num_bands_, frame_index,
472 &render_buffer_.split_bands_f(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800473
peahcf02cf12017-04-05 14:18:07 -0700474 if (sample_rate_hz_ > 16000) {
475 render_buffer_.SplitIntoFrequencyBands();
476 }
477
478 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800479 }
480
peahcf02cf12017-04-05 14:18:07 -0700481 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
peahd0263542017-01-03 04:20:34 -0800482 ++frame_index) {
483 aec3.AnalyzeCapture(&capture_buffer_);
484 if (sample_rate_hz_ > 16000) {
485 capture_buffer_.SplitIntoFrequencyBands();
486 }
487
488 PopulateInputFrame(frame_length_, num_bands_, frame_index,
489 &capture_buffer_.split_bands_f(0)[0], 0);
490
491 aec3.ProcessCapture(&capture_buffer_, false);
492 EXPECT_TRUE(VerifyOutputFrameBitexactness(
peahcf02cf12017-04-05 14:18:07 -0700493 frame_length_, num_bands_, frame_index,
494 &capture_buffer_.split_bands_f(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800495 }
496 }
497
498 // This test verifies that a buffer overrun in the render swapqueue is
499 // properly reported.
500 void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200501 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false);
peahd0263542017-01-03 04:20:34 -0800502
peahcf02cf12017-04-05 14:18:07 -0700503 constexpr size_t kRenderTransferQueueSize = 30;
peahd0263542017-01-03 04:20:34 -0800504 for (size_t k = 0; k < 2; ++k) {
peahcf02cf12017-04-05 14:18:07 -0700505 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
peahd0263542017-01-03 04:20:34 -0800506 ++frame_index) {
507 if (sample_rate_hz_ > 16000) {
508 render_buffer_.SplitIntoFrequencyBands();
509 }
peah522d71b2017-02-23 05:16:26 -0800510 PopulateInputFrame(frame_length_, frame_index,
511 &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800512
513 if (k == 0) {
peahcf02cf12017-04-05 14:18:07 -0700514 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800515 } else {
peahcf02cf12017-04-05 14:18:07 -0700516 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800517 }
518 }
519 }
520 }
521
522#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
523 // Verifies the that the check for the number of bands in the AnalyzeRender
524 // input is correct by adjusting the sample rates of EchoCanceller3 and the
525 // input AudioBuffer to have a different number of bands.
526 void RunAnalyzeRenderNumBandsCheckVerification() {
527 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
528 // way that the number of bands for the rates are different.
529 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200530 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peah522d71b2017-02-23 05:16:26 -0800531 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800532
533 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
534 }
535
536 // Verifies the that the check for the number of bands in the ProcessCapture
537 // input is correct by adjusting the sample rates of EchoCanceller3 and the
538 // input AudioBuffer to have a different number of bands.
539 void RunProcessCaptureNumBandsCheckVerification() {
540 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
541 // way that the number of bands for the rates are different.
542 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200543 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800544 PopulateInputFrame(frame_length_, num_bands_, 0,
545 &capture_buffer_.split_bands_f(0)[0], 100);
546 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
547 }
548
549 // Verifies the that the check for the frame length in the AnalyzeRender input
550 // is correct by adjusting the sample rates of EchoCanceller3 and the input
551 // AudioBuffer to have a different frame lengths.
552 void RunAnalyzeRenderFrameLengthCheckVerification() {
553 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
554 // way that the band frame lengths are different.
555 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200556 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800557
558 OptionalBandSplit();
peah522d71b2017-02-23 05:16:26 -0800559 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800560
561 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
562 }
563
564 // Verifies the that the check for the frame length in the AnalyzeRender input
565 // is correct by adjusting the sample rates of EchoCanceller3 and the input
566 // AudioBuffer to have a different frame lengths.
567 void RunProcessCaptureFrameLengthCheckVerification() {
568 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
569 // way that the band frame lengths are different.
570 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200571 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800572
573 OptionalBandSplit();
574 PopulateInputFrame(frame_length_, num_bands_, 0,
575 &capture_buffer_.split_bands_f(0)[0], 100);
576
577 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
578 }
579
580#endif
581
582 private:
583 void OptionalBandSplit() {
584 if (sample_rate_hz_ > 16000) {
585 capture_buffer_.SplitIntoFrequencyBands();
586 render_buffer_.SplitIntoFrequencyBands();
587 }
588 }
589
590 static constexpr size_t kNumFramesToProcess = 20;
591 const int sample_rate_hz_;
592 const size_t num_bands_;
593 const size_t frame_length_;
594 const int fullband_frame_length_;
595 AudioBuffer capture_buffer_;
596 AudioBuffer render_buffer_;
597
598 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester);
599};
600
601std::string ProduceDebugText(int sample_rate_hz) {
602 std::ostringstream ss;
603 ss << "Sample rate: " << sample_rate_hz;
604 return ss.str();
605}
606
607std::string ProduceDebugText(int sample_rate_hz, int variant) {
608 std::ostringstream ss;
609 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant;
610 return ss.str();
611}
612
613} // namespace
614
615TEST(EchoCanceller3Buffering, CaptureBitexactness) {
616 for (auto rate : {8000, 16000, 32000, 48000}) {
617 SCOPED_TRACE(ProduceDebugText(rate));
618 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest();
619 }
620}
621
622TEST(EchoCanceller3Buffering, RenderBitexactness) {
623 for (auto rate : {8000, 16000, 32000, 48000}) {
624 SCOPED_TRACE(ProduceDebugText(rate));
625 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest();
626 }
627}
628
629TEST(EchoCanceller3Buffering, RenderSwapQueue) {
peahcf02cf12017-04-05 14:18:07 -0700630 for (auto rate : {8000, 16000}) {
peahd0263542017-01-03 04:20:34 -0800631 SCOPED_TRACE(ProduceDebugText(rate));
632 EchoCanceller3Tester(rate).RunRenderSwapQueueVerificationTest();
633 }
634}
635
636TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) {
637 for (auto rate : {8000, 16000, 32000, 48000}) {
638 SCOPED_TRACE(ProduceDebugText(rate));
639 EchoCanceller3Tester(rate)
640 .RunRenderPipelineSwapQueueOverrunReturnValueTest();
641 }
642}
643
644TEST(EchoCanceller3Messaging, CaptureSaturation) {
645 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone,
646 EchoCanceller3Tester::SaturationTestVariant::kOneNegative,
647 EchoCanceller3Tester::SaturationTestVariant::kOnePositive};
648 for (auto rate : {8000, 16000, 32000, 48000}) {
649 for (auto variant : variants) {
650 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
651 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant);
652 }
653 }
654}
655
656TEST(EchoCanceller3Messaging, EchoPathChange) {
657 auto variants = {
658 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone,
659 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky,
660 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky};
661 for (auto rate : {8000, 16000, 32000, 48000}) {
662 for (auto variant : variants) {
663 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
664 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant);
665 }
666 }
667}
668
669TEST(EchoCanceller3Messaging, EchoLeakage) {
670 auto variants = {
671 EchoCanceller3Tester::EchoLeakageTestVariant::kNone,
672 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky,
673 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky,
674 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky};
675 for (auto rate : {8000, 16000, 32000, 48000}) {
676 for (auto variant : variants) {
677 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
678 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant);
679 }
680 }
681}
682
peah697a5902017-06-30 07:06:10 -0700683TEST(EchoCanceller3, ConfigValidation) {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200684 EchoCanceller3Config config;
peah697a5902017-06-30 07:06:10 -0700685 EXPECT_TRUE(EchoCanceller3::Validate(config));
peah697a5902017-06-30 07:06:10 -0700686}
687
peahd0263542017-01-03 04:20:34 -0800688#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
peahd0263542017-01-03 04:20:34 -0800689
690TEST(EchoCanceller3InputCheck, WrongCaptureNumBandsCheckVerification) {
691 for (auto rate : {8000, 16000, 32000, 48000}) {
692 SCOPED_TRACE(ProduceDebugText(rate));
693 EchoCanceller3Tester(rate).RunProcessCaptureNumBandsCheckVerification();
694 }
695}
696
peah522d71b2017-02-23 05:16:26 -0800697// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
698// tests on test bots has been fixed.
699TEST(EchoCanceller3InputCheck,
700 DISABLED_WrongRenderFrameLengthCheckVerification) {
peahd0263542017-01-03 04:20:34 -0800701 for (auto rate : {8000, 16000}) {
702 SCOPED_TRACE(ProduceDebugText(rate));
703 EchoCanceller3Tester(rate).RunAnalyzeRenderFrameLengthCheckVerification();
704 }
705}
706
707TEST(EchoCanceller3InputCheck, WrongCaptureFrameLengthCheckVerification) {
708 for (auto rate : {8000, 16000}) {
709 SCOPED_TRACE(ProduceDebugText(rate));
710 EchoCanceller3Tester(rate).RunProcessCaptureFrameLengthCheckVerification();
711 }
712}
713
714// Verifiers that the verification for null input to the render analysis api
715// call works.
716TEST(EchoCanceller3InputCheck, NullRenderAnalysisParameter) {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200717 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
718 .AnalyzeRender(nullptr),
719 "");
peahd0263542017-01-03 04:20:34 -0800720}
721
722// Verifiers that the verification for null input to the capture analysis api
723// call works.
724TEST(EchoCanceller3InputCheck, NullCaptureAnalysisParameter) {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200725 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
726 .AnalyzeCapture(nullptr),
727 "");
peahd0263542017-01-03 04:20:34 -0800728}
729
730// Verifiers that the verification for null input to the capture processing api
731// call works.
732TEST(EchoCanceller3InputCheck, NullCaptureProcessingParameter) {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200733 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8000, false)
734 .ProcessCapture(nullptr, false),
735 "");
peahd0263542017-01-03 04:20:34 -0800736}
737
peah21920892017-02-08 05:08:56 -0800738// Verifies the check for correct sample rate.
peahcf02cf12017-04-05 14:18:07 -0700739// TODO(peah): Re-enable the test once the issue with memory leaks during DEATH
740// tests on test bots has been fixed.
741TEST(EchoCanceller3InputCheck, DISABLED_WrongSampleRate) {
peah21920892017-02-08 05:08:56 -0800742 ApmDataDumper data_dumper(0);
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200743 EXPECT_DEATH(EchoCanceller3(EchoCanceller3Config(), 8001, false), "");
peah21920892017-02-08 05:08:56 -0800744}
745
peahd0263542017-01-03 04:20:34 -0800746#endif
747
748} // namespace webrtc