• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear License
5  * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6  * License was not distributed with this source code in the LICENSE file, you
7  * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8  * Alliance for Open Media Patent License 1.0 was not distributed with this
9  * source code in the PATENTS file, you can obtain it at
10  * www.aomedia.org/license/patent.
11  */
12 
13 #ifndef CLI_AMBISONIC_ENCODER_AMBISONIC_UTILS_H_
14 #define CLI_AMBISONIC_ENCODER_AMBISONIC_UTILS_H_
15 
16 #include <cmath>
17 #include <numbers>
18 
19 #include "absl/log/check.h"
20 
21 // TODO(b/400635711): Use the one in the obr library once it is open-sourced.
22 // This code is forked from Resonance Audio's `misc_math.h`.
23 namespace iamf_tools {
24 // Defines conversion factor from degrees to radians.
25 inline constexpr float kRadiansFromDegrees =
26     static_cast<float>(std::numbers::pi_v<float> / 180.0);
27 
28 // Defines conversion factor from radians to degrees.
29 inline constexpr float kDegreesFromRadians =
30     static_cast<float>(180.0 / std::numbers::pi_v<float>);
31 
32 /*!\brief Returns the factorial (!) of x. If x < 0, it returns 0.
33  *
34  * \param x Input to take factorial of.
35  * \return Computed factorial of input; 0 if the input is negative.
36  */
Factorial(int x)37 inline float Factorial(int x) {
38   if (x < 0) {
39     return 0.0f;
40   }
41   float result = 1.0f;
42   for (; x > 0; --x) {
43     result *= static_cast<float>(x);
44   }
45   return result;
46 }
47 
48 /*!\brief Returns the double factorial (!!) of x.
49  *
50  * For odd x:  1 * 3 * 5 * ... * (x - 2) * x.
51  * For even x: 2 * 4 * 6 * ... * (x - 2) * x.
52  * If x < 0, it returns 0.
53  *
54  * \param x Input to take double factorial of.
55  * \return Computed double factorial of input; 0 if the input is negative.
56  */
DoubleFactorial(int x)57 inline float DoubleFactorial(int x) {
58   if (x < 0) {
59     return 0.0f;
60   }
61   float result = 1.0f;
62   for (; x > 0; x -= 2) {
63     result *= static_cast<float>(x);
64   }
65   return result;
66 }
67 
68 /*!\brief Computes `base`^`exp`, where `exp` is a *non-negative* integer.
69  *
70  * Computed using the squared exponentiation (a.k.a double-and-add) method.
71  * When `T` is a floating point type, this has the same semantics as pow(), but
72  * is much faster.
73  * `T` can also be any integral type, in which case computations will be
74  * performed in the value domain of this integral type, and overflow semantics
75  * will be those of `T`.
76  * You can also use any type for which `operator*=` is defined.
77 
78  * \param base Input to the exponent function. Any type for which *= is defined.
79  * \param exp Integer exponent, must be greater than or equal to zero.
80  * \return `base`^`exp`.
81  */
82 template <typename T>
IntegerPow(T base,int exp)83 static inline T IntegerPow(T base, int exp) {
84   DCHECK_GE(exp, 0);
85   T result = static_cast<T>(1);
86   while (true) {
87     if (exp & 1) {
88       result *= base;
89     }
90     exp >>= 1;
91     if (!exp) break;
92     base *= base;
93   }
94   return result;
95 }
96 
97 /*!\brief Computes ACN channel sequence from a degree and order.
98  *
99  * \param degree Degree of the spherical harmonic.
100  * \param order Order of the spherical harmonic.
101  * \return Computed ACN channel sequence.
102  */
AcnSequence(int degree,int order)103 inline int AcnSequence(int degree, int order) {
104   DCHECK_GE(degree, 0);
105   DCHECK_LE(-degree, order);
106   DCHECK_LE(order, degree);
107 
108   return degree * degree + degree + order;
109 }
110 
111 /*!\brief Computes normalization factor for Schmidt semi-normalized harmonics.
112  *
113  * The Schmidt semi-normalized spherical harmonics is used in AmbiX.
114  *
115  * \param degree Degree of the spherical harmonic.
116  * \param order Order of the spherical harmonic.
117  * \return Computed normalization factor.
118  */
Sn3dNormalization(int degree,int order)119 inline float Sn3dNormalization(int degree, int order) {
120   DCHECK_GE(degree, 0);
121   DCHECK_LE(-degree, order);
122   DCHECK_LE(order, degree);
123   return std::sqrt((2.0f - ((order == 0) ? 1.0f : 0.0f)) *
124                    Factorial(degree - std::abs(order)) /
125                    Factorial(degree + std::abs(order)));
126 }
127 
128 }  // namespace iamf_tools
129 
130 #endif  // CLI_AMBISONIC_ENCODER_AMBISONIC_UTILS_H_
131