Make the separation between target and interferer scenario depend on microphone spacing in NonlinearBeamformer

Depends on this CL: https://codereview.webrtc.org/1378973003/

Review URL: https://codereview.webrtc.org/1388033002

Cr-Commit-Position: refs/heads/master@{#10330}
diff --git a/webrtc/modules/audio_processing/BUILD.gn b/webrtc/modules/audio_processing/BUILD.gn
index 9a45cec..2d0c602 100644
--- a/webrtc/modules/audio_processing/BUILD.gn
+++ b/webrtc/modules/audio_processing/BUILD.gn
@@ -54,6 +54,8 @@
     "audio_buffer.h",
     "audio_processing_impl.cc",
     "audio_processing_impl.h",
+    "beamformer/array_util.cc",
+    "beamformer/array_util.h",
     "beamformer/beamformer.h",
     "beamformer/complex_matrix.h",
     "beamformer/covariance_matrix_generator.cc",
diff --git a/webrtc/modules/audio_processing/audio_processing.gypi b/webrtc/modules/audio_processing/audio_processing.gypi
index a6e8f5c..8f1fbdf 100644
--- a/webrtc/modules/audio_processing/audio_processing.gypi
+++ b/webrtc/modules/audio_processing/audio_processing.gypi
@@ -64,6 +64,8 @@
         'audio_buffer.h',
         'audio_processing_impl.cc',
         'audio_processing_impl.h',
+        'beamformer/array_util.cc',
+        'beamformer/array_util.h',
         'beamformer/beamformer.h',
         'beamformer/complex_matrix.h',
         'beamformer/covariance_matrix_generator.cc',
diff --git a/webrtc/modules/audio_processing/beamformer/array_util.cc b/webrtc/modules/audio_processing/beamformer/array_util.cc
new file mode 100644
index 0000000..c1c4066
--- /dev/null
+++ b/webrtc/modules/audio_processing/beamformer/array_util.cc
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/audio_processing/beamformer/array_util.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "webrtc/base/checks.h"
+
+namespace webrtc {
+
+float GetMinimumSpacing(const std::vector<Point>& array_geometry) {
+  RTC_CHECK_GT(array_geometry.size(), 1u);
+  float mic_spacing = std::numeric_limits<float>::max();
+  for (size_t i = 0; i < (array_geometry.size() - 1); ++i) {
+    for (size_t j = i + 1; j < array_geometry.size(); ++j) {
+      mic_spacing =
+          std::min(mic_spacing, Distance(array_geometry[i], array_geometry[j]));
+    }
+  }
+  return mic_spacing;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_processing/beamformer/array_util.h b/webrtc/modules/audio_processing/beamformer/array_util.h
index f7598c0..2ac174e 100644
--- a/webrtc/modules/audio_processing/beamformer/array_util.h
+++ b/webrtc/modules/audio_processing/beamformer/array_util.h
@@ -12,6 +12,7 @@
 #define WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_ARRAY_UTIL_H_
 
 #include <cmath>
+#include <vector>
 
 namespace webrtc {
 
@@ -31,6 +32,10 @@
 
 using Point = CartesianPoint<float>;
 
+// Returns the minimum distance between any two Points in the given
+// |array_geometry|.
+float GetMinimumSpacing(const std::vector<Point>& array_geometry);
+
 template<typename T>
 float Distance(CartesianPoint<T> a, CartesianPoint<T> b) {
   return std::sqrt((a.x() - b.x()) * (a.x() - b.x()) +
diff --git a/webrtc/modules/audio_processing/beamformer/array_util_unittest.cc b/webrtc/modules/audio_processing/beamformer/array_util_unittest.cc
new file mode 100644
index 0000000..57f1708
--- /dev/null
+++ b/webrtc/modules/audio_processing/beamformer/array_util_unittest.cc
@@ -0,0 +1,32 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/audio_processing/beamformer/array_util.h"
+
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace webrtc {
+
+TEST(ArrayUtilTest, GetMinimumSpacing) {
+  std::vector<Point> array_geometry;
+  array_geometry.push_back(Point(0.f, 0.f, 0.f));
+  array_geometry.push_back(Point(0.1f, 0.f, 0.f));
+  EXPECT_FLOAT_EQ(0.1f, GetMinimumSpacing(array_geometry));
+  array_geometry.push_back(Point(0.f, 0.05f, 0.f));
+  EXPECT_FLOAT_EQ(0.05f, GetMinimumSpacing(array_geometry));
+  array_geometry.push_back(Point(0.f, 0.f, 0.02f));
+  EXPECT_FLOAT_EQ(0.02f, GetMinimumSpacing(array_geometry));
+  array_geometry.push_back(Point(-0.003f, -0.004f, 0.02f));
+  EXPECT_FLOAT_EQ(0.005f, GetMinimumSpacing(array_geometry));
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.cc b/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.cc
index 40e738c..20e6b55 100644
--- a/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.cc
+++ b/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.cc
@@ -36,6 +36,14 @@
 // TODO(aluebs): Make the target angle dynamically settable.
 const float kTargetAngleRadians = static_cast<float>(M_PI) / 2.f;
 
+// The minimum separation in radians between the target direction and an
+// interferer scenario.
+const float kMinAwayRadians = 0.2f;
+
+// The separation between the target direction and the closest interferer
+// scenario is proportional to this constant.
+const float kAwaySlope = 0.008f;
+
 // When calculating the interference covariance matrix, this is the weight for
 // the weighted average between the uniform covariance matrix and the angled
 // covariance matrix.
@@ -189,8 +197,9 @@
 
 NonlinearBeamformer::NonlinearBeamformer(
     const std::vector<Point>& array_geometry)
-  : num_input_channels_(array_geometry.size()),
-      array_geometry_(GetCenteredArray(array_geometry)) {
+    : num_input_channels_(array_geometry.size()),
+      array_geometry_(GetCenteredArray(array_geometry)),
+      min_mic_spacing_(GetMinimumSpacing(array_geometry)) {
   WindowGenerator::KaiserBesselDerived(kKbdAlpha, kFftSize, window_);
 }
 
@@ -253,8 +262,10 @@
 }
 
 void NonlinearBeamformer::InitInterfAngles() {
-  // TODO(aluebs): Make kAwayRadians dependent on the mic spacing.
-  const float kAwayRadians = 0.5;
+  const float kAwayRadians =
+      std::min(static_cast<float>(M_PI),
+               std::max(kMinAwayRadians, kAwaySlope * static_cast<float>(M_PI) /
+                                             min_mic_spacing_));
 
   interf_angles_radians_.clear();
   // TODO(aluebs): When the target angle is settable, make sure the interferer
diff --git a/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h b/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h
index 4ff0b48..d24bbb6 100644
--- a/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h
+++ b/webrtc/modules/audio_processing/beamformer/nonlinear_beamformer.h
@@ -116,6 +116,9 @@
 
   const std::vector<Point> array_geometry_;
 
+  // Minimum spacing between microphone pairs.
+  const float min_mic_spacing_;
+
   // Calculated based on user-input and constants in the .cc file.
   size_t low_mean_start_bin_;
   size_t low_mean_end_bin_;
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 31c3dac..71d200c 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -168,6 +168,7 @@
             # 'audio_processing/agc/agc_unittest.cc',
             'audio_processing/agc/histogram_unittest.cc',
             'audio_processing/agc/mock_agc.h',
+            'audio_processing/beamformer/array_util_unittest.cc',
             'audio_processing/beamformer/complex_matrix_unittest.cc',
             'audio_processing/beamformer/covariance_matrix_generator_unittest.cc',
             'audio_processing/beamformer/matrix_unittest.cc',