firewheel_core/param/
range.rs

1#[cfg(not(feature = "std"))]
2use num_traits::Float;
3
4/// A parameter range with a linear mapping
5#[derive(Debug, Clone, Copy, PartialEq)]
6pub struct LinearRange {
7    pub min: f32,
8    pub max: f32,
9}
10
11impl LinearRange {
12    pub fn new(min: f32, max: f32) -> Self {
13        Self { min, max }
14    }
15
16    /// Map a value to its corresponding raw value for use in DSP
17    pub fn clamp(&self, val: f32) -> f32 {
18        if self.min > self.max {
19            val.min(self.min).max(self.max)
20        } else {
21            val.min(self.max).max(self.min)
22        }
23    }
24}
25
26impl Default for LinearRange {
27    fn default() -> Self {
28        Self { min: 0.0, max: 1.0 }
29    }
30}
31
32/// A parameter range that takes a normalized value in the range `[0.0, 1.0]`
33/// as input and outputs a frequency value in Hz.
34#[derive(Debug, Clone, Copy, PartialEq)]
35pub struct NormToFreqRange {
36    min_hz: f32,
37    max_hz: f32,
38
39    min_log2: f32,
40    range: f32,
41}
42
43impl NormToFreqRange {
44    pub fn new(min_hz: f32, max_hz: f32) -> Self {
45        assert!(min_hz < max_hz);
46        assert_ne!(min_hz, 0.0);
47        assert_ne!(max_hz, 0.0);
48
49        let min_log2 = min_hz.log2();
50        let range = max_hz.log2() - min_log2;
51
52        Self {
53            min_hz,
54            max_hz,
55            min_log2,
56            range,
57        }
58    }
59
60    pub fn min_hz(&self) -> f32 {
61        self.min_hz
62    }
63
64    pub fn max_hz(&self) -> f32 {
65        self.max_hz
66    }
67
68    /// Convert the normalized value in the range `[0.0, 1.0]` to the
69    /// corresponding frequency value in hz.
70    pub fn to_hz(&self, normalized: f32) -> f32 {
71        if normalized <= 0.0 {
72            return self.min_hz;
73        }
74
75        if normalized >= 1.0 {
76            return self.max_hz;
77        }
78
79        2.0f32.powf((normalized * self.range) + self.min_log2)
80    }
81}
82
83/// A parameter range that takes a normalized value in the range `[0.0, 1.0]`
84/// as input and outputs a corresponding value using a power curve.
85#[derive(Debug, Clone, Copy, PartialEq)]
86pub struct NormToPowRange {
87    pub exponent: f32,
88    min: f32,
89    max: f32,
90}
91
92impl NormToPowRange {
93    pub fn new(min: f32, max: f32, exponent: f32) -> Self {
94        assert!(min <= max);
95
96        Self { exponent, min, max }
97    }
98
99    pub fn min(&self) -> f32 {
100        self.min
101    }
102
103    pub fn max(&self) -> f32 {
104        self.max
105    }
106
107    /// Convert the normalized value in the range `[0.0, 1.0]` to the
108    /// corresponding value for use in DSP.
109    pub fn to_dsp(&self, normalized: f32) -> f32 {
110        if normalized <= 0.0 {
111            return self.min;
112        }
113
114        if normalized >= 1.0 {
115            return self.max;
116        }
117
118        normalized.powf(self.exponent) * (self.max - self.min) + self.min
119    }
120}