Index: webrtc/modules/audio_processing/beamformer/array_util.cc |
diff --git a/webrtc/modules/audio_processing/beamformer/array_util.cc b/webrtc/modules/audio_processing/beamformer/array_util.cc |
index c1c4066b0c1e581dd1b38216ba01ebbd172d2ad2..ee2fe55493eaebb0f6fba86169f36c845b9f5de3 100644 |
--- a/webrtc/modules/audio_processing/beamformer/array_util.cc |
+++ b/webrtc/modules/audio_processing/beamformer/array_util.cc |
@@ -16,6 +16,11 @@ |
#include "webrtc/base/checks.h" |
namespace webrtc { |
+namespace { |
+ |
+const float kMaxDotProduct = 1e-6f; |
+ |
+} // namespace |
float GetMinimumSpacing(const std::vector<Point>& array_geometry) { |
RTC_CHECK_GT(array_geometry.size(), 1u); |
@@ -29,4 +34,84 @@ float GetMinimumSpacing(const std::vector<Point>& array_geometry) { |
return mic_spacing; |
} |
+Point PairDirection(const Point& a, const Point& b) { |
+ return {b.x() - a.x(), b.y() - a.y(), b.z() - a.z()}; |
+} |
+ |
+float DotProduct(const Point& a, const Point& b) { |
+ return a.x() * b.x() + a.y() * b.y() + a.z() * b.z(); |
+} |
+ |
+Point CrossProduct(const Point& a, const Point& b) { |
+ return {a.y() * b.z() - a.z() * b.y(), a.z() * b.x() - a.x() * b.z(), |
+ a.x() * b.y() - a.y() * b.x()}; |
+} |
+ |
+bool AreParallel(const Point& a, const Point& b) { |
+ Point cross_product = CrossProduct(a, b); |
+ return DotProduct(cross_product, cross_product) < kMaxDotProduct; |
+} |
+ |
+bool ArePerpendicular(const Point& a, const Point& b) { |
+ return std::abs(DotProduct(a, b)) < kMaxDotProduct; |
+} |
+ |
+Point IsGeometryLinear(const std::vector<Point>& array_geometry) { |
+ RTC_DCHECK_GT(array_geometry.size(), 1u); |
+ const Point first_pair_direction = |
+ PairDirection(array_geometry[0], array_geometry[1]); |
+ for (size_t i = 2u; i < array_geometry.size(); ++i) { |
+ const Point pair_direction = |
+ PairDirection(array_geometry[i - 1], array_geometry[i]); |
+ if (!AreParallel(first_pair_direction, pair_direction)) { |
+ return Point(0.f, 0.f, 0.f); |
+ } |
+ } |
+ return first_pair_direction; |
+} |
+ |
+Point IsGeometryPlanar(const std::vector<Point>& array_geometry) { |
+ RTC_DCHECK_GT(array_geometry.size(), 1u); |
+ const Point first_pair_direction = |
+ PairDirection(array_geometry[0], array_geometry[1]); |
+ Point pair_direction(0.f, 0.f, 0.f); |
+ size_t i = 2u; |
+ bool is_linear = true; |
+ for (; i < array_geometry.size() && is_linear; ++i) { |
+ pair_direction = PairDirection(array_geometry[i - 1], array_geometry[i]); |
+ if (!AreParallel(first_pair_direction, pair_direction)) { |
+ is_linear = false; |
+ } |
+ } |
+ if (is_linear) { |
+ return Point(0.f, 0.f, 0.f); |
+ } |
+ const Point normal_direction = |
+ CrossProduct(first_pair_direction, pair_direction); |
+ for (; i < array_geometry.size(); ++i) { |
+ pair_direction = PairDirection(array_geometry[i - 1], array_geometry[i]); |
+ if (!ArePerpendicular(normal_direction, pair_direction)) { |
+ return Point(0.f, 0.f, 0.f); |
+ } |
+ } |
+ return normal_direction; |
+} |
+ |
+Point GetArrayNormal(const std::vector<Point>& array_geometry) { |
+ const Point direction = IsGeometryLinear(array_geometry); |
+ if (DotProduct(direction, direction) > kMaxDotProduct) { |
+ return Point(direction.y(), -direction.x(), 0.f); |
+ } |
+ const Point normal = IsGeometryPlanar(array_geometry); |
+ if (DotProduct(normal, normal) > kMaxDotProduct && |
+ normal.z() < kMaxDotProduct) { |
+ return normal; |
+ } |
+ return Point(0.f, 0.f, 0.f); |
+} |
+ |
+Point AzimuthToPoint(float azimuth) { |
+ return Point(std::cos(azimuth), std::sin(azimuth), 0.f); |
+} |
+ |
} // namespace webrtc |