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