11d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org/*
21d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
31d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org *
41d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org *  Use of this source code is governed by a BSD-style license
51d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org *  that can be found in the LICENSE file in the root of the source
61d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org *  tree. An additional intellectual property rights grant can be found
71d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org *  in the file PATENTS.  All contributing project authors may
81d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
91d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org */
101d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org
111d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org#ifndef WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_ARRAY_UTIL_H_
121d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org#define WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_ARRAY_UTIL_H_
131d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org
141d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org#include <cmath>
154a66e4a4d8847cef1e61aec6978f64dddece3d96aluebs#include <vector>
161d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org
17be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg#include "webrtc/base/optional.h"
18cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
191d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.orgnamespace webrtc {
201d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org
21cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// Coordinates in meters. The convention used is:
22cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// x: the horizontal dimension, with positive to the right from the camera's
23cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs//    perspective.
24cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// y: the depth dimension, with positive forward from the camera's
25cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs//    perspective.
26cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// z: the vertical dimension, with positive upwards.
271d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.orgtemplate<typename T>
281d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.orgstruct CartesianPoint {
29cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs  CartesianPoint() {
30cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs    c[0] = 0;
31cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs    c[1] = 0;
32cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs    c[2] = 0;
33cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs  }
341d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org  CartesianPoint(T x, T y, T z) {
351d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org    c[0] = x;
361d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org    c[1] = y;
371d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org    c[2] = z;
381d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org  }
39ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  T x() const { return c[0]; }
40ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  T y() const { return c[1]; }
41ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  T z() const { return c[2]; }
421d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org  T c[3];
431d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org};
441d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org
45ebe7422372c561a017990ac59e15e58a2f02d8ebblochusing Point = CartesianPoint<float>;
461d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org
47cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// Calculates the direction from a to b.
48cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro LuebsPoint PairDirection(const Point& a, const Point& b);
49cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
50cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebsfloat DotProduct(const Point& a, const Point& b);
51cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro LuebsPoint CrossProduct(const Point& a, const Point& b);
52cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
53cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebsbool AreParallel(const Point& a, const Point& b);
54cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebsbool ArePerpendicular(const Point& a, const Point& b);
55cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
564a66e4a4d8847cef1e61aec6978f64dddece3d96aluebs// Returns the minimum distance between any two Points in the given
574a66e4a4d8847cef1e61aec6978f64dddece3d96aluebs// |array_geometry|.
584a66e4a4d8847cef1e61aec6978f64dddece3d96aluebsfloat GetMinimumSpacing(const std::vector<Point>& array_geometry);
594a66e4a4d8847cef1e61aec6978f64dddece3d96aluebs
60cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// If the given array geometry is linear it returns the direction without
61cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// normalizing.
62be57983f4bd875c39a229bab5112b32dad004057Karl Wibergrtc::Optional<Point> GetDirectionIfLinear(
63cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs    const std::vector<Point>& array_geometry);
64cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
65cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// If the given array geometry is planar it returns the normal without
66cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// normalizing.
67be57983f4bd875c39a229bab5112b32dad004057Karl Wibergrtc::Optional<Point> GetNormalIfPlanar(
68be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg    const std::vector<Point>& array_geometry);
69cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
70cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// Returns the normal of an array if it has one and it is in the xy-plane.
71be57983f4bd875c39a229bab5112b32dad004057Karl Wibergrtc::Optional<Point> GetArrayNormalIfExists(
72cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs    const std::vector<Point>& array_geometry);
73cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
74cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// The resulting Point will be in the xy-plane.
75cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro LuebsPoint AzimuthToPoint(float azimuth);
76cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
771d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.orgtemplate<typename T>
781d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.orgfloat Distance(CartesianPoint<T> a, CartesianPoint<T> b) {
791d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org  return std::sqrt((a.x() - b.x()) * (a.x() - b.x()) +
801d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org                   (a.y() - b.y()) * (a.y() - b.y()) +
811d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org                   (a.z() - b.z()) * (a.z() - b.z()));
821d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org}
831d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org
84cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// The convention used:
85cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// azimuth: zero is to the right from the camera's perspective, with positive
86cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs//          angles in radians counter-clockwise.
87cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// elevation: zero is horizontal, with positive angles in radians upwards.
88cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// radius: distance from the camera in meters.
89ebe7422372c561a017990ac59e15e58a2f02d8ebblochtemplate <typename T>
90ebe7422372c561a017990ac59e15e58a2f02d8ebblochstruct SphericalPoint {
91ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  SphericalPoint(T azimuth, T elevation, T radius) {
92ebe7422372c561a017990ac59e15e58a2f02d8ebbloch    s[0] = azimuth;
93ebe7422372c561a017990ac59e15e58a2f02d8ebbloch    s[1] = elevation;
94ebe7422372c561a017990ac59e15e58a2f02d8ebbloch    s[2] = radius;
95ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  }
96ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  T azimuth() const { return s[0]; }
97ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  T elevation() const { return s[1]; }
98ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  T distance() const { return s[2]; }
99ebe7422372c561a017990ac59e15e58a2f02d8ebbloch  T s[3];
100ebe7422372c561a017990ac59e15e58a2f02d8ebbloch};
101ebe7422372c561a017990ac59e15e58a2f02d8ebbloch
102ebe7422372c561a017990ac59e15e58a2f02d8ebblochusing SphericalPointf = SphericalPoint<float>;
103ebe7422372c561a017990ac59e15e58a2f02d8ebbloch
104cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs// Helper functions to transform degrees to radians and the inverse.
105cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebstemplate <typename T>
106cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro LuebsT DegreesToRadians(T angle_degrees) {
107cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs  return M_PI * angle_degrees / 180;
108cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs}
109cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
110cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebstemplate <typename T>
111cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro LuebsT RadiansToDegrees(T angle_radians) {
112cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs  return 180 * angle_radians / M_PI;
113cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs}
114cb3f9bd9c024f11e1ee060de23bf65c7a1f9f594Alejandro Luebs
1151d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org}  // namespace webrtc
1161d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org
1171d88394bcb91ba74d7425678079731156e9ba281aluebs@webrtc.org#endif  // WEBRTC_MODULES_AUDIO_PROCESSING_BEAMFORMER_ARRAY_UTIL_H_
118