Index: webrtc/modules/audio_processing/aec3/matched_filter_unittest.cc |
diff --git a/webrtc/modules/audio_processing/aec3/matched_filter_unittest.cc b/webrtc/modules/audio_processing/aec3/matched_filter_unittest.cc |
index 993ebc8b92ce59b387f47db34357f6712f76f9c5..952b3710fe04deff81f157e6a8612500c1a65685 100644 |
--- a/webrtc/modules/audio_processing/aec3/matched_filter_unittest.cc |
+++ b/webrtc/modules/audio_processing/aec3/matched_filter_unittest.cc |
@@ -10,16 +10,23 @@ |
#include "webrtc/modules/audio_processing/aec3/matched_filter.h" |
+#include "webrtc/typedefs.h" |
+#if defined(WEBRTC_ARCH_X86_FAMILY) |
+#include <emmintrin.h> |
+#endif |
#include <algorithm> |
#include <sstream> |
#include <string> |
-#include "webrtc/modules/audio_processing/aec3/aec3_constants.h" |
+#include "webrtc/base/random.h" |
+#include "webrtc/modules/audio_processing/aec3/aec3_common.h" |
#include "webrtc/modules/audio_processing/logging/apm_data_dumper.h" |
#include "webrtc/modules/audio_processing/test/echo_canceller_test_tools.h" |
+#include "webrtc/system_wrappers/include/cpu_features_wrapper.h" |
#include "webrtc/test/gtest.h" |
namespace webrtc { |
+namespace aec3 { |
namespace { |
std::string ProduceDebugText(size_t delay) { |
@@ -34,6 +41,47 @@ constexpr size_t kNumMatchedFilters = 4; |
} // namespace |
+#if defined(WEBRTC_ARCH_X86_FAMILY) |
+// Verifies that the optimized methods are bitexact to their reference |
+// counterparts. |
+TEST(MatchedFilter, TestOptimizations) { |
+ bool use_sse2 = (WebRtc_GetCPUInfo(kSSE2) != 0); |
+ if (use_sse2) { |
+ Random random_generator(42U); |
+ std::vector<float> x(2000); |
+ RandomizeSampleVector(&random_generator, x); |
+ std::vector<float> y(kSubBlockSize); |
+ std::vector<float> h_SSE2(512); |
+ std::vector<float> h(512); |
+ int x_index = 0; |
+ for (int k = 0; k < 1000; ++k) { |
+ RandomizeSampleVector(&random_generator, y); |
+ |
+ bool filters_updated = false; |
+ float error_sum = 0.f; |
+ bool filters_updated_SSE2 = false; |
+ float error_sum_SSE2 = 0.f; |
+ |
+ MatchedFilterCore_SSE2(x_index, h.size() * 150.f * 150.f, x, y, h_SSE2, |
+ &filters_updated_SSE2, &error_sum_SSE2); |
+ |
+ MatchedFilterCore(x_index, h.size() * 150.f * 150.f, x, y, h, |
+ &filters_updated, &error_sum); |
+ |
+ EXPECT_EQ(filters_updated, filters_updated_SSE2); |
+ EXPECT_NEAR(error_sum, error_sum_SSE2, error_sum / 100000.f); |
+ |
+ for (size_t j = 0; j < h.size(); ++j) { |
+ EXPECT_NEAR(h[j], h_SSE2[j], 0.001f); |
+ } |
+ |
+ x_index = (x_index + kSubBlockSize) % x.size(); |
+ } |
+ } |
+} |
+ |
+#endif |
+ |
// Verifies that the matched filter produces proper lag estimates for |
// artificially |
// delayed signals. |
@@ -44,10 +92,11 @@ TEST(MatchedFilter, LagEstimation) { |
render.fill(0.f); |
capture.fill(0.f); |
ApmDataDumper data_dumper(0); |
- for (size_t delay_samples : {0, 64, 150, 200, 800, 1000}) { |
+ for (size_t delay_samples : {5, 64, 150, 200, 800, 1000}) { |
SCOPED_TRACE(ProduceDebugText(delay_samples)); |
DelayBuffer<float> signal_delay_buffer(delay_samples); |
- MatchedFilter filter(&data_dumper, kWindowSizeSubBlocks, kNumMatchedFilters, |
+ MatchedFilter filter(&data_dumper, DetectOptimization(), |
+ kWindowSizeSubBlocks, kNumMatchedFilters, |
kAlignmentShiftSubBlocks); |
// Analyze the correlation between render and capture. |
@@ -107,8 +156,8 @@ TEST(MatchedFilter, LagNotReliableForUncorrelatedRenderAndCapture) { |
render.fill(0.f); |
capture.fill(0.f); |
ApmDataDumper data_dumper(0); |
- MatchedFilter filter(&data_dumper, kWindowSizeSubBlocks, kNumMatchedFilters, |
- kAlignmentShiftSubBlocks); |
+ MatchedFilter filter(&data_dumper, DetectOptimization(), kWindowSizeSubBlocks, |
+ kNumMatchedFilters, kAlignmentShiftSubBlocks); |
// Analyze the correlation between render and capture. |
for (size_t k = 0; k < 100; ++k) { |
@@ -136,8 +185,8 @@ TEST(MatchedFilter, LagNotUpdatedForLowLevelRender) { |
render.fill(0.f); |
capture.fill(0.f); |
ApmDataDumper data_dumper(0); |
- MatchedFilter filter(&data_dumper, kWindowSizeSubBlocks, kNumMatchedFilters, |
- kAlignmentShiftSubBlocks); |
+ MatchedFilter filter(&data_dumper, DetectOptimization(), kWindowSizeSubBlocks, |
+ kNumMatchedFilters, kAlignmentShiftSubBlocks); |
// Analyze the correlation between render and capture. |
for (size_t k = 0; k < 100; ++k) { |
@@ -167,7 +216,8 @@ TEST(MatchedFilter, NumberOfLagEstimates) { |
ApmDataDumper data_dumper(0); |
for (size_t num_matched_filters = 0; num_matched_filters < 10; |
++num_matched_filters) { |
- MatchedFilter filter(&data_dumper, 32, num_matched_filters, 1); |
+ MatchedFilter filter(&data_dumper, DetectOptimization(), 32, |
+ num_matched_filters, 1); |
EXPECT_EQ(num_matched_filters, filter.GetLagEstimates().size()); |
} |
} |
@@ -177,14 +227,15 @@ TEST(MatchedFilter, NumberOfLagEstimates) { |
// Verifies the check for non-zero windows size. |
TEST(MatchedFilter, ZeroWindowSize) { |
ApmDataDumper data_dumper(0); |
- EXPECT_DEATH(MatchedFilter(&data_dumper, 0, 1, 1), ""); |
+ EXPECT_DEATH(MatchedFilter(&data_dumper, DetectOptimization(), 0, 1, 1), ""); |
} |
// Verifies the check for non-null data dumper. |
TEST(MatchedFilter, NullDataDumper) { |
- EXPECT_DEATH(MatchedFilter(nullptr, 1, 1, 1), ""); |
+ EXPECT_DEATH(MatchedFilter(nullptr, DetectOptimization(), 1, 1, 1), ""); |
} |
#endif |
+} // namespace aec3 |
} // namespace webrtc |