Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
math_utils.h
1// SPDX-FileCopyrightText: © 2018-2024 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3/*
4 * This file incorporates work covered by the following copyright and
5 * permission notices:
6 *
7 * ---
8 *
9 * Copyright (C) 2017-2019 Robin Gareus <robin@gareus.org>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 *
25 * ---
26 */
27
28#pragma once
29
30#include <cmath>
31#include <limits>
32#include <numbers>
33#include <string>
34
35#include "utils/types.h"
36
43{
44
50constexpr unsigned RMS_FRAMES = 1;
51
54constexpr float ALMOST_SILENCE = 0.0000001f;
55
56constexpr auto MINUS_INFINITY = -HUGE_VAL;
57
63template <std::floating_point T>
64constexpr bool
65floats_near (T a, T b, T e)
66{
67 return std::abs (a - b) < e;
68}
69
73template <std::floating_point T>
74constexpr bool
75floats_equal (T a, T b)
76{
77 return floats_near (a, b, std::numeric_limits<T>::epsilon ());
78}
79
83template <std::floating_point T>
84constexpr long
86{
87 if constexpr (std::is_same_v<T, float>)
88 {
89 return lroundf (x);
90 }
91 else
92 {
93 return lround (x);
94 }
95}
96
100template <std::floating_point T>
101constexpr long long
103{
104 if constexpr (std::is_same_v<T, float>)
105 {
106 return llroundf (x);
107 }
108 else
109 {
110 return llround (x);
111 }
112}
113
120[[gnu::const]]
121constexpr float
122fast_log2 (float val)
123{
124 union
125 {
126 float f;
127 int i;
128 } t{};
129 t.f = val;
130 int * const exp_ptr = &t.i;
131 int x = *exp_ptr;
132 const auto log_2 = (float) (((x >> 23) & 255) - 128);
133
134 x &= ~(255 << 23);
135 x += 127 << 23;
136
137 *exp_ptr = x;
138
139 val = ((-1.0f / 3) * t.f + 2) * t.f - 2.0f / 3;
140
141 return (val + log_2);
142}
143
144[[gnu::const]]
145constexpr auto
146fast_log (const float val)
147{
148 return (fast_log2 (val) * std::numbers::ln2_v<float>);
149}
150
151[[gnu::const]]
152constexpr auto
153fast_log10 (const float val)
154{
155 return fast_log2 (val) / 3.312500f;
156}
157
162template <std::floating_point T>
163[[gnu::const]]
164static inline T
165get_fader_val_from_amp (T amp)
166{
167 constexpr T fader_coefficient1 =
168 /*192.f * logf (2.f);*/
169 133.084258667509499408f;
170 constexpr T fader_coefficient2 =
171 /*powf (logf (2.f), 8.f) * powf (198.f, 8.f);*/
172 1.25870863180257576e17f;
173
174 /* to prevent weird values when amp is very
175 * small */
176 if (amp <= 0.00001f)
177 {
178 return 1e-20f;
179 }
180
181 if (floats_equal (amp, 1.f))
182 {
183 amp = 1.f + 1e-20f;
184 }
185 T fader =
186 std::powf (
187 // note: don't use fast_log here - it causes weirdness in faders
188 (6.f * std::logf (amp)) + fader_coefficient1, 8.f)
189 / fader_coefficient2;
190 return fader;
191}
192
196template <std::floating_point T>
197[[gnu::const]]
198static inline T
199get_amp_val_from_fader (T fader)
200{
201 constexpr float val1 = 1.f / 6.f;
202 return std::powf (
203 2.f, (val1) * (-192.f + 198.f * std::powf (fader, 1.f / 8.f)));
204}
205
209template <std::floating_point T>
210[[gnu::const]]
211static inline T
212amp_to_dbfs (T amp)
213{
214 return 20.f * std::log10f (amp);
215}
216
221float
222calculate_rms_amp (const float * buf, nframes_t nframes);
223
230template <std::floating_point T>
231static inline T
232calculate_rms_db (const T * buf, nframes_t nframes)
233{
234 return amp_to_dbfs (calculate_rms_amp (buf, nframes));
235}
236
240template <std::floating_point T>
241[[gnu::const]]
242static inline T
243dbfs_to_amp (T dbfs)
244{
245 return std::powf (10.f, (dbfs / 20.f));
246}
247
251template <std::floating_point T>
252[[gnu::const]]
253static inline T
254dbfs_to_fader_val (T dbfs)
255{
256 return get_fader_val_from_amp (dbfs_to_amp (dbfs));
257}
258
266bool
268
274bool
275is_string_valid_float (const std::string &str, float * ret);
276
277} // namespace zrythm::utils::math
uint32_t nframes_t
Frame count.
Definition types.h:58
constexpr bool floats_equal(T a, T b)
Checks if 2 floating point numbers are equal.
Definition math_utils.h:75
constexpr float fast_log2(float val)
Fast log calculation to be used where precision is not required (like log curves).
Definition math_utils.h:122
constexpr long round_to_signed_32(T x)
Rounds a double to a (minimum) signed 32-bit integer.
Definition math_utils.h:85
constexpr bool floats_near(T a, T b, T e)
Returns whether 2 floating point numbers are equal.
Definition math_utils.h:65
constexpr long long round_to_signed_64(T x)
Rounds a double to a (minimum) signed 64-bit integer.
Definition math_utils.h:102
bool is_string_valid_float(const std::string &str, float *ret)
Returns whether the given string is a valid float.
constexpr float ALMOST_SILENCE
Tiny number to be used for denormaml prevention (-140dB).
Definition math_utils.h:54
constexpr unsigned RMS_FRAMES
Frames to skip when calculating the RMS.
Definition math_utils.h:50
bool assert_nonnann(float x)
Asserts that the value is non-nan.
float calculate_rms_amp(const float *buf, nframes_t nframes)
Gets the RMS of the given signal as amplitude (0-2).