rill_core/math/
functions.rs1use super::num::Transcendental;
4
5#[inline(always)]
7pub fn lerp<T: Transcendental>(a: T, b: T, t: T) -> T {
8 a + (b - a) * t
9}
10
11#[inline(always)]
13pub fn db_to_linear<T: Transcendental>(db: T) -> T {
14 T::from_f32(10.0_f32.powf(db.to_f32() / 20.0))
15}
16
17#[inline(always)]
19pub fn linear_to_db<T: Transcendental>(linear: T) -> T {
20 T::from_f32(20.0 * linear.to_f32().log10())
21}
22
23#[inline(always)]
25pub fn midi_to_freq<T: Transcendental>(note: u8) -> T {
26 let exp = (note as f32 - 69.0) / 12.0;
27 T::from_f32(440.0 * 2.0_f32.powf(exp))
28}
29
30#[inline(always)]
32pub fn freq_to_midi<T: Transcendental>(freq: T) -> f32 {
33 69.0 + 12.0 * (freq.to_f32() / 440.0).log2()
34}
35
36#[inline(always)]
38pub fn seconds_to_samples(seconds: f32, sample_rate: f32) -> usize {
39 (seconds * sample_rate) as usize
40}
41
42#[inline(always)]
44pub fn samples_to_seconds(samples: usize, sample_rate: f32) -> f32 {
45 samples as f32 / sample_rate
46}
47
48#[inline(always)]
50pub fn fast_tanh<T: Transcendental>(x: T) -> T {
51 let xf = x.to_f32();
52 T::from_f32(xf / (1.0 + xf.abs()))
53}
54
55#[inline(always)]
57pub fn soft_clip<T: Transcendental>(x: T, threshold: T) -> T {
58 let xf = x.to_f32();
59 let t = threshold.to_f32();
60
61 if xf > t {
62 T::from_f32(t + (xf - t) / (1.0 + ((xf - t) / (1.0 - t)).powi(2)))
63 } else if xf < -t {
64 T::from_f32(-t - (-xf - t) / (1.0 + ((-xf - t) / (1.0 - t)).powi(2)))
65 } else {
66 x
67 }
68}
69
70#[inline(always)]
72pub fn hann_window<T: Transcendental>(x: T) -> T {
73 let cos_term = (x * T::from_f32(2.0) * T::PI).cos();
74 T::from_f32(0.5) * (T::ONE - cos_term)
75}