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

Side by Side Diff: webrtc/modules/audio_processing/aec3/matched_filter_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
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/matched_filter.h" 11 #include "webrtc/modules/audio_processing/aec3/matched_filter.h"
12 12
13 #include "webrtc/typedefs.h"
14 #if defined(WEBRTC_ARCH_X86_FAMILY)
15 #include <emmintrin.h>
16 #endif
13 #include <algorithm> 17 #include <algorithm>
14 #include <sstream> 18 #include <sstream>
15 #include <string> 19 #include <string>
16 20
17 #include "webrtc/modules/audio_processing/aec3/aec3_constants.h" 21 #include "webrtc/base/random.h"
22 #include "webrtc/modules/audio_processing/aec3/aec3_common.h"
18 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" 23 #include "webrtc/modules/audio_processing/logging/apm_data_dumper.h"
19 #include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h" 24 #include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h"
25 #include "webrtc/system_wrappers/include/cpu_features_wrapper.h"
20 #include "webrtc/test/gtest.h" 26 #include "webrtc/test/gtest.h"
21 27
22 namespace webrtc { 28 namespace webrtc {
29 namespace aec3 {
23 namespace { 30 namespace {
24 31
25 std::string ProduceDebugText(size_t delay) { 32 std::string ProduceDebugText(size_t delay) {
26 std::ostringstream ss; 33 std::ostringstream ss;
27 ss << "Delay: " << delay; 34 ss << "Delay: " << delay;
28 return ss.str(); 35 return ss.str();
29 } 36 }
30 37
31 constexpr size_t kWindowSizeSubBlocks = 32; 38 constexpr size_t kWindowSizeSubBlocks = 32;
32 constexpr size_t kAlignmentShiftSubBlocks = kWindowSizeSubBlocks * 3 / 4; 39 constexpr size_t kAlignmentShiftSubBlocks = kWindowSizeSubBlocks * 3 / 4;
33 constexpr size_t kNumMatchedFilters = 4; 40 constexpr size_t kNumMatchedFilters = 4;
34 41
35 } // namespace 42 } // namespace
36 43
44 #if defined(WEBRTC_ARCH_X86_FAMILY)
45 // Verifies that the optimized methods are bitexact to their reference
46 // counterparts.
47 TEST(MatchedFilter, TestOptimizations) {
48 bool use_sse2 = (WebRtc_GetCPUInfo(kSSE2) != 0);
49 if (use_sse2) {
50 Random random_generator(42U);
51 std::vector<float> x(2000);
52 RandomizeSampleVector(&random_generator, x);
53 std::vector<float> y(kSubBlockSize);
54 std::vector<float> h_SSE2(512);
55 std::vector<float> h(512);
56 int x_index = 0;
57 for (int k = 0; k < 1000; ++k) {
58 RandomizeSampleVector(&random_generator, y);
59
60 bool filters_updated = false;
61 float error_sum = 0.f;
62 bool filters_updated_SSE2 = false;
63 float error_sum_SSE2 = 0.f;
64
65 MatchedFilterCore_SSE2(x_index, h.size() * 150.f * 150.f, x, y, h_SSE2,
66 &filters_updated_SSE2, &error_sum_SSE2);
67
68 MatchedFilterCore(x_index, h.size() * 150.f * 150.f, x, y, h,
69 &filters_updated, &error_sum);
70
71 EXPECT_EQ(filters_updated, filters_updated_SSE2);
72 EXPECT_NEAR(error_sum, error_sum_SSE2, error_sum / 100000.f);
73
74 for (size_t j = 0; j < h.size(); ++j) {
75 EXPECT_NEAR(h[j], h_SSE2[j], 0.001f);
76 }
77
78 x_index = (x_index + kSubBlockSize) % x.size();
79 }
80 }
81 }
82
83 #endif
84
37 // Verifies that the matched filter produces proper lag estimates for 85 // Verifies that the matched filter produces proper lag estimates for
38 // artificially 86 // artificially
39 // delayed signals. 87 // delayed signals.
40 TEST(MatchedFilter, LagEstimation) { 88 TEST(MatchedFilter, LagEstimation) {
41 Random random_generator(42U); 89 Random random_generator(42U);
42 std::array<float, kSubBlockSize> render; 90 std::array<float, kSubBlockSize> render;
43 std::array<float, kSubBlockSize> capture; 91 std::array<float, kSubBlockSize> capture;
44 render.fill(0.f); 92 render.fill(0.f);
45 capture.fill(0.f); 93 capture.fill(0.f);
46 ApmDataDumper data_dumper(0); 94 ApmDataDumper data_dumper(0);
47 for (size_t delay_samples : {0, 64, 150, 200, 800, 1000}) { 95 for (size_t delay_samples : {5, 64, 150, 200, 800, 1000}) {
48 SCOPED_TRACE(ProduceDebugText(delay_samples)); 96 SCOPED_TRACE(ProduceDebugText(delay_samples));
49 DelayBuffer<float> signal_delay_buffer(delay_samples); 97 DelayBuffer<float> signal_delay_buffer(delay_samples);
50 MatchedFilter filter(&data_dumper, kWindowSizeSubBlocks, kNumMatchedFilters, 98 MatchedFilter filter(&data_dumper, DetectOptimization(),
99 kWindowSizeSubBlocks, kNumMatchedFilters,
51 kAlignmentShiftSubBlocks); 100 kAlignmentShiftSubBlocks);
52 101
53 // Analyze the correlation between render and capture. 102 // Analyze the correlation between render and capture.
54 for (size_t k = 0; k < (100 + delay_samples / kSubBlockSize); ++k) { 103 for (size_t k = 0; k < (100 + delay_samples / kSubBlockSize); ++k) {
55 RandomizeSampleVector(&random_generator, render); 104 RandomizeSampleVector(&random_generator, render);
56 signal_delay_buffer.Delay(render, capture); 105 signal_delay_buffer.Delay(render, capture);
57 filter.Update(render, capture); 106 filter.Update(render, capture);
58 } 107 }
59 108
60 // Obtain the lag estimates. 109 // Obtain the lag estimates.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 149
101 // Verifies that the matched filter does not produce reliable and accurate 150 // Verifies that the matched filter does not produce reliable and accurate
102 // estimates for uncorrelated render and capture signals. 151 // estimates for uncorrelated render and capture signals.
103 TEST(MatchedFilter, LagNotReliableForUncorrelatedRenderAndCapture) { 152 TEST(MatchedFilter, LagNotReliableForUncorrelatedRenderAndCapture) {
104 Random random_generator(42U); 153 Random random_generator(42U);
105 std::array<float, kSubBlockSize> render; 154 std::array<float, kSubBlockSize> render;
106 std::array<float, kSubBlockSize> capture; 155 std::array<float, kSubBlockSize> capture;
107 render.fill(0.f); 156 render.fill(0.f);
108 capture.fill(0.f); 157 capture.fill(0.f);
109 ApmDataDumper data_dumper(0); 158 ApmDataDumper data_dumper(0);
110 MatchedFilter filter(&data_dumper, kWindowSizeSubBlocks, kNumMatchedFilters, 159 MatchedFilter filter(&data_dumper, DetectOptimization(), kWindowSizeSubBlocks,
111 kAlignmentShiftSubBlocks); 160 kNumMatchedFilters, kAlignmentShiftSubBlocks);
112 161
113 // Analyze the correlation between render and capture. 162 // Analyze the correlation between render and capture.
114 for (size_t k = 0; k < 100; ++k) { 163 for (size_t k = 0; k < 100; ++k) {
115 RandomizeSampleVector(&random_generator, render); 164 RandomizeSampleVector(&random_generator, render);
116 RandomizeSampleVector(&random_generator, capture); 165 RandomizeSampleVector(&random_generator, capture);
117 filter.Update(render, capture); 166 filter.Update(render, capture);
118 } 167 }
119 168
120 // Obtain the lag estimates. 169 // Obtain the lag estimates.
121 auto lag_estimates = filter.GetLagEstimates(); 170 auto lag_estimates = filter.GetLagEstimates();
122 EXPECT_EQ(kNumMatchedFilters, lag_estimates.size()); 171 EXPECT_EQ(kNumMatchedFilters, lag_estimates.size());
123 172
124 // Verify that no lag estimates are reliable. 173 // Verify that no lag estimates are reliable.
125 for (auto& le : lag_estimates) { 174 for (auto& le : lag_estimates) {
126 EXPECT_FALSE(le.reliable); 175 EXPECT_FALSE(le.reliable);
127 } 176 }
128 } 177 }
129 178
130 // Verifies that the matched filter does not produce updated lag estimates for 179 // Verifies that the matched filter does not produce updated lag estimates for
131 // render signals of low level. 180 // render signals of low level.
132 TEST(MatchedFilter, LagNotUpdatedForLowLevelRender) { 181 TEST(MatchedFilter, LagNotUpdatedForLowLevelRender) {
133 Random random_generator(42U); 182 Random random_generator(42U);
134 std::array<float, kSubBlockSize> render; 183 std::array<float, kSubBlockSize> render;
135 std::array<float, kSubBlockSize> capture; 184 std::array<float, kSubBlockSize> capture;
136 render.fill(0.f); 185 render.fill(0.f);
137 capture.fill(0.f); 186 capture.fill(0.f);
138 ApmDataDumper data_dumper(0); 187 ApmDataDumper data_dumper(0);
139 MatchedFilter filter(&data_dumper, kWindowSizeSubBlocks, kNumMatchedFilters, 188 MatchedFilter filter(&data_dumper, DetectOptimization(), kWindowSizeSubBlocks,
140 kAlignmentShiftSubBlocks); 189 kNumMatchedFilters, kAlignmentShiftSubBlocks);
141 190
142 // Analyze the correlation between render and capture. 191 // Analyze the correlation between render and capture.
143 for (size_t k = 0; k < 100; ++k) { 192 for (size_t k = 0; k < 100; ++k) {
144 RandomizeSampleVector(&random_generator, render); 193 RandomizeSampleVector(&random_generator, render);
145 for (auto& render_k : render) { 194 for (auto& render_k : render) {
146 render_k *= 149.f / 32767.f; 195 render_k *= 149.f / 32767.f;
147 } 196 }
148 std::copy(render.begin(), render.end(), capture.begin()); 197 std::copy(render.begin(), render.end(), capture.begin());
149 filter.Update(render, capture); 198 filter.Update(render, capture);
150 } 199 }
151 200
152 // Obtain the lag estimates. 201 // Obtain the lag estimates.
153 auto lag_estimates = filter.GetLagEstimates(); 202 auto lag_estimates = filter.GetLagEstimates();
154 EXPECT_EQ(kNumMatchedFilters, lag_estimates.size()); 203 EXPECT_EQ(kNumMatchedFilters, lag_estimates.size());
155 204
156 // Verify that no lag estimates are updated and that no lag estimates are 205 // Verify that no lag estimates are updated and that no lag estimates are
157 // reliable. 206 // reliable.
158 for (auto& le : lag_estimates) { 207 for (auto& le : lag_estimates) {
159 EXPECT_FALSE(le.updated); 208 EXPECT_FALSE(le.updated);
160 EXPECT_FALSE(le.reliable); 209 EXPECT_FALSE(le.reliable);
161 } 210 }
162 } 211 }
163 212
164 // Verifies that the correct number of lag estimates are produced for a certain 213 // Verifies that the correct number of lag estimates are produced for a certain
165 // number of alignment shifts. 214 // number of alignment shifts.
166 TEST(MatchedFilter, NumberOfLagEstimates) { 215 TEST(MatchedFilter, NumberOfLagEstimates) {
167 ApmDataDumper data_dumper(0); 216 ApmDataDumper data_dumper(0);
168 for (size_t num_matched_filters = 0; num_matched_filters < 10; 217 for (size_t num_matched_filters = 0; num_matched_filters < 10;
169 ++num_matched_filters) { 218 ++num_matched_filters) {
170 MatchedFilter filter(&data_dumper, 32, num_matched_filters, 1); 219 MatchedFilter filter(&data_dumper, DetectOptimization(), 32,
220 num_matched_filters, 1);
171 EXPECT_EQ(num_matched_filters, filter.GetLagEstimates().size()); 221 EXPECT_EQ(num_matched_filters, filter.GetLagEstimates().size());
172 } 222 }
173 } 223 }
174 224
175 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 225 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
176 226
177 // Verifies the check for non-zero windows size. 227 // Verifies the check for non-zero windows size.
178 TEST(MatchedFilter, ZeroWindowSize) { 228 TEST(MatchedFilter, ZeroWindowSize) {
179 ApmDataDumper data_dumper(0); 229 ApmDataDumper data_dumper(0);
180 EXPECT_DEATH(MatchedFilter(&data_dumper, 0, 1, 1), ""); 230 EXPECT_DEATH(MatchedFilter(&data_dumper, DetectOptimization(), 0, 1, 1), "");
181 } 231 }
182 232
183 // Verifies the check for non-null data dumper. 233 // Verifies the check for non-null data dumper.
184 TEST(MatchedFilter, NullDataDumper) { 234 TEST(MatchedFilter, NullDataDumper) {
185 EXPECT_DEATH(MatchedFilter(nullptr, 1, 1, 1), ""); 235 EXPECT_DEATH(MatchedFilter(nullptr, DetectOptimization(), 1, 1, 1), "");
186 } 236 }
187 237
188 #endif 238 #endif
189 239
240 } // namespace aec3
190 } // namespace webrtc 241 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698