1 /*
2 * Copyright (C) 2018-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 *
19 * This file incorporates work covered by the following copyright and
20 * permission notices:
21 *
22 * Copyright (C) 2017-2019 Robin Gareus <robin@gareus.org>
23 *
24 * This program is free software; you can redistribute it and/or modify
25 * it under the terms of the GNU General Public License as published by
26 * the Free Software Foundation; either version 2 of the License, or
27 * (at your option) any later version.
28 *
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License along
35 * with this program; if not, write to the Free Software Foundation, Inc.,
36 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 */
38
39 /**
40 * \file
41 *
42 * Math utils.
43 *
44 * For more, look at libs/pbd/pbd/control_math.h in
45 * ardour.
46 */
47
48 #ifndef __UTILS_MATH_H__
49 #define __UTILS_MATH_H__
50
51 #include <float.h>
52 #include <math.h>
53 #include <stdbool.h>
54 #include <stdint.h>
55
56 #include "utils/types.h"
57
58 /**
59 * @addtogroup utils
60 *
61 * @{
62 */
63
64 /**
65 * Frames to skip when calculating the RMS.
66 *
67 * The lower the more CPU intensive.
68 */
69 #define MATH_RMS_FRAMES 1
70
71 /** Tiny number to be used for denormaml prevention
72 * (-140dB). */
73 #define MATH_TINY_NUMBER (0.0000001)
74
75 #define MATH_MINUS_INFINITY (- HUGE_VAL)
76
77 /**
78 * Checks if 2 doubles are equal.
79 *
80 * @param epsilon The allowed difference.
81 */
82 #define math_floats_equal_epsilon(a,b,e) \
83 ((a) > (b) ? (a) - (b) < e : (b) - (a) < e)
84
85 #define math_doubles_equal_epsilon \
86 math_floats_equal_epsilon
87
88 /**
89 * Checks if 2 doubles are equal.
90 */
91 #define math_floats_equal(a,b) \
92 ((a) > (b) ? \
93 (a) - (b) < FLT_EPSILON : \
94 (b) - (a) < FLT_EPSILON)
95
96 #define math_doubles_equal(a,b) \
97 ((a) > (b) ? \
98 (a) - (b) < DBL_EPSILON : \
99 (b) - (a) < DBL_EPSILON)
100
101 /**
102 * Rounds a double to an int.
103 */
104 #define math_round_double_to_type(x,type) \
105 ((type) ((x) + 0.5 - ((x) < 0.0)))
106
107 /**
108 * Rounds a double to an int.
109 */
110 #define math_round_double_to_int(x) \
111 math_round_double_to_type (x, int)
112
113 #define math_round_double_to_uint(x) \
114 math_round_double_to_type (x, unsigned int)
115
116 /**
117 * Rounds a double to a size_t.
118 */
119 #define math_round_double_to_size_t(x) \
120 math_round_double_to_type (x,size_t)
121
122 /**
123 * Rounds a double to a long.
124 */
125 #define math_round_double_to_long(x) \
126 math_round_double_to_type (x,long)
127
128 /**
129 * Rounds a float to a given type.
130 */
131 #define math_round_float_to_type(x,type) \
132 ((type) (x + 0.5f - (x < 0.f)))
133
134 /**
135 * Rounds a float to an int.
136 */
137 #define math_round_float_to_int(x) \
138 math_round_float_to_type (x,int)
139
140 /**
141 * Rounds a float to a long.
142 */
143 #define math_round_float_to_long(x) \
144 math_round_float_to_type (x,long)
145
146 /**
147 * Fast log calculation to be used where precision
148 * is not required (like log curves).
149 *
150 * Taken from ardour from code in the public domain.
151 */
152 CONST
153 static inline float
math_fast_log2(float val)154 math_fast_log2 (
155 float val)
156 {
157 union {float f; int i;} t;
158 t.f = val;
159 int* const exp_ptr = &t.i;
160 int x = *exp_ptr;
161 const int log_2 = ((x >> 23) & 255) - 128;
162
163 x &= ~(255 << 23);
164 x += 127 << 23;
165
166 *exp_ptr = x;
167
168 val = ((-1.0f/3) * t.f + 2) * t.f - 2.0f/3;
169
170 return (val + log_2);
171 }
172
173 CONST
174 static inline float
math_fast_log(const float val)175 math_fast_log (
176 const float val)
177 {
178 return (math_fast_log2 (val) * 0.69314718f);
179 }
180
181 CONST
182 static inline float
math_fast_log10(const float val)183 math_fast_log10 (
184 const float val)
185 {
186 return math_fast_log2(val) / 3.312500f;
187 }
188
189 /**
190 * Returns fader value 0.0 to 1.0 from amp value
191 * 0.0 to 2.0 (+6 dbFS).
192 */
193 CONST
194 static inline sample_t
math_get_fader_val_from_amp(sample_t amp)195 math_get_fader_val_from_amp (
196 sample_t amp)
197 {
198 static const float fader_coefficient1 =
199 /*192.f * logf (2.f);*/
200 133.084258667509499408f;
201 static const float fader_coefficient2 =
202 /*powf (logf (2.f), 8.f) * powf (198.f, 8.f);*/
203 1.25870863180257576e17f;
204
205 /* to prevent weird values when amp is very
206 * small */
207 if (amp <= 0.00001f)
208 {
209 return 1e-20f;
210 }
211 else
212 {
213 if (math_floats_equal (amp, 1.f))
214 {
215 amp = 1.f + 1e-20f;
216 }
217 sample_t fader =
218 powf (
219 6.f * logf (amp) + fader_coefficient1, 8.f) /
220 fader_coefficient2;
221 return (sample_t) fader;
222 }
223 }
224
225 /**
226 * Returns amp value 0.0 to 2.0 (+6 dbFS) from
227 * fader value 0.0 to 1.0.
228 */
229 CONST
230 static inline sample_t
math_get_amp_val_from_fader(sample_t fader)231 math_get_amp_val_from_fader (
232 sample_t fader)
233 {
234 static const float val1 = 1.f / 6.f;
235 return
236 powf (
237 2.f,
238 (val1) *
239 (-192.f + 198.f * powf (fader, 1.f / 8.f)));
240 }
241
242 /**
243 * Convert from amplitude 0.0 to 2.0 to dbFS.
244 */
245 CONST
246 static inline sample_t
math_amp_to_dbfs(sample_t amp)247 math_amp_to_dbfs (
248 sample_t amp)
249 {
250 return 20.f * log10f (amp);
251 }
252
253 sample_t
254 math_calculate_rms_amp (
255 sample_t * buf,
256 const nframes_t nframes);
257
258 /**
259 * Gets the digital peak of the given signal as
260 * amplitude (0-2).
261 */
262 DEPRECATED_MSG ("use abs max")
263 sample_t
264 math_calculate_max_amp (
265 sample_t * buf,
266 const nframes_t nframes);
267
268 /**
269 * Calculate db using RMS method.
270 *
271 * @param buf Buffer containing the samples.
272 * @param nframes Number of samples.
273 */
274 sample_t
275 math_calculate_rms_db (
276 sample_t * buf,
277 const nframes_t nframes);
278
279 /**
280 * Convert form dbFS to amplitude 0.0 to 2.0.
281 */
282 CONST
283 static inline sample_t
math_dbfs_to_amp(sample_t dbfs)284 math_dbfs_to_amp (
285 sample_t dbfs)
286 {
287 return powf (10.f, (dbfs / 20.f));
288 }
289
290 /**
291 * Convert form dbFS to fader val 0.0 to 1.0.
292 */
293 CONST
294 static inline sample_t
math_dbfs_to_fader_val(sample_t dbfs)295 math_dbfs_to_fader_val (
296 sample_t dbfs)
297 {
298 return
299 math_get_fader_val_from_amp (
300 math_dbfs_to_amp (dbfs));
301 }
302
303 /**
304 * Asserts that the value is non-nan.
305 *
306 * Not real-time safe.
307 *
308 * @return Whether the value is valid (nonnan).
309 */
310 bool
311 math_assert_nonnann (
312 float x);
313
314 /**
315 * @}
316 */
317
318 #endif
319