Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(621)

Side by Side Diff: webrtc/modules/audio_processing/aec3/aec_state_unittest.cc

Issue 2678423005: Finalization of the first version of EchoCanceller 3 (Closed)
Patch Set: Fixed compilation error Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "webrtc/modules/audio_processing/aec3/aec_state.h"
12
13 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
14 #include "webrtc/test/gtest.h"
15
16 namespace webrtc {
17
18 // Verify the general functionality of AecState
19 TEST(AecState, NormalUsage) {
20 ApmDataDumper data_dumper(42);
21 AecState state;
22 FftBuffer X_buffer(Aec3Optimization::kNone, 30, std::vector<size_t>(1, 30));
23 std::array<float, kFftLengthBy2Plus1> E2_main;
24 std::array<float, kFftLengthBy2Plus1> E2_shadow;
25 std::array<float, kFftLengthBy2Plus1> Y2;
26 std::array<float, kBlockSize> x;
27 EchoPathVariability echo_path_variability(false, false);
28 x.fill(0.f);
29
30 std::vector<std::array<float, kFftLengthBy2Plus1>>
31 converged_filter_frequency_response(10);
32 for (auto& v : converged_filter_frequency_response) {
33 v.fill(0.01f);
34 }
35 std::vector<std::array<float, kFftLengthBy2Plus1>>
36 diverged_filter_frequency_response = converged_filter_frequency_response;
37 converged_filter_frequency_response[2].fill(100.f);
38
39 // Verify that model based aec feasibility and linear AEC usability are false
40 // when the filter is diverged and there is no external delay reported.
41 state.Update(diverged_filter_frequency_response, rtc::Optional<size_t>(),
42 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
43 false);
44 EXPECT_FALSE(state.ModelBasedAecFeasible());
45 EXPECT_FALSE(state.UsableLinearEstimate());
46
47 // Verify that model based aec feasibility is true and that linear AEC
48 // usability is false when the filter is diverged and there is an external
49 // delay reported.
50 state.Update(diverged_filter_frequency_response, rtc::Optional<size_t>(),
51 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
52 false);
53 EXPECT_FALSE(state.ModelBasedAecFeasible());
54 for (int k = 0; k < 50; ++k) {
55 state.Update(diverged_filter_frequency_response, rtc::Optional<size_t>(2),
56 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
57 false);
58 }
59 EXPECT_TRUE(state.ModelBasedAecFeasible());
60 EXPECT_FALSE(state.UsableLinearEstimate());
61
62 // Verify that linear AEC usability is true when the filter is converged
63 for (int k = 0; k < 50; ++k) {
64 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
65 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
66 false);
67 }
68 EXPECT_TRUE(state.UsableLinearEstimate());
69
70 // Verify that linear AEC usability becomes false after an echo path change is
71 // reported
72 echo_path_variability = EchoPathVariability(true, false);
73 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
74 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
75 false);
76 EXPECT_FALSE(state.UsableLinearEstimate());
77
78 // Verify that the active render detection works as intended.
79 x.fill(101.f);
80 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
81 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
82 false);
83 EXPECT_TRUE(state.ActiveRender());
84
85 x.fill(0.f);
86 for (int k = 0; k < 200; ++k) {
87 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
88 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
89 false);
90 }
91 EXPECT_FALSE(state.ActiveRender());
92
93 x.fill(101.f);
94 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
95 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
96 false);
97 EXPECT_TRUE(state.ActiveRender());
98
99 // Verify that echo leakage is properly reported.
100 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
101 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
102 false);
103 EXPECT_FALSE(state.EchoLeakageDetected());
104
105 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
106 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
107 true);
108 EXPECT_TRUE(state.EchoLeakageDetected());
109
110 // Verify that the bands containing reliable filter estimates are properly
111 // reported.
112 echo_path_variability = EchoPathVariability(false, false);
113 for (int k = 0; k < 200; ++k) {
114 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
115 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
116 false);
117 }
118
119 FftData X;
120 X.re.fill(10000.f);
121 X.im.fill(0.f);
122 for (size_t k = 0; k < X_buffer.Buffer().size(); ++k) {
123 X_buffer.Insert(X);
124 }
125
126 Y2.fill(10.f * 1000.f * 1000.f);
127 E2_main.fill(100.f * Y2[0]);
128 E2_shadow.fill(100.f * Y2[0]);
129 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
130 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
131 false);
132
133 E2_main.fill(0.1f * Y2[0]);
134 E2_shadow.fill(E2_main[0]);
135 for (size_t k = 0; k < Y2.size(); k += 2) {
136 E2_main[k] = Y2[k];
137 E2_shadow[k] = Y2[k];
138 }
139 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
140 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
141 false);
142
143 const std::array<bool, kFftLengthBy2Plus1>& reliable_bands =
144 state.BandsWithReliableFilter();
145
146 EXPECT_EQ(reliable_bands[0], reliable_bands[1]);
147 for (size_t k = 1; k < kFftLengthBy2 - 5; ++k) {
148 EXPECT_TRUE(reliable_bands[k]);
149 }
150 for (size_t k = kFftLengthBy2 - 5; k < reliable_bands.size(); ++k) {
151 EXPECT_EQ(reliable_bands[kFftLengthBy2 - 6], reliable_bands[k]);
152 }
153
154 // Verify that the ERL is properly estimated
155 Y2.fill(10.f * X.re[0] * X.re[0]);
156 for (size_t k = 0; k < 100000; ++k) {
157 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
158 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
159 false);
160 }
161
162 ASSERT_TRUE(state.UsableLinearEstimate());
163 const std::array<float, kFftLengthBy2Plus1>& erl = state.Erl();
164 std::for_each(erl.begin(), erl.end(),
165 [](float a) { EXPECT_NEAR(10.f, a, 0.1); });
166
167 // Verify that the ERLE is properly estimated
168 E2_main.fill(1.f * X.re[0] * X.re[0]);
169 Y2.fill(10.f * E2_main[0]);
170 for (size_t k = 0; k < 10000; ++k) {
171 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
172 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
173 false);
174 }
175 ASSERT_TRUE(state.UsableLinearEstimate());
176 std::for_each(state.Erle().begin(), state.Erle().end(),
177 [](float a) { EXPECT_NEAR(8.f, a, 0.1); });
178
179 E2_main.fill(1.f * X.re[0] * X.re[0]);
180 Y2.fill(5.f * E2_main[0]);
181 for (size_t k = 0; k < 10000; ++k) {
182 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2),
183 X_buffer, E2_main, E2_shadow, Y2, x, echo_path_variability,
184 false);
185 }
186 ASSERT_TRUE(state.UsableLinearEstimate());
187 std::for_each(state.Erle().begin(), state.Erle().end(),
188 [](float a) { EXPECT_NEAR(5.f, a, 0.1); });
189 }
190
191 // Verifies the a non-significant delay is correctly identified.
192 TEST(AecState, NonSignificantDelay) {
193 AecState state;
194 FftBuffer X_buffer(Aec3Optimization::kNone, 30, std::vector<size_t>(1, 30));
195 std::array<float, kFftLengthBy2Plus1> E2_main;
196 std::array<float, kFftLengthBy2Plus1> E2_shadow;
197 std::array<float, kFftLengthBy2Plus1> Y2;
198 std::array<float, kBlockSize> x;
199 EchoPathVariability echo_path_variability(false, false);
200 x.fill(0.f);
201
202 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(30);
203 for (auto& v : frequency_response) {
204 v.fill(0.01f);
205 }
206
207 // Verify that a non-significant filter delay is identified correctly.
208 state.Update(frequency_response, rtc::Optional<size_t>(), X_buffer, E2_main,
209 E2_shadow, Y2, x, echo_path_variability, false);
210 EXPECT_FALSE(state.FilterDelay());
211 }
212
213 // Verifies the delay for a converged filter is correctly identified.
214 TEST(AecState, ConvergedFilterDelay) {
215 constexpr int kFilterLength = 10;
216 AecState state;
217 FftBuffer X_buffer(Aec3Optimization::kNone, 30, std::vector<size_t>(1, 30));
218 std::array<float, kFftLengthBy2Plus1> E2_main;
219 std::array<float, kFftLengthBy2Plus1> E2_shadow;
220 std::array<float, kFftLengthBy2Plus1> Y2;
221 std::array<float, kBlockSize> x;
222 EchoPathVariability echo_path_variability(false, false);
223 x.fill(0.f);
224
225 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(
226 kFilterLength);
227
228 // Verify that the filter delay for a converged filter is properly identified.
229 for (int k = 0; k < kFilterLength; ++k) {
230 for (auto& v : frequency_response) {
231 v.fill(0.01f);
232 }
233 frequency_response[k].fill(100.f);
234
235 state.Update(frequency_response, rtc::Optional<size_t>(), X_buffer, E2_main,
236 E2_shadow, Y2, x, echo_path_variability, false);
237 EXPECT_TRUE(k == (kFilterLength - 1) || state.FilterDelay());
238 if (k != (kFilterLength - 1)) {
239 EXPECT_EQ(k, state.FilterDelay());
240 }
241 }
242 }
243
244 // Verify that the externally reported delay is properly reported and converted.
245 TEST(AecState, ExternalDelay) {
246 AecState state;
247 std::array<float, kFftLengthBy2Plus1> E2_main;
248 std::array<float, kFftLengthBy2Plus1> E2_shadow;
249 std::array<float, kFftLengthBy2Plus1> Y2;
250 std::array<float, kBlockSize> x;
251 E2_main.fill(0.f);
252 E2_shadow.fill(0.f);
253 Y2.fill(0.f);
254 x.fill(0.f);
255 FftBuffer X_buffer(Aec3Optimization::kNone, 30, std::vector<size_t>(1, 30));
256 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(30);
257 for (auto& v : frequency_response) {
258 v.fill(0.01f);
259 }
260
261 for (size_t k = 0; k < frequency_response.size() - 1; ++k) {
262 state.Update(frequency_response, rtc::Optional<size_t>(k * kBlockSize + 5),
263 X_buffer, E2_main, E2_shadow, Y2, x,
264 EchoPathVariability(false, false), false);
265 EXPECT_TRUE(state.ExternalDelay());
266 EXPECT_EQ(k, state.ExternalDelay());
267 }
268
269 // Verify that the externally reported delay is properly unset when it is no
270 // longer present.
271 state.Update(frequency_response, rtc::Optional<size_t>(), X_buffer, E2_main,
272 E2_shadow, Y2, x, EchoPathVariability(false, false), false);
273 EXPECT_FALSE(state.ExternalDelay());
274 }
275
276 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698