1 /*
2  *  Copyright (c) 2017 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/aec3/aec_state.h"
12 
13 #include "modules/audio_processing/logging/apm_data_dumper.h"
14 #include "test/gtest.h"
15 
16 namespace webrtc {
17 
18 // Verify the general functionality of AecState
TEST(AecState,NormalUsage)19 TEST(AecState, NormalUsage) {
20   ApmDataDumper data_dumper(42);
21   AecState state(EchoCanceller3Config{});
22   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
23                              std::vector<size_t>(1, 30));
24   std::array<float, kFftLengthBy2Plus1> E2_main = {};
25   std::array<float, kFftLengthBy2Plus1> Y2 = {};
26   std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
27   EchoPathVariability echo_path_variability(false, false);
28   std::array<float, kBlockSize> s;
29   s.fill(100.f);
30 
31   std::vector<std::array<float, kFftLengthBy2Plus1>>
32       converged_filter_frequency_response(10);
33   for (auto& v : converged_filter_frequency_response) {
34     v.fill(0.01f);
35   }
36   std::vector<std::array<float, kFftLengthBy2Plus1>>
37       diverged_filter_frequency_response = converged_filter_frequency_response;
38   converged_filter_frequency_response[2].fill(100.f);
39   converged_filter_frequency_response[2][0] = 1.f;
40 
41   std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
42   impulse_response.fill(0.f);
43 
44   // Verify that linear AEC usability is false when the filter is diverged and
45   // there is no external delay reported.
46   state.Update(diverged_filter_frequency_response, impulse_response, true,
47                rtc::nullopt, render_buffer, E2_main, Y2, x[0], s, false);
48   EXPECT_FALSE(state.UsableLinearEstimate());
49 
50   // Verify that linear AEC usability is true when the filter is converged
51   std::fill(x[0].begin(), x[0].end(), 101.f);
52   for (int k = 0; k < 3000; ++k) {
53     state.Update(converged_filter_frequency_response, impulse_response, true, 2,
54                  render_buffer, E2_main, Y2, x[0], s, false);
55   }
56   EXPECT_TRUE(state.UsableLinearEstimate());
57 
58   // Verify that linear AEC usability becomes false after an echo path change is
59   // reported
60   state.HandleEchoPathChange(EchoPathVariability(true, false));
61   state.Update(converged_filter_frequency_response, impulse_response, true, 2,
62                render_buffer, E2_main, Y2, x[0], s, false);
63   EXPECT_FALSE(state.UsableLinearEstimate());
64 
65   // Verify that the active render detection works as intended.
66   std::fill(x[0].begin(), x[0].end(), 101.f);
67   state.HandleEchoPathChange(EchoPathVariability(true, true));
68   state.Update(converged_filter_frequency_response, impulse_response, true, 2,
69                render_buffer, E2_main, Y2, x[0], s, false);
70   EXPECT_FALSE(state.ActiveRender());
71 
72   for (int k = 0; k < 1000; ++k) {
73     state.Update(converged_filter_frequency_response, impulse_response, true, 2,
74                  render_buffer, E2_main, Y2, x[0], s, false);
75   }
76   EXPECT_TRUE(state.ActiveRender());
77 
78   // Verify that echo leakage is properly reported.
79   state.Update(converged_filter_frequency_response, impulse_response, true, 2,
80                render_buffer, E2_main, Y2, x[0], s, false);
81   EXPECT_FALSE(state.EchoLeakageDetected());
82 
83   state.Update(converged_filter_frequency_response, impulse_response, true, 2,
84                render_buffer, E2_main, Y2, x[0], s, true);
85   EXPECT_TRUE(state.EchoLeakageDetected());
86 
87   // Verify that the ERL is properly estimated
88   for (auto& x_k : x) {
89     x_k = std::vector<float>(kBlockSize, 0.f);
90   }
91 
92   x[0][0] = 5000.f;
93   for (size_t k = 0; k < render_buffer.Buffer().size(); ++k) {
94     render_buffer.Insert(x);
95   }
96 
97   Y2.fill(10.f * 10000.f * 10000.f);
98   for (size_t k = 0; k < 1000; ++k) {
99     state.Update(converged_filter_frequency_response, impulse_response, true, 2,
100                  render_buffer, E2_main, Y2, x[0], s, false);
101   }
102 
103   ASSERT_TRUE(state.UsableLinearEstimate());
104   const std::array<float, kFftLengthBy2Plus1>& erl = state.Erl();
105   EXPECT_EQ(erl[0], erl[1]);
106   for (size_t k = 1; k < erl.size() - 1; ++k) {
107     EXPECT_NEAR(k % 2 == 0 ? 10.f : 1000.f, erl[k], 0.1);
108   }
109   EXPECT_EQ(erl[erl.size() - 2], erl[erl.size() - 1]);
110 
111   // Verify that the ERLE is properly estimated
112   E2_main.fill(1.f * 10000.f * 10000.f);
113   Y2.fill(10.f * E2_main[0]);
114   for (size_t k = 0; k < 1000; ++k) {
115     state.Update(converged_filter_frequency_response, impulse_response, true, 2,
116                  render_buffer, E2_main, Y2, x[0], s, false);
117   }
118   ASSERT_TRUE(state.UsableLinearEstimate());
119   {
120     const auto& erle = state.Erle();
121     EXPECT_EQ(erle[0], erle[1]);
122     constexpr size_t kLowFrequencyLimit = 32;
123     for (size_t k = 1; k < kLowFrequencyLimit; ++k) {
124       EXPECT_NEAR(k % 2 == 0 ? 8.f : 1.f, erle[k], 0.1);
125     }
126     for (size_t k = kLowFrequencyLimit; k < erle.size() - 1; ++k) {
127       EXPECT_NEAR(k % 2 == 0 ? 1.5f : 1.f, erle[k], 0.1);
128     }
129     EXPECT_EQ(erle[erle.size() - 2], erle[erle.size() - 1]);
130   }
131 
132   E2_main.fill(1.f * 10000.f * 10000.f);
133   Y2.fill(5.f * E2_main[0]);
134   for (size_t k = 0; k < 1000; ++k) {
135     state.Update(converged_filter_frequency_response, impulse_response, true, 2,
136                  render_buffer, E2_main, Y2, x[0], s, false);
137   }
138 
139   ASSERT_TRUE(state.UsableLinearEstimate());
140   {
141     const auto& erle = state.Erle();
142     EXPECT_EQ(erle[0], erle[1]);
143     constexpr size_t kLowFrequencyLimit = 32;
144     for (size_t k = 1; k < kLowFrequencyLimit; ++k) {
145       EXPECT_NEAR(k % 2 == 0 ? 5.f : 1.f, erle[k], 0.1);
146     }
147     for (size_t k = kLowFrequencyLimit; k < erle.size() - 1; ++k) {
148       EXPECT_NEAR(k % 2 == 0 ? 1.5f : 1.f, erle[k], 0.1);
149     }
150     EXPECT_EQ(erle[erle.size() - 2], erle[erle.size() - 1]);
151   }
152 }
153 
154 // Verifies the delay for a converged filter is correctly identified.
TEST(AecState,ConvergedFilterDelay)155 TEST(AecState, ConvergedFilterDelay) {
156   constexpr int kFilterLength = 10;
157   AecState state(EchoCanceller3Config{});
158   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
159                              std::vector<size_t>(1, 30));
160   std::array<float, kFftLengthBy2Plus1> E2_main;
161   std::array<float, kFftLengthBy2Plus1> Y2;
162   std::array<float, kBlockSize> x;
163   EchoPathVariability echo_path_variability(false, false);
164   std::array<float, kBlockSize> s;
165   s.fill(100.f);
166   x.fill(0.f);
167 
168   std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(
169       kFilterLength);
170 
171   std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
172   impulse_response.fill(0.f);
173 
174   // Verify that the filter delay for a converged filter is properly identified.
175   for (int k = 0; k < kFilterLength; ++k) {
176     for (auto& v : frequency_response) {
177       v.fill(0.01f);
178     }
179     frequency_response[k].fill(100.f);
180     frequency_response[k][0] = 0.f;
181     state.HandleEchoPathChange(echo_path_variability);
182     state.Update(frequency_response, impulse_response, true, rtc::nullopt,
183                  render_buffer, E2_main, Y2, x, s, false);
184     EXPECT_TRUE(k == (kFilterLength - 1) || state.FilterDelay());
185     if (k != (kFilterLength - 1)) {
186       EXPECT_EQ(k, state.FilterDelay());
187     }
188   }
189 }
190 
191 // Verify that the externally reported delay is properly reported and converted.
TEST(AecState,ExternalDelay)192 TEST(AecState, ExternalDelay) {
193   AecState state(EchoCanceller3Config{});
194   std::array<float, kFftLengthBy2Plus1> E2_main;
195   std::array<float, kFftLengthBy2Plus1> E2_shadow;
196   std::array<float, kFftLengthBy2Plus1> Y2;
197   std::array<float, kBlockSize> x;
198   std::array<float, kBlockSize> s;
199   s.fill(100.f);
200   E2_main.fill(0.f);
201   E2_shadow.fill(0.f);
202   Y2.fill(0.f);
203   x.fill(0.f);
204   RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
205                              std::vector<size_t>(1, 30));
206   std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(
207       kAdaptiveFilterLength);
208   for (auto& v : frequency_response) {
209     v.fill(0.01f);
210   }
211 
212   std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
213   impulse_response.fill(0.f);
214 
215   for (size_t k = 0; k < frequency_response.size() - 1; ++k) {
216     state.HandleEchoPathChange(EchoPathVariability(false, false));
217     state.Update(frequency_response, impulse_response, true, k * kBlockSize + 5,
218                  render_buffer, E2_main, Y2, x, s, false);
219     EXPECT_TRUE(state.ExternalDelay());
220     EXPECT_EQ(k, state.ExternalDelay());
221   }
222 
223   // Verify that the externally reported delay is properly unset when it is no
224   // longer present.
225   state.HandleEchoPathChange(EchoPathVariability(false, false));
226   state.Update(frequency_response, impulse_response, true, rtc::nullopt,
227                render_buffer, E2_main, Y2, x, s, false);
228   EXPECT_FALSE(state.ExternalDelay());
229 }
230 
231 }  // namespace webrtc
232