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 "modules/audio_processing/residual_echo_detector.h"
12
13 #include <vector>
14
15 #include "rtc_base/ref_counted_object.h"
16 #include "test/gtest.h"
17
18 namespace webrtc {
19
TEST(ResidualEchoDetectorTests,Echo)20 TEST(ResidualEchoDetectorTests, Echo) {
21 rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
22 new rtc::RefCountedObject<ResidualEchoDetector>();
23 echo_detector->SetReliabilityForTest(1.0f);
24 std::vector<float> ones(160, 1.f);
25 std::vector<float> zeros(160, 0.f);
26
27 // In this test the capture signal has a delay of 10 frames w.r.t. the render
28 // signal, but is otherwise identical. Both signals are periodic with a 20
29 // frame interval.
30 for (int i = 0; i < 1000; i++) {
31 if (i % 20 == 0) {
32 echo_detector->AnalyzeRenderAudio(ones);
33 echo_detector->AnalyzeCaptureAudio(zeros);
34 } else if (i % 20 == 10) {
35 echo_detector->AnalyzeRenderAudio(zeros);
36 echo_detector->AnalyzeCaptureAudio(ones);
37 } else {
38 echo_detector->AnalyzeRenderAudio(zeros);
39 echo_detector->AnalyzeCaptureAudio(zeros);
40 }
41 }
42 // We expect to detect echo with near certain likelihood.
43 auto ed_metrics = echo_detector->GetMetrics();
44 ASSERT_TRUE(ed_metrics.echo_likelihood);
45 EXPECT_NEAR(1.f, ed_metrics.echo_likelihood.value(), 0.01f);
46 }
47
TEST(ResidualEchoDetectorTests,NoEcho)48 TEST(ResidualEchoDetectorTests, NoEcho) {
49 rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
50 new rtc::RefCountedObject<ResidualEchoDetector>();
51 echo_detector->SetReliabilityForTest(1.0f);
52 std::vector<float> ones(160, 1.f);
53 std::vector<float> zeros(160, 0.f);
54
55 // In this test the capture signal is always zero, so no echo should be
56 // detected.
57 for (int i = 0; i < 1000; i++) {
58 if (i % 20 == 0) {
59 echo_detector->AnalyzeRenderAudio(ones);
60 } else {
61 echo_detector->AnalyzeRenderAudio(zeros);
62 }
63 echo_detector->AnalyzeCaptureAudio(zeros);
64 }
65 // We expect to not detect any echo.
66 auto ed_metrics = echo_detector->GetMetrics();
67 ASSERT_TRUE(ed_metrics.echo_likelihood);
68 EXPECT_NEAR(0.f, ed_metrics.echo_likelihood.value(), 0.01f);
69 }
70
TEST(ResidualEchoDetectorTests,EchoWithRenderClockDrift)71 TEST(ResidualEchoDetectorTests, EchoWithRenderClockDrift) {
72 rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
73 new rtc::RefCountedObject<ResidualEchoDetector>();
74 echo_detector->SetReliabilityForTest(1.0f);
75 std::vector<float> ones(160, 1.f);
76 std::vector<float> zeros(160, 0.f);
77
78 // In this test the capture signal has a delay of 10 frames w.r.t. the render
79 // signal, but is otherwise identical. Both signals are periodic with a 20
80 // frame interval. There is a simulated clock drift of 1% in this test, with
81 // the render side producing data slightly faster.
82 for (int i = 0; i < 1000; i++) {
83 if (i % 20 == 0) {
84 echo_detector->AnalyzeRenderAudio(ones);
85 echo_detector->AnalyzeCaptureAudio(zeros);
86 } else if (i % 20 == 10) {
87 echo_detector->AnalyzeRenderAudio(zeros);
88 echo_detector->AnalyzeCaptureAudio(ones);
89 } else {
90 echo_detector->AnalyzeRenderAudio(zeros);
91 echo_detector->AnalyzeCaptureAudio(zeros);
92 }
93 if (i % 100 == 0) {
94 // This is causing the simulated clock drift.
95 echo_detector->AnalyzeRenderAudio(zeros);
96 }
97 }
98 // We expect to detect echo with high likelihood. Clock drift is harder to
99 // correct on the render side than on the capture side. This is due to the
100 // render buffer, clock drift can only be discovered after a certain delay.
101 // A growing buffer can be caused by jitter or clock drift and it's not
102 // possible to make this decision right away. For this reason we only expect
103 // an echo likelihood of 75% in this test.
104 auto ed_metrics = echo_detector->GetMetrics();
105 ASSERT_TRUE(ed_metrics.echo_likelihood);
106 EXPECT_GT(ed_metrics.echo_likelihood.value(), 0.75f);
107 }
108
TEST(ResidualEchoDetectorTests,EchoWithCaptureClockDrift)109 TEST(ResidualEchoDetectorTests, EchoWithCaptureClockDrift) {
110 rtc::scoped_refptr<ResidualEchoDetector> echo_detector =
111 new rtc::RefCountedObject<ResidualEchoDetector>();
112 echo_detector->SetReliabilityForTest(1.0f);
113 std::vector<float> ones(160, 1.f);
114 std::vector<float> zeros(160, 0.f);
115
116 // In this test the capture signal has a delay of 10 frames w.r.t. the render
117 // signal, but is otherwise identical. Both signals are periodic with a 20
118 // frame interval. There is a simulated clock drift of 1% in this test, with
119 // the capture side producing data slightly faster.
120 for (int i = 0; i < 1000; i++) {
121 if (i % 20 == 0) {
122 echo_detector->AnalyzeRenderAudio(ones);
123 echo_detector->AnalyzeCaptureAudio(zeros);
124 } else if (i % 20 == 10) {
125 echo_detector->AnalyzeRenderAudio(zeros);
126 echo_detector->AnalyzeCaptureAudio(ones);
127 } else {
128 echo_detector->AnalyzeRenderAudio(zeros);
129 echo_detector->AnalyzeCaptureAudio(zeros);
130 }
131 if (i % 100 == 0) {
132 // This is causing the simulated clock drift.
133 echo_detector->AnalyzeCaptureAudio(zeros);
134 }
135 }
136 // We expect to detect echo with near certain likelihood.
137 auto ed_metrics = echo_detector->GetMetrics();
138 ASSERT_TRUE(ed_metrics.echo_likelihood);
139 EXPECT_NEAR(1.f, ed_metrics.echo_likelihood.value(), 0.01f);
140 }
141
142 } // namespace webrtc
143