blob: 267213ea3494d9ca687b8a380174ffefe7d0eb86 [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>
peahd0263542017-01-03 04:20:34 -080015#include <string>
16#include <utility>
17#include <vector>
18
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "modules/audio_processing/aec3/aec3_common.h"
20#include "modules/audio_processing/aec3/block_processor.h"
21#include "modules/audio_processing/aec3/frame_blocker.h"
22#include "modules/audio_processing/aec3/mock/mock_block_processor.h"
23#include "modules/audio_processing/audio_buffer.h"
Jonas Olsson366a50c2018-09-06 13:41:30 +020024#include "rtc_base/strings/string_builder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#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
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100107 void SetAudioBufferDelay(size_t delay_ms) override {}
Per Ã…hgrend0fa8202018-04-18 09:35:13 +0200108
peahd0263542017-01-03 04:20:34 -0800109 private:
110 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CaptureTransportVerificationProcessor);
111};
112
113// Class for testing that the render data is properly received by the block
114// processor.
115class RenderTransportVerificationProcessor : public BlockProcessor {
116 public:
117 explicit RenderTransportVerificationProcessor(size_t num_bands) {}
118 ~RenderTransportVerificationProcessor() override = default;
119
peah69221db2017-01-27 03:28:19 -0800120 void ProcessCapture(bool level_change,
peahd0263542017-01-03 04:20:34 -0800121 bool saturated_microphone_signal,
122 std::vector<std::vector<float>>* capture_block) override {
123 std::vector<std::vector<float>> render_block =
124 received_render_blocks_.front();
125 received_render_blocks_.pop_front();
126 capture_block->swap(render_block);
127 }
128
peahcf02cf12017-04-05 14:18:07 -0700129 void BufferRender(const std::vector<std::vector<float>>& block) override {
130 received_render_blocks_.push_back(block);
peahd0263542017-01-03 04:20:34 -0800131 }
132
peah69221db2017-01-27 03:28:19 -0800133 void UpdateEchoLeakageStatus(bool leakage_detected) override {}
peahd0263542017-01-03 04:20:34 -0800134
Gustaf Ullberg332150d2017-11-22 14:17:39 +0100135 void GetMetrics(EchoControl::Metrics* metrics) const override {}
136
Mirko Bonadeic4dd7302019-02-25 09:12:02 +0100137 void SetAudioBufferDelay(size_t delay_ms) override {}
Per Ã…hgrend0fa8202018-04-18 09:35:13 +0200138
peahd0263542017-01-03 04:20:34 -0800139 private:
140 std::deque<std::vector<std::vector<float>>> received_render_blocks_;
141 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RenderTransportVerificationProcessor);
142};
143
144class EchoCanceller3Tester {
145 public:
146 explicit EchoCanceller3Tester(int sample_rate_hz)
147 : sample_rate_hz_(sample_rate_hz),
148 num_bands_(NumBandsForRate(sample_rate_hz_)),
149 frame_length_(sample_rate_hz_ == 8000 ? 80 : 160),
150 fullband_frame_length_(rtc::CheckedDivExact(sample_rate_hz_, 100)),
151 capture_buffer_(fullband_frame_length_,
152 1,
153 fullband_frame_length_,
154 1,
155 fullband_frame_length_),
156 render_buffer_(fullband_frame_length_,
157 1,
158 fullband_frame_length_,
159 1,
160 fullband_frame_length_) {}
161
162 // Verifies that the capture data is properly received by the block processor
163 // and that the processor data is properly passed to the EchoCanceller3
164 // output.
165 void RunCaptureTransportVerificationTest() {
166 EchoCanceller3 aec3(
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100167 EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800168 std::unique_ptr<BlockProcessor>(
169 new CaptureTransportVerificationProcessor(num_bands_)));
170
171 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
172 ++frame_index) {
173 aec3.AnalyzeCapture(&capture_buffer_);
174 OptionalBandSplit();
175 PopulateInputFrame(frame_length_, num_bands_, frame_index,
176 &capture_buffer_.split_bands_f(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800177 PopulateInputFrame(frame_length_, frame_index,
178 &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800179
peahcf02cf12017-04-05 14:18:07 -0700180 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800181 aec3.ProcessCapture(&capture_buffer_, false);
182 EXPECT_TRUE(VerifyOutputFrameBitexactness(
183 frame_length_, num_bands_, frame_index,
184 &capture_buffer_.split_bands_f(0)[0], -64));
185 }
186 }
187
188 // Test method for testing that the render data is properly received by the
189 // block processor.
190 void RunRenderTransportVerificationTest() {
191 EchoCanceller3 aec3(
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100192 EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800193 std::unique_ptr<BlockProcessor>(
194 new RenderTransportVerificationProcessor(num_bands_)));
195
196 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
197 ++frame_index) {
198 aec3.AnalyzeCapture(&capture_buffer_);
199 OptionalBandSplit();
200 PopulateInputFrame(frame_length_, num_bands_, frame_index,
201 &capture_buffer_.split_bands_f(0)[0], 100);
peahcf02cf12017-04-05 14:18:07 -0700202 PopulateInputFrame(frame_length_, num_bands_, frame_index,
203 &render_buffer_.split_bands_f(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800204
peahcf02cf12017-04-05 14:18:07 -0700205 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800206 aec3.ProcessCapture(&capture_buffer_, false);
207 EXPECT_TRUE(VerifyOutputFrameBitexactness(
peahcf02cf12017-04-05 14:18:07 -0700208 frame_length_, num_bands_, frame_index,
209 &capture_buffer_.split_bands_f(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800210 }
211 }
212
213 // Verifies that information about echo path changes are properly propagated
214 // to the block processor.
215 // The cases tested are:
216 // -That no set echo path change flags are received when there is no echo path
217 // change.
218 // -That set echo path change flags are received and continues to be received
219 // as long as echo path changes are flagged.
220 // -That set echo path change flags are no longer received when echo path
221 // change events stop being flagged.
222 enum class EchoPathChangeTestVariant { kNone, kOneSticky, kOneNonSticky };
223
224 void RunEchoPathChangeVerificationTest(
225 EchoPathChangeTestVariant echo_path_change_test_variant) {
226 const size_t num_full_blocks_per_frame =
227 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
228 const size_t expected_num_block_to_process =
229 (kNumFramesToProcess *
230 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
231 kBlockSize;
232 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
233 block_processor_mock(
234 new StrictMock<webrtc::test::MockBlockProcessor>());
235 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700236 .Times(expected_num_block_to_process);
peah69221db2017-01-27 03:28:19 -0800237 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800238
239 switch (echo_path_change_test_variant) {
240 case EchoPathChangeTestVariant::kNone:
241 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
242 .Times(expected_num_block_to_process);
243 break;
244 case EchoPathChangeTestVariant::kOneSticky:
245 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
246 .Times(expected_num_block_to_process);
247 break;
248 case EchoPathChangeTestVariant::kOneNonSticky:
249 EXPECT_CALL(*block_processor_mock, ProcessCapture(true, _, _))
250 .Times(num_full_blocks_per_frame);
251 EXPECT_CALL(*block_processor_mock, ProcessCapture(false, _, _))
252 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
253 break;
254 }
255
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100256 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800257 std::move(block_processor_mock));
258
259 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
260 ++frame_index) {
261 bool echo_path_change = false;
262 switch (echo_path_change_test_variant) {
263 case EchoPathChangeTestVariant::kNone:
264 break;
265 case EchoPathChangeTestVariant::kOneSticky:
266 echo_path_change = true;
267 break;
268 case EchoPathChangeTestVariant::kOneNonSticky:
269 if (frame_index == 0) {
270 echo_path_change = true;
271 }
272 break;
273 }
274
275 aec3.AnalyzeCapture(&capture_buffer_);
276 OptionalBandSplit();
277
278 PopulateInputFrame(frame_length_, num_bands_, frame_index,
279 &capture_buffer_.split_bands_f(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800280 PopulateInputFrame(frame_length_, frame_index,
281 &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800282
peahcf02cf12017-04-05 14:18:07 -0700283 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800284 aec3.ProcessCapture(&capture_buffer_, echo_path_change);
285 }
286 }
287
288 // Test for verifying that echo leakage information is being properly passed
289 // to the processor.
290 // The cases tested are:
291 // -That no method calls are received when they should not.
292 // -That false values are received each time they are flagged.
293 // -That true values are received each time they are flagged.
294 // -That a false value is received when flagged after a true value has been
295 // flagged.
296 enum class EchoLeakageTestVariant {
297 kNone,
298 kFalseSticky,
299 kTrueSticky,
300 kTrueNonSticky
301 };
302
303 void RunEchoLeakageVerificationTest(
304 EchoLeakageTestVariant leakage_report_variant) {
305 const size_t expected_num_block_to_process =
306 (kNumFramesToProcess *
307 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
308 kBlockSize;
309 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
310 block_processor_mock(
311 new StrictMock<webrtc::test::MockBlockProcessor>());
312 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700313 .Times(expected_num_block_to_process);
peahd0263542017-01-03 04:20:34 -0800314 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, _, _))
315 .Times(expected_num_block_to_process);
316
317 switch (leakage_report_variant) {
318 case EchoLeakageTestVariant::kNone:
peah69221db2017-01-27 03:28:19 -0800319 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800320 break;
321 case EchoLeakageTestVariant::kFalseSticky:
peah69221db2017-01-27 03:28:19 -0800322 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
323 .Times(1);
peahd0263542017-01-03 04:20:34 -0800324 break;
325 case EchoLeakageTestVariant::kTrueSticky:
peah69221db2017-01-27 03:28:19 -0800326 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
327 .Times(1);
peahd0263542017-01-03 04:20:34 -0800328 break;
329 case EchoLeakageTestVariant::kTrueNonSticky: {
330 testing::InSequence s;
peah69221db2017-01-27 03:28:19 -0800331 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(true))
332 .Times(1);
333 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(false))
peahd0263542017-01-03 04:20:34 -0800334 .Times(kNumFramesToProcess - 1);
335 } break;
336 }
337
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100338 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800339 std::move(block_processor_mock));
340
341 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
342 ++frame_index) {
343 switch (leakage_report_variant) {
344 case EchoLeakageTestVariant::kNone:
345 break;
346 case EchoLeakageTestVariant::kFalseSticky:
347 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800348 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800349 }
350 break;
351 case EchoLeakageTestVariant::kTrueSticky:
352 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800353 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800354 }
355 break;
356 case EchoLeakageTestVariant::kTrueNonSticky:
357 if (frame_index == 0) {
peah69221db2017-01-27 03:28:19 -0800358 aec3.UpdateEchoLeakageStatus(true);
peahd0263542017-01-03 04:20:34 -0800359 } else {
peah69221db2017-01-27 03:28:19 -0800360 aec3.UpdateEchoLeakageStatus(false);
peahd0263542017-01-03 04:20:34 -0800361 }
362 break;
363 }
364
365 aec3.AnalyzeCapture(&capture_buffer_);
366 OptionalBandSplit();
367
368 PopulateInputFrame(frame_length_, num_bands_, frame_index,
369 &capture_buffer_.split_bands_f(0)[0], 0);
peah522d71b2017-02-23 05:16:26 -0800370 PopulateInputFrame(frame_length_, frame_index,
371 &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800372
peahcf02cf12017-04-05 14:18:07 -0700373 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800374 aec3.ProcessCapture(&capture_buffer_, false);
375 }
376 }
377
378 // This verifies that saturation information is properly passed to the
379 // BlockProcessor.
380 // The cases tested are:
381 // -That no saturation event is passed to the processor if there is no
382 // saturation.
383 // -That one frame with one negative saturated sample value is reported to be
384 // saturated and that following non-saturated frames are properly reported as
385 // not being saturated.
386 // -That one frame with one positive saturated sample value is reported to be
387 // saturated and that following non-saturated frames are properly reported as
388 // not being saturated.
389 enum class SaturationTestVariant { kNone, kOneNegative, kOnePositive };
390
391 void RunCaptureSaturationVerificationTest(
392 SaturationTestVariant saturation_variant) {
393 const size_t num_full_blocks_per_frame =
394 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100) / kBlockSize;
395 const size_t expected_num_block_to_process =
396 (kNumFramesToProcess *
397 rtc::CheckedDivExact(LowestBandRate(sample_rate_hz_), 100)) /
398 kBlockSize;
399 std::unique_ptr<testing::StrictMock<webrtc::test::MockBlockProcessor>>
400 block_processor_mock(
401 new StrictMock<webrtc::test::MockBlockProcessor>());
402 EXPECT_CALL(*block_processor_mock, BufferRender(_))
peahcf02cf12017-04-05 14:18:07 -0700403 .Times(expected_num_block_to_process);
peah69221db2017-01-27 03:28:19 -0800404 EXPECT_CALL(*block_processor_mock, UpdateEchoLeakageStatus(_)).Times(0);
peahd0263542017-01-03 04:20:34 -0800405
406 switch (saturation_variant) {
407 case SaturationTestVariant::kNone:
408 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
409 .Times(expected_num_block_to_process);
410 break;
411 case SaturationTestVariant::kOneNegative: {
412 testing::InSequence s;
413 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
414 .Times(num_full_blocks_per_frame);
415 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
416 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
417 } break;
418 case SaturationTestVariant::kOnePositive: {
419 testing::InSequence s;
420 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, true, _))
421 .Times(num_full_blocks_per_frame);
422 EXPECT_CALL(*block_processor_mock, ProcessCapture(_, false, _))
423 .Times(expected_num_block_to_process - num_full_blocks_per_frame);
424 } break;
425 }
426
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100427 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800428 std::move(block_processor_mock));
peahd0263542017-01-03 04:20:34 -0800429 for (size_t frame_index = 0; frame_index < kNumFramesToProcess;
430 ++frame_index) {
431 for (int k = 0; k < fullband_frame_length_; ++k) {
432 capture_buffer_.channels_f()[0][k] = 0.f;
433 }
434 switch (saturation_variant) {
435 case SaturationTestVariant::kNone:
436 break;
437 case SaturationTestVariant::kOneNegative:
438 if (frame_index == 0) {
439 capture_buffer_.channels_f()[0][10] = -32768.f;
440 }
441 break;
442 case SaturationTestVariant::kOnePositive:
443 if (frame_index == 0) {
444 capture_buffer_.channels_f()[0][10] = 32767.f;
445 }
446 break;
447 }
448
449 aec3.AnalyzeCapture(&capture_buffer_);
450 OptionalBandSplit();
451
452 PopulateInputFrame(frame_length_, num_bands_, frame_index,
453 &capture_buffer_.split_bands_f(0)[0], 0);
peahcf02cf12017-04-05 14:18:07 -0700454 PopulateInputFrame(frame_length_, num_bands_, frame_index,
455 &render_buffer_.split_bands_f(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800456
peahcf02cf12017-04-05 14:18:07 -0700457 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800458 aec3.ProcessCapture(&capture_buffer_, false);
459 }
460 }
461
462 // This test verifies that the swapqueue is able to handle jitter in the
463 // capture and render API calls.
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000464 void RunRenderSwapQueueVerificationTest() {
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100465 const EchoCanceller3Config config;
peahd0263542017-01-03 04:20:34 -0800466 EchoCanceller3 aec3(
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100467 config, sample_rate_hz_, false,
peahd0263542017-01-03 04:20:34 -0800468 std::unique_ptr<BlockProcessor>(
469 new RenderTransportVerificationProcessor(num_bands_)));
470
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100471 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
peahd0263542017-01-03 04:20:34 -0800472 ++frame_index) {
473 if (sample_rate_hz_ > 16000) {
474 render_buffer_.SplitIntoFrequencyBands();
475 }
peahcf02cf12017-04-05 14:18:07 -0700476 PopulateInputFrame(frame_length_, num_bands_, frame_index,
477 &render_buffer_.split_bands_f(0)[0], 0);
peahd0263542017-01-03 04:20:34 -0800478
peahcf02cf12017-04-05 14:18:07 -0700479 if (sample_rate_hz_ > 16000) {
480 render_buffer_.SplitIntoFrequencyBands();
481 }
482
483 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800484 }
485
Per Ã…hgren8ba58612017-12-01 23:01:44 +0100486 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSizeFrames;
peahd0263542017-01-03 04:20:34 -0800487 ++frame_index) {
488 aec3.AnalyzeCapture(&capture_buffer_);
489 if (sample_rate_hz_ > 16000) {
490 capture_buffer_.SplitIntoFrequencyBands();
491 }
492
493 PopulateInputFrame(frame_length_, num_bands_, frame_index,
494 &capture_buffer_.split_bands_f(0)[0], 0);
495
496 aec3.ProcessCapture(&capture_buffer_, false);
497 EXPECT_TRUE(VerifyOutputFrameBitexactness(
peahcf02cf12017-04-05 14:18:07 -0700498 frame_length_, num_bands_, frame_index,
499 &capture_buffer_.split_bands_f(0)[0], -64));
peahd0263542017-01-03 04:20:34 -0800500 }
501 }
502
503 // This test verifies that a buffer overrun in the render swapqueue is
504 // properly reported.
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000505 void RunRenderPipelineSwapQueueOverrunReturnValueTest() {
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200506 EchoCanceller3 aec3(EchoCanceller3Config(), sample_rate_hz_, false);
peahd0263542017-01-03 04:20:34 -0800507
peahcf02cf12017-04-05 14:18:07 -0700508 constexpr size_t kRenderTransferQueueSize = 30;
peahd0263542017-01-03 04:20:34 -0800509 for (size_t k = 0; k < 2; ++k) {
peahcf02cf12017-04-05 14:18:07 -0700510 for (size_t frame_index = 0; frame_index < kRenderTransferQueueSize;
peahd0263542017-01-03 04:20:34 -0800511 ++frame_index) {
512 if (sample_rate_hz_ > 16000) {
513 render_buffer_.SplitIntoFrequencyBands();
514 }
peah522d71b2017-02-23 05:16:26 -0800515 PopulateInputFrame(frame_length_, frame_index,
516 &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800517
518 if (k == 0) {
peahcf02cf12017-04-05 14:18:07 -0700519 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800520 } else {
peahcf02cf12017-04-05 14:18:07 -0700521 aec3.AnalyzeRender(&render_buffer_);
peahd0263542017-01-03 04:20:34 -0800522 }
523 }
524 }
525 }
526
527#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
528 // Verifies the that the check for the number of bands in the AnalyzeRender
529 // input is correct by adjusting the sample rates of EchoCanceller3 and the
530 // input AudioBuffer to have a different number of bands.
531 void RunAnalyzeRenderNumBandsCheckVerification() {
532 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
533 // way that the number of bands for the rates are different.
534 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200535 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peah522d71b2017-02-23 05:16:26 -0800536 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800537
538 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
539 }
540
541 // Verifies the that the check for the number of bands in the ProcessCapture
542 // input is correct by adjusting the sample rates of EchoCanceller3 and the
543 // input AudioBuffer to have a different number of bands.
544 void RunProcessCaptureNumBandsCheckVerification() {
545 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
546 // way that the number of bands for the rates are different.
547 const int aec3_sample_rate_hz = sample_rate_hz_ == 48000 ? 32000 : 48000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200548 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800549 PopulateInputFrame(frame_length_, num_bands_, 0,
550 &capture_buffer_.split_bands_f(0)[0], 100);
551 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
552 }
553
554 // Verifies the that the check for the frame length in the AnalyzeRender input
555 // is correct by adjusting the sample rates of EchoCanceller3 and the input
556 // AudioBuffer to have a different frame lengths.
557 void RunAnalyzeRenderFrameLengthCheckVerification() {
558 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
559 // way that the band frame lengths are different.
560 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200561 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800562
563 OptionalBandSplit();
peah522d71b2017-02-23 05:16:26 -0800564 PopulateInputFrame(frame_length_, 0, &render_buffer_.channels_f()[0][0], 0);
peahd0263542017-01-03 04:20:34 -0800565
566 EXPECT_DEATH(aec3.AnalyzeRender(&render_buffer_), "");
567 }
568
569 // Verifies the that the check for the frame length in the AnalyzeRender input
570 // is correct by adjusting the sample rates of EchoCanceller3 and the input
571 // AudioBuffer to have a different frame lengths.
572 void RunProcessCaptureFrameLengthCheckVerification() {
573 // Set aec3_sample_rate_hz to be different from sample_rate_hz_ in such a
574 // way that the band frame lengths are different.
575 const int aec3_sample_rate_hz = sample_rate_hz_ == 8000 ? 16000 : 8000;
Gustaf Ullbergbd83b912017-10-18 12:32:42 +0200576 EchoCanceller3 aec3(EchoCanceller3Config(), aec3_sample_rate_hz, false);
peahd0263542017-01-03 04:20:34 -0800577
578 OptionalBandSplit();
579 PopulateInputFrame(frame_length_, num_bands_, 0,
580 &capture_buffer_.split_bands_f(0)[0], 100);
581
582 EXPECT_DEATH(aec3.ProcessCapture(&capture_buffer_, false), "");
583 }
584
585#endif
586
587 private:
588 void OptionalBandSplit() {
589 if (sample_rate_hz_ > 16000) {
590 capture_buffer_.SplitIntoFrequencyBands();
591 render_buffer_.SplitIntoFrequencyBands();
592 }
593 }
594
595 static constexpr size_t kNumFramesToProcess = 20;
596 const int sample_rate_hz_;
597 const size_t num_bands_;
598 const size_t frame_length_;
599 const int fullband_frame_length_;
600 AudioBuffer capture_buffer_;
601 AudioBuffer render_buffer_;
602
603 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EchoCanceller3Tester);
604};
605
606std::string ProduceDebugText(int sample_rate_hz) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200607 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800608 ss << "Sample rate: " << sample_rate_hz;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200609 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800610}
611
612std::string ProduceDebugText(int sample_rate_hz, int variant) {
Jonas Olsson366a50c2018-09-06 13:41:30 +0200613 rtc::StringBuilder ss;
peahd0263542017-01-03 04:20:34 -0800614 ss << "Sample rate: " << sample_rate_hz << ", variant: " << variant;
Jonas Olsson84df1c72018-09-14 16:59:32 +0200615 return ss.Release();
peahd0263542017-01-03 04:20:34 -0800616}
617
618} // namespace
619
620TEST(EchoCanceller3Buffering, CaptureBitexactness) {
621 for (auto rate : {8000, 16000, 32000, 48000}) {
622 SCOPED_TRACE(ProduceDebugText(rate));
623 EchoCanceller3Tester(rate).RunCaptureTransportVerificationTest();
624 }
625}
626
627TEST(EchoCanceller3Buffering, RenderBitexactness) {
628 for (auto rate : {8000, 16000, 32000, 48000}) {
629 SCOPED_TRACE(ProduceDebugText(rate));
630 EchoCanceller3Tester(rate).RunRenderTransportVerificationTest();
631 }
632}
633
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000634TEST(EchoCanceller3Buffering, RenderSwapQueue) {
peahcf02cf12017-04-05 14:18:07 -0700635 for (auto rate : {8000, 16000}) {
peahd0263542017-01-03 04:20:34 -0800636 SCOPED_TRACE(ProduceDebugText(rate));
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000637 EchoCanceller3Tester(rate).RunRenderSwapQueueVerificationTest();
peahd0263542017-01-03 04:20:34 -0800638 }
639}
640
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000641TEST(EchoCanceller3Buffering, RenderSwapQueueOverrunReturnValue) {
peahd0263542017-01-03 04:20:34 -0800642 for (auto rate : {8000, 16000, 32000, 48000}) {
643 SCOPED_TRACE(ProduceDebugText(rate));
644 EchoCanceller3Tester(rate)
Mirko Bonadeif0d9cda2019-01-17 20:43:58 +0000645 .RunRenderPipelineSwapQueueOverrunReturnValueTest();
peahd0263542017-01-03 04:20:34 -0800646 }
647}
648
649TEST(EchoCanceller3Messaging, CaptureSaturation) {
650 auto variants = {EchoCanceller3Tester::SaturationTestVariant::kNone,
651 EchoCanceller3Tester::SaturationTestVariant::kOneNegative,
652 EchoCanceller3Tester::SaturationTestVariant::kOnePositive};
653 for (auto rate : {8000, 16000, 32000, 48000}) {
654 for (auto variant : variants) {
655 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
656 EchoCanceller3Tester(rate).RunCaptureSaturationVerificationTest(variant);
657 }
658 }
659}
660
661TEST(EchoCanceller3Messaging, EchoPathChange) {
662 auto variants = {
663 EchoCanceller3Tester::EchoPathChangeTestVariant::kNone,
664 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneSticky,
665 EchoCanceller3Tester::EchoPathChangeTestVariant::kOneNonSticky};
666 for (auto rate : {8000, 16000, 32000, 48000}) {
667 for (auto variant : variants) {
668 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
669 EchoCanceller3Tester(rate).RunEchoPathChangeVerificationTest(variant);
670 }
671 }
672}
673
674TEST(EchoCanceller3Messaging, EchoLeakage) {
675 auto variants = {
676 EchoCanceller3Tester::EchoLeakageTestVariant::kNone,
677 EchoCanceller3Tester::EchoLeakageTestVariant::kFalseSticky,
678 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueSticky,
679 EchoCanceller3Tester::EchoLeakageTestVariant::kTrueNonSticky};
680 for (auto rate : {8000, 16000, 32000, 48000}) {
681 for (auto variant : variants) {
682 SCOPED_TRACE(ProduceDebugText(rate, static_cast<int>(variant)));
683 EchoCanceller3Tester(rate).RunEchoLeakageVerificationTest(variant);
684 }
685 }
686}
687
688#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