Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
math.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 <cfloat>
31#include <cmath>
32#include <limits>
33#include <numbers>
34#include <string>
35
36#include "utils/types.h"
37
44{
45
51constexpr unsigned RMS_FRAMES = 1;
52
55constexpr float ALMOST_SILENCE = 0.0000001f;
56
57constexpr auto MINUS_INFINITY = -HUGE_VAL;
58
64template <std::floating_point T>
65constexpr bool
66floats_near (T a, T b, T e)
67{
68 return std::abs (a - b) < e;
69}
70
74template <std::floating_point T>
75constexpr bool
76floats_equal (T a, T b)
77{
78 return floats_near (a, b, std::numeric_limits<T>::epsilon ());
79}
80
84template <std::floating_point T>
85constexpr long
87{
88 if constexpr (std::is_same_v<T, float>)
89 {
90 return lroundf (x);
91 }
92 else
93 {
94 return lround (x);
95 }
96}
97
101template <std::floating_point T>
102constexpr long long
104{
105 if constexpr (std::is_same_v<T, float>)
106 {
107 return llroundf (x);
108 }
109 else
110 {
111 return llround (x);
112 }
113}
114
115template <std::floating_point T>
116constexpr signed_frame_t
117round_to_signed_frame_t (T x)
118{
119 return round_to_signed_64 (x);
120}
121
128[[gnu::const]]
129constexpr float
130fast_log2 (float val)
131{
132 union
133 {
134 float f;
135 int i;
136 } t;
137 t.f = val;
138 int * const exp_ptr = &t.i;
139 int x = *exp_ptr;
140 const auto log_2 = (float) (((x >> 23) & 255) - 128);
141
142 x &= ~(255 << 23);
143 x += 127 << 23;
144
145 *exp_ptr = x;
146
147 val = ((-1.0f / 3) * t.f + 2) * t.f - 2.0f / 3;
148
149 return (val + log_2);
150}
151
152[[gnu::const]]
153constexpr auto
154fast_log (const float val)
155{
156 return (fast_log2 (val) * std::numbers::ln2_v<float>);
157}
158
159[[gnu::const]]
160constexpr auto
161fast_log10 (const float val)
162{
163 return fast_log2 (val) / 3.312500f;
164}
165
170[[gnu::const]]
171static inline audio_sample_type_t
172get_fader_val_from_amp (audio_sample_type_t amp)
173{
174 constexpr float fader_coefficient1 =
175 /*192.f * logf (2.f);*/
176 133.084258667509499408f;
177 constexpr float fader_coefficient2 =
178 /*powf (logf (2.f), 8.f) * powf (198.f, 8.f);*/
179 1.25870863180257576e17f;
180
181 /* to prevent weird values when amp is very
182 * small */
183 if (amp <= 0.00001f)
184 {
185 return 1e-20f;
186 }
187
188 if (floats_equal (amp, 1.f))
189 {
190 amp = 1.f + 1e-20f;
191 }
192 audio_sample_type_t fader =
193 std::powf (
194 // note: don't use fast_log here - it causes weirdness in faders
195 (6.f * std::logf (amp)) + fader_coefficient1, 8.f)
196 / fader_coefficient2;
197 return fader;
198}
199
203[[gnu::const]]
204static inline audio_sample_type_t
205get_amp_val_from_fader (audio_sample_type_t fader)
206{
207 constexpr float val1 = 1.f / 6.f;
208 return std::powf (
209 2.f, (val1) * (-192.f + 198.f * std::powf (fader, 1.f / 8.f)));
210}
211
215[[gnu::const]]
216static inline audio_sample_type_t
217amp_to_dbfs (audio_sample_type_t amp)
218{
219 return 20.f * std::log10f (amp);
220}
221
228
235static inline audio_sample_type_t
236calculate_rms_db (const audio_sample_type_t * buf, nframes_t nframes)
237{
238 return amp_to_dbfs (calculate_rms_amp (buf, nframes));
239}
240
244[[gnu::const]]
245static inline audio_sample_type_t
246dbfs_to_amp (audio_sample_type_t dbfs)
247{
248 return std::powf (10.f, (dbfs / 20.f));
249}
250
254[[gnu::const]]
255static inline audio_sample_type_t
256dbfs_to_fader_val (audio_sample_type_t dbfs)
257{
258 return get_fader_val_from_amp (dbfs_to_amp (dbfs));
259}
260
268bool
270
276bool
277is_string_valid_float (const std::string &str, float * ret);
278
279} // namespace zrythm::utils::math
uint32_t nframes_t
Frame count.
Definition types.h:58
float audio_sample_type_t
The sample type.
Definition types.h:67
int_fast64_t signed_frame_t
Signed type for frame index.
Definition types.h:75
Math utils.
Definition math.h:44
constexpr bool floats_equal(T a, T b)
Checks if 2 floating point numbers are equal.
Definition math.h:76
constexpr float fast_log2(float val)
Fast log calculation to be used where precision is not required (like log curves).
Definition math.h:130
audio_sample_type_t calculate_rms_amp(const audio_sample_type_t *buf, nframes_t nframes)
Gets the RMS of the given signal as amplitude (0-2).
constexpr long round_to_signed_32(T x)
Rounds a double to a (minimum) signed 32-bit integer.
Definition math.h:86
constexpr bool floats_near(T a, T b, T e)
Returns whether 2 floating point numbers are equal.
Definition math.h:66
constexpr long long round_to_signed_64(T x)
Rounds a double to a (minimum) signed 64-bit integer.
Definition math.h:103
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.h:55
constexpr unsigned RMS_FRAMES
Frames to skip when calculating the RMS.
Definition math.h:51
bool assert_nonnann(float x)
Asserts that the value is non-nan.