1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
//! Shared value scaling utilities for audio UI components
//!
//! Provides linear and logarithmic scaling for parameters like
//! frequency (Hz), gain (dB), Q factor, etc.
/// Scale type for value mapping between UI position and actual value
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Scale {
/// Linear scale (default) - equal increments
#[default]
Linear,
/// Logarithmic scale - for frequency, etc.
/// Values must be positive (min > 0)
Logarithmic,
}
impl Scale {
/// Convert a value to normalized position [0, 1] based on scale type
pub fn value_to_normalized(self, value: f64, min: f64, max: f64) -> f64 {
match self {
Scale::Linear => {
if max > min {
((value - min) / (max - min)).clamp(0.0, 1.0)
} else {
0.0
}
}
Scale::Logarithmic => {
// For log scale, min must be > 0
let min = min.max(1e-10);
let max = max.max(min + 1e-10);
let value = value.clamp(min, max);
let log_min = min.ln();
let log_max = max.ln();
((value.ln() - log_min) / (log_max - log_min)).clamp(0.0, 1.0)
}
}
}
/// Convert a normalized position [0, 1] to a value based on scale type
pub fn normalized_to_value(self, normalized: f64, min: f64, max: f64) -> f64 {
match self {
Scale::Linear => min + normalized * (max - min),
Scale::Logarithmic => {
// For log scale, min must be > 0
let min = min.max(1e-10);
let max = max.max(min + 1e-10);
let log_min = min.ln();
let log_max = max.ln();
(log_min + normalized * (log_max - log_min)).exp()
}
}
}
/// Compute new value after stepping in normalized space
/// `direction`: 1.0 for increase, -1.0 for decrease
/// `step_percent`: step size as fraction (e.g., 0.05 for 5%)
pub fn step_value(
self,
current: f64,
min: f64,
max: f64,
direction: f64,
step_percent: f64,
) -> f64 {
let current_norm = self.value_to_normalized(current, min, max);
let new_norm = (current_norm + step_percent * direction).clamp(0.0, 1.0);
self.normalized_to_value(new_norm, min, max)
}
}
/// Default step sizes for scroll/keyboard adjustments
pub mod step_sizes {
/// Normal scroll/keyboard step (5% of range)
pub const NORMAL: f64 = 0.05;
/// Fine step when Shift is held (0.5% of range)
pub const FINE: f64 = 0.005;
/// Large step when Ctrl/Cmd is held (10% of range)
pub const LARGE: f64 = 0.1;
}