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