| 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
 | 
| 
 |