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

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

Issue 2974583004: Transparency improvements in the echo canceller 3 (Closed)
Patch Set: Corrected wrong echo estimate vector in unittest Created 3 years, 5 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
1 /* 1 /*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/modules/audio_processing/aec3/aec_state.h" 11 #include "webrtc/modules/audio_processing/aec3/aec_state.h"
12 12
13 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" 13 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
14 #include "webrtc/test/gtest.h" 14 #include "webrtc/test/gtest.h"
15 15
16 namespace webrtc { 16 namespace webrtc {
17 17
18 // Verify the general functionality of AecState 18 // Verify the general functionality of AecState
19 TEST(AecState, NormalUsage) { 19 TEST(AecState, NormalUsage) {
20 ApmDataDumper data_dumper(42); 20 ApmDataDumper data_dumper(42);
21 AecState state(0.f); 21 AecState state(0.f);
22 RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, 22 RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
23 std::vector<size_t>(1, 30)); 23 std::vector<size_t>(1, 30));
24 std::array<float, kFftLengthBy2Plus1> E2_main = {}; 24 std::array<float, kFftLengthBy2Plus1> E2_main = {};
25 std::array<float, kFftLengthBy2Plus1> Y2 = {}; 25 std::array<float, kFftLengthBy2Plus1> Y2 = {};
26 std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f)); 26 std::vector<std::vector<float>> x(3, std::vector<float>(kBlockSize, 0.f));
27 EchoPathVariability echo_path_variability(false, false); 27 EchoPathVariability echo_path_variability(false, false);
28 std::array<float, kBlockSize> s;
29 s.fill(100.f);
28 30
29 std::vector<std::array<float, kFftLengthBy2Plus1>> 31 std::vector<std::array<float, kFftLengthBy2Plus1>>
30 converged_filter_frequency_response(10); 32 converged_filter_frequency_response(10);
31 for (auto& v : converged_filter_frequency_response) { 33 for (auto& v : converged_filter_frequency_response) {
32 v.fill(0.01f); 34 v.fill(0.01f);
33 } 35 }
34 std::vector<std::array<float, kFftLengthBy2Plus1>> 36 std::vector<std::array<float, kFftLengthBy2Plus1>>
35 diverged_filter_frequency_response = converged_filter_frequency_response; 37 diverged_filter_frequency_response = converged_filter_frequency_response;
36 converged_filter_frequency_response[2].fill(100.f); 38 converged_filter_frequency_response[2].fill(100.f);
37 converged_filter_frequency_response[2][0] = 1.f; 39 converged_filter_frequency_response[2][0] = 1.f;
38 40
41 std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
42 impulse_response.fill(0.f);
43
39 // Verify that linear AEC usability is false when the filter is diverged and 44 // Verify that linear AEC usability is false when the filter is diverged and
40 // there is no external delay reported. 45 // there is no external delay reported.
41 state.Update(diverged_filter_frequency_response, rtc::Optional<size_t>(), 46 state.Update(diverged_filter_frequency_response, impulse_response,
42 render_buffer, E2_main, Y2, x[0], false); 47 rtc::Optional<size_t>(), render_buffer, E2_main, Y2, x[0], s,
48 false);
43 EXPECT_FALSE(state.UsableLinearEstimate()); 49 EXPECT_FALSE(state.UsableLinearEstimate());
44 50
45 // Verify that linear AEC usability is true when the filter is converged 51 // Verify that linear AEC usability is true when the filter is converged
46 std::fill(x[0].begin(), x[0].end(), 101.f); 52 std::fill(x[0].begin(), x[0].end(), 101.f);
47 for (int k = 0; k < 3000; ++k) { 53 for (int k = 0; k < 3000; ++k) {
48 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 54 state.Update(converged_filter_frequency_response, impulse_response,
49 render_buffer, E2_main, Y2, x[0], false); 55 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
56 false);
50 } 57 }
51 EXPECT_TRUE(state.UsableLinearEstimate()); 58 EXPECT_TRUE(state.UsableLinearEstimate());
52 59
53 // Verify that linear AEC usability becomes false after an echo path change is 60 // Verify that linear AEC usability becomes false after an echo path change is
54 // reported 61 // reported
55 state.HandleEchoPathChange(EchoPathVariability(true, false)); 62 state.HandleEchoPathChange(EchoPathVariability(true, false));
56 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 63 state.Update(converged_filter_frequency_response, impulse_response,
57 render_buffer, E2_main, Y2, x[0], false); 64 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
65 false);
58 EXPECT_FALSE(state.UsableLinearEstimate()); 66 EXPECT_FALSE(state.UsableLinearEstimate());
59 67
60 // Verify that the active render detection works as intended. 68 // Verify that the active render detection works as intended.
61 std::fill(x[0].begin(), x[0].end(), 101.f); 69 std::fill(x[0].begin(), x[0].end(), 101.f);
62 state.HandleEchoPathChange(EchoPathVariability(true, true)); 70 state.HandleEchoPathChange(EchoPathVariability(true, true));
63 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 71 state.Update(converged_filter_frequency_response, impulse_response,
64 render_buffer, E2_main, Y2, x[0], false); 72 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
73 false);
65 EXPECT_FALSE(state.ActiveRender()); 74 EXPECT_FALSE(state.ActiveRender());
66 75
67 for (int k = 0; k < 1000; ++k) { 76 for (int k = 0; k < 1000; ++k) {
68 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 77 state.Update(converged_filter_frequency_response, impulse_response,
69 render_buffer, E2_main, Y2, x[0], false); 78 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
79 false);
70 } 80 }
71 EXPECT_TRUE(state.ActiveRender()); 81 EXPECT_TRUE(state.ActiveRender());
72 82
73 // Verify that echo leakage is properly reported. 83 // Verify that echo leakage is properly reported.
74 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 84 state.Update(converged_filter_frequency_response, impulse_response,
75 render_buffer, E2_main, Y2, x[0], false); 85 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
86 false);
76 EXPECT_FALSE(state.EchoLeakageDetected()); 87 EXPECT_FALSE(state.EchoLeakageDetected());
77 88
78 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 89 state.Update(converged_filter_frequency_response, impulse_response,
79 render_buffer, E2_main, Y2, x[0], true); 90 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
91 true);
80 EXPECT_TRUE(state.EchoLeakageDetected()); 92 EXPECT_TRUE(state.EchoLeakageDetected());
81 93
82 // Verify that the ERL is properly estimated 94 // Verify that the ERL is properly estimated
83 for (auto& x_k : x) { 95 for (auto& x_k : x) {
84 x_k = std::vector<float>(kBlockSize, 0.f); 96 x_k = std::vector<float>(kBlockSize, 0.f);
85 } 97 }
86 98
87 x[0][0] = 5000.f; 99 x[0][0] = 5000.f;
88 for (size_t k = 0; k < render_buffer.Buffer().size(); ++k) { 100 for (size_t k = 0; k < render_buffer.Buffer().size(); ++k) {
89 render_buffer.Insert(x); 101 render_buffer.Insert(x);
90 } 102 }
91 103
92 Y2.fill(10.f * 10000.f * 10000.f); 104 Y2.fill(10.f * 10000.f * 10000.f);
93 for (size_t k = 0; k < 1000; ++k) { 105 for (size_t k = 0; k < 1000; ++k) {
94 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 106 state.Update(converged_filter_frequency_response, impulse_response,
95 render_buffer, E2_main, Y2, x[0], false); 107 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
108 false);
96 } 109 }
97 110
98 ASSERT_TRUE(state.UsableLinearEstimate()); 111 ASSERT_TRUE(state.UsableLinearEstimate());
99 const std::array<float, kFftLengthBy2Plus1>& erl = state.Erl(); 112 const std::array<float, kFftLengthBy2Plus1>& erl = state.Erl();
100 EXPECT_EQ(erl[0], erl[1]); 113 EXPECT_EQ(erl[0], erl[1]);
101 for (size_t k = 1; k < erl.size() - 1; ++k) { 114 for (size_t k = 1; k < erl.size() - 1; ++k) {
102 EXPECT_NEAR(k % 2 == 0 ? 10.f : 1000.f, erl[k], 0.1); 115 EXPECT_NEAR(k % 2 == 0 ? 10.f : 1000.f, erl[k], 0.1);
103 } 116 }
104 EXPECT_EQ(erl[erl.size() - 2], erl[erl.size() - 1]); 117 EXPECT_EQ(erl[erl.size() - 2], erl[erl.size() - 1]);
105 118
106 // Verify that the ERLE is properly estimated 119 // Verify that the ERLE is properly estimated
107 E2_main.fill(1.f * 10000.f * 10000.f); 120 E2_main.fill(1.f * 10000.f * 10000.f);
108 Y2.fill(10.f * E2_main[0]); 121 Y2.fill(10.f * E2_main[0]);
109 for (size_t k = 0; k < 1000; ++k) { 122 for (size_t k = 0; k < 1000; ++k) {
110 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 123 state.Update(converged_filter_frequency_response, impulse_response,
111 render_buffer, E2_main, Y2, x[0], false); 124 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
125 false);
112 } 126 }
113 ASSERT_TRUE(state.UsableLinearEstimate()); 127 ASSERT_TRUE(state.UsableLinearEstimate());
114 { 128 {
115 const auto& erle = state.Erle(); 129 const auto& erle = state.Erle();
116 EXPECT_EQ(erle[0], erle[1]); 130 EXPECT_EQ(erle[0], erle[1]);
117 constexpr size_t kLowFrequencyLimit = 32; 131 constexpr size_t kLowFrequencyLimit = 32;
118 for (size_t k = 1; k < kLowFrequencyLimit; ++k) { 132 for (size_t k = 1; k < kLowFrequencyLimit; ++k) {
119 EXPECT_NEAR(k % 2 == 0 ? 8.f : 1.f, erle[k], 0.1); 133 EXPECT_NEAR(k % 2 == 0 ? 8.f : 1.f, erle[k], 0.1);
120 } 134 }
121 for (size_t k = kLowFrequencyLimit; k < erle.size() - 1; ++k) { 135 for (size_t k = kLowFrequencyLimit; k < erle.size() - 1; ++k) {
122 EXPECT_NEAR(k % 2 == 0 ? 1.5f : 1.f, erle[k], 0.1); 136 EXPECT_NEAR(k % 2 == 0 ? 1.5f : 1.f, erle[k], 0.1);
123 } 137 }
124 EXPECT_EQ(erle[erle.size() - 2], erle[erle.size() - 1]); 138 EXPECT_EQ(erle[erle.size() - 2], erle[erle.size() - 1]);
125 } 139 }
126 140
127 E2_main.fill(1.f * 10000.f * 10000.f); 141 E2_main.fill(1.f * 10000.f * 10000.f);
128 Y2.fill(5.f * E2_main[0]); 142 Y2.fill(5.f * E2_main[0]);
129 for (size_t k = 0; k < 1000; ++k) { 143 for (size_t k = 0; k < 1000; ++k) {
130 state.Update(converged_filter_frequency_response, rtc::Optional<size_t>(2), 144 state.Update(converged_filter_frequency_response, impulse_response,
131 render_buffer, E2_main, Y2, x[0], false); 145 rtc::Optional<size_t>(2), render_buffer, E2_main, Y2, x[0], s,
146 false);
132 } 147 }
133 148
134 ASSERT_TRUE(state.UsableLinearEstimate()); 149 ASSERT_TRUE(state.UsableLinearEstimate());
135 { 150 {
136 const auto& erle = state.Erle(); 151 const auto& erle = state.Erle();
137 EXPECT_EQ(erle[0], erle[1]); 152 EXPECT_EQ(erle[0], erle[1]);
138 constexpr size_t kLowFrequencyLimit = 32; 153 constexpr size_t kLowFrequencyLimit = 32;
139 for (size_t k = 1; k < kLowFrequencyLimit; ++k) { 154 for (size_t k = 1; k < kLowFrequencyLimit; ++k) {
140 EXPECT_NEAR(k % 2 == 0 ? 5.f : 1.f, erle[k], 0.1); 155 EXPECT_NEAR(k % 2 == 0 ? 5.f : 1.f, erle[k], 0.1);
141 } 156 }
142 for (size_t k = kLowFrequencyLimit; k < erle.size() - 1; ++k) { 157 for (size_t k = kLowFrequencyLimit; k < erle.size() - 1; ++k) {
143 EXPECT_NEAR(k % 2 == 0 ? 1.5f : 1.f, erle[k], 0.1); 158 EXPECT_NEAR(k % 2 == 0 ? 1.5f : 1.f, erle[k], 0.1);
144 } 159 }
145 EXPECT_EQ(erle[erle.size() - 2], erle[erle.size() - 1]); 160 EXPECT_EQ(erle[erle.size() - 2], erle[erle.size() - 1]);
146 } 161 }
147 } 162 }
148 163
149 // Verifies the a non-significant delay is correctly identified. 164 // Verifies the a non-significant delay is correctly identified.
150 TEST(AecState, NonSignificantDelay) { 165 TEST(AecState, NonSignificantDelay) {
151 AecState state(0.f); 166 AecState state(0.f);
152 RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, 167 RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
153 std::vector<size_t>(1, 30)); 168 std::vector<size_t>(1, 30));
154 std::array<float, kFftLengthBy2Plus1> E2_main; 169 std::array<float, kFftLengthBy2Plus1> E2_main;
155 std::array<float, kFftLengthBy2Plus1> Y2; 170 std::array<float, kFftLengthBy2Plus1> Y2;
156 std::array<float, kBlockSize> x; 171 std::array<float, kBlockSize> x;
157 EchoPathVariability echo_path_variability(false, false); 172 EchoPathVariability echo_path_variability(false, false);
173 std::array<float, kBlockSize> s;
174 s.fill(100.f);
158 x.fill(0.f); 175 x.fill(0.f);
159 176
160 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(30); 177 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(30);
161 for (auto& v : frequency_response) { 178 for (auto& v : frequency_response) {
162 v.fill(0.01f); 179 v.fill(0.01f);
163 } 180 }
164 181
182 std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
183 impulse_response.fill(0.f);
184
165 // Verify that a non-significant filter delay is identified correctly. 185 // Verify that a non-significant filter delay is identified correctly.
166 state.HandleEchoPathChange(echo_path_variability); 186 state.HandleEchoPathChange(echo_path_variability);
167 state.Update(frequency_response, rtc::Optional<size_t>(), render_buffer, 187 state.Update(frequency_response, impulse_response, rtc::Optional<size_t>(),
168 E2_main, Y2, x, false); 188 render_buffer, E2_main, Y2, x, s, false);
169 EXPECT_FALSE(state.FilterDelay()); 189 EXPECT_FALSE(state.FilterDelay());
170 } 190 }
171 191
172 // Verifies the delay for a converged filter is correctly identified. 192 // Verifies the delay for a converged filter is correctly identified.
173 TEST(AecState, ConvergedFilterDelay) { 193 TEST(AecState, ConvergedFilterDelay) {
174 constexpr int kFilterLength = 10; 194 constexpr int kFilterLength = 10;
175 AecState state(0.f); 195 AecState state(0.f);
176 RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, 196 RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
177 std::vector<size_t>(1, 30)); 197 std::vector<size_t>(1, 30));
178 std::array<float, kFftLengthBy2Plus1> E2_main; 198 std::array<float, kFftLengthBy2Plus1> E2_main;
179 std::array<float, kFftLengthBy2Plus1> Y2; 199 std::array<float, kFftLengthBy2Plus1> Y2;
180 std::array<float, kBlockSize> x; 200 std::array<float, kBlockSize> x;
181 EchoPathVariability echo_path_variability(false, false); 201 EchoPathVariability echo_path_variability(false, false);
202 std::array<float, kBlockSize> s;
203 s.fill(100.f);
182 x.fill(0.f); 204 x.fill(0.f);
183 205
184 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response( 206 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(
185 kFilterLength); 207 kFilterLength);
186 208
209 std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
210 impulse_response.fill(0.f);
211
187 // Verify that the filter delay for a converged filter is properly identified. 212 // Verify that the filter delay for a converged filter is properly identified.
188 for (int k = 0; k < kFilterLength; ++k) { 213 for (int k = 0; k < kFilterLength; ++k) {
189 for (auto& v : frequency_response) { 214 for (auto& v : frequency_response) {
190 v.fill(0.01f); 215 v.fill(0.01f);
191 } 216 }
192 frequency_response[k].fill(100.f); 217 frequency_response[k].fill(100.f);
193 frequency_response[k][0] = 0.f; 218 frequency_response[k][0] = 0.f;
194 state.HandleEchoPathChange(echo_path_variability); 219 state.HandleEchoPathChange(echo_path_variability);
195 state.Update(frequency_response, rtc::Optional<size_t>(), render_buffer, 220 state.Update(frequency_response, impulse_response, rtc::Optional<size_t>(),
196 E2_main, Y2, x, false); 221 render_buffer, E2_main, Y2, x, s, false);
197 EXPECT_TRUE(k == (kFilterLength - 1) || state.FilterDelay()); 222 EXPECT_TRUE(k == (kFilterLength - 1) || state.FilterDelay());
198 if (k != (kFilterLength - 1)) { 223 if (k != (kFilterLength - 1)) {
199 EXPECT_EQ(k, state.FilterDelay()); 224 EXPECT_EQ(k, state.FilterDelay());
200 } 225 }
201 } 226 }
202 } 227 }
203 228
204 // Verify that the externally reported delay is properly reported and converted. 229 // Verify that the externally reported delay is properly reported and converted.
205 TEST(AecState, ExternalDelay) { 230 TEST(AecState, ExternalDelay) {
206 AecState state(0.f); 231 AecState state(0.f);
207 std::array<float, kFftLengthBy2Plus1> E2_main; 232 std::array<float, kFftLengthBy2Plus1> E2_main;
208 std::array<float, kFftLengthBy2Plus1> E2_shadow; 233 std::array<float, kFftLengthBy2Plus1> E2_shadow;
209 std::array<float, kFftLengthBy2Plus1> Y2; 234 std::array<float, kFftLengthBy2Plus1> Y2;
210 std::array<float, kBlockSize> x; 235 std::array<float, kBlockSize> x;
236 std::array<float, kBlockSize> s;
237 s.fill(100.f);
211 E2_main.fill(0.f); 238 E2_main.fill(0.f);
212 E2_shadow.fill(0.f); 239 E2_shadow.fill(0.f);
213 Y2.fill(0.f); 240 Y2.fill(0.f);
214 x.fill(0.f); 241 x.fill(0.f);
215 RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30, 242 RenderBuffer render_buffer(Aec3Optimization::kNone, 3, 30,
216 std::vector<size_t>(1, 30)); 243 std::vector<size_t>(1, 30));
217 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(30); 244 std::vector<std::array<float, kFftLengthBy2Plus1>> frequency_response(30);
218 for (auto& v : frequency_response) { 245 for (auto& v : frequency_response) {
219 v.fill(0.01f); 246 v.fill(0.01f);
220 } 247 }
221 248
249 std::array<float, kAdaptiveFilterTimeDomainLength> impulse_response;
250 impulse_response.fill(0.f);
251
222 for (size_t k = 0; k < frequency_response.size() - 1; ++k) { 252 for (size_t k = 0; k < frequency_response.size() - 1; ++k) {
223 state.HandleEchoPathChange(EchoPathVariability(false, false)); 253 state.HandleEchoPathChange(EchoPathVariability(false, false));
224 state.Update(frequency_response, rtc::Optional<size_t>(k * kBlockSize + 5), 254 state.Update(frequency_response, impulse_response,
225 render_buffer, E2_main, Y2, x, false); 255 rtc::Optional<size_t>(k * kBlockSize + 5), render_buffer,
256 E2_main, Y2, x, s, false);
226 EXPECT_TRUE(state.ExternalDelay()); 257 EXPECT_TRUE(state.ExternalDelay());
227 EXPECT_EQ(k, state.ExternalDelay()); 258 EXPECT_EQ(k, state.ExternalDelay());
228 } 259 }
229 260
230 // Verify that the externally reported delay is properly unset when it is no 261 // Verify that the externally reported delay is properly unset when it is no
231 // longer present. 262 // longer present.
232 state.HandleEchoPathChange(EchoPathVariability(false, false)); 263 state.HandleEchoPathChange(EchoPathVariability(false, false));
233 state.Update(frequency_response, rtc::Optional<size_t>(), render_buffer, 264 state.Update(frequency_response, impulse_response, rtc::Optional<size_t>(),
234 E2_main, Y2, x, false); 265 render_buffer, E2_main, Y2, x, s, false);
235 EXPECT_FALSE(state.ExternalDelay()); 266 EXPECT_FALSE(state.ExternalDelay());
236 } 267 }
237 268
238 } // namespace webrtc 269 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_processing/aec3/aec_state.cc ('k') | webrtc/modules/audio_processing/aec3/echo_remover.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698