music_math/
scaling.rs

1use crate::binaryops::clip;
2use num_traits::Float;
3
4/// Map an input value from one range to another.
5/// It performs clipping on the input value in the range of `from_min` and `from_max`.
6/// Using generics, this function can map any type that implements the `Into` trait.
7///
8/// Note: If the denominator is zero, the function will return `to_min` to avoid division by zero.
9#[inline]
10#[must_use]
11pub fn linlin<T: Float>(value: T, from_min: T, from_max: T, to_min: T, to_max: T) -> T {
12    let denominator = from_max.sub(from_min);
13
14    if denominator == T::zero() {
15        return to_min;
16    }
17
18    let value = clip(value, from_min, from_max);
19    let nominator = value.sub(from_min);
20
21    nominator
22        .mul(to_max.sub(to_min))
23        .div(denominator)
24        .add(to_min)
25}
26
27/// Map an input value from one range to another with an exponential curve. It performs clipping on
28/// the input value in the range of `from_min` and `from_max`.
29/// Using generics, this function can map any type that implements the `Float` trait.
30///
31/// Note: If the denominator is zero, the function will return `to_min` to avoid division by zero.
32#[inline]
33#[must_use]
34pub fn linexp<T: Float>(
35    value: T,
36    from_min: T,
37    from_max: T,
38    to_min: T,
39    to_max: T,
40    exponent: T,
41) -> T {
42    let denominator = from_max.sub(from_min);
43    if denominator == T::zero() {
44        to_min
45    } else {
46        let value = clip(value, from_min, from_max);
47        let value = value.sub(from_min).div(denominator).powf(exponent);
48
49        value.mul(to_max.sub(to_min)).add(to_min)
50    }
51}
52
53/// Convert a decibel value to amplitude.
54/// # Panics
55/// If a type conversion fails.
56#[inline]
57#[must_use]
58pub fn dbamp<T: Float>(db: T) -> T {
59    let twenty = T::from(20.0).expect("Could not convert 20.0 to T");
60    let ten = T::from(10.0).expect("Could not convert 10.0 to T");
61    let n = db.div(twenty);
62
63    ten.powf(n)
64}
65
66/// Convert an amplitude value to decibels.
67/// # Panics
68/// If a type conversion fails.
69#[inline]
70#[must_use]
71pub fn ampdb<T: Float>(amp: T) -> T {
72    let twenty = T::from(20.0).expect("Could not convert 20.0 to T");
73    twenty.mul(amp.log10())
74}