Skip to main content

truce_params/
types.rs

1use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU32, Ordering};
2
3use crate::info::ParamInfo;
4use crate::smooth::{Smoother, SmoothingStyle};
5
6/// Atomic f64 — wraps AtomicU64 with f64 load/store.
7pub struct AtomicF64 {
8    bits: std::sync::atomic::AtomicU64,
9}
10
11impl AtomicF64 {
12    pub fn new(value: f64) -> Self {
13        Self {
14            bits: std::sync::atomic::AtomicU64::new(value.to_bits()),
15        }
16    }
17
18    #[inline]
19    pub fn load(&self) -> f64 {
20        f64::from_bits(self.bits.load(Ordering::Relaxed))
21    }
22
23    #[inline]
24    pub fn store(&self, value: f64) {
25        self.bits.store(value.to_bits(), Ordering::Relaxed);
26    }
27}
28
29/// A continuous floating-point parameter.
30pub struct FloatParam {
31    pub info: ParamInfo,
32    value: AtomicF64,
33    pub smoother: Smoother,
34}
35
36impl FloatParam {
37    pub fn new(info: ParamInfo, smoothing: SmoothingStyle) -> Self {
38        let default = info.default_plain;
39        let smoother = Smoother::new(smoothing);
40        smoother.snap(default);
41        Self {
42            info,
43            value: AtomicF64::new(default),
44            smoother,
45        }
46    }
47
48    /// Current raw value. Safe from any thread.
49    #[inline]
50    pub fn value(&self) -> f32 {
51        self.value.load() as f32
52    }
53
54    /// Set the plain value (used by host automation).
55    #[inline]
56    pub fn set_value(&self, v: f64) {
57        self.value.store(v);
58    }
59
60    /// Next smoothed value. Call once per sample in process().
61    #[inline]
62    pub fn smoothed_next(&self) -> f32 {
63        let target = self.value.load();
64        self.smoother.next(target)
65    }
66
67    /// Current smoothed value without advancing.
68    #[inline]
69    pub fn smoothed(&self) -> f32 {
70        self.smoother.current()
71    }
72
73    /// Parameter ID.
74    pub fn id(&self) -> u32 {
75        self.info.id
76    }
77}
78
79/// A boolean parameter.
80pub struct BoolParam {
81    pub info: ParamInfo,
82    value: AtomicBool,
83}
84
85impl BoolParam {
86    pub fn new(info: ParamInfo) -> Self {
87        let default = info.default_plain != 0.0;
88        Self {
89            info,
90            value: AtomicBool::new(default),
91        }
92    }
93
94    pub fn value(&self) -> bool {
95        self.value.load(Ordering::Relaxed)
96    }
97
98    pub fn set_value(&self, v: bool) {
99        self.value.store(v, Ordering::Relaxed);
100    }
101
102    pub fn id(&self) -> u32 {
103        self.info.id
104    }
105}
106
107/// An integer parameter.
108pub struct IntParam {
109    pub info: ParamInfo,
110    value: AtomicI64,
111}
112
113impl IntParam {
114    pub fn new(info: ParamInfo) -> Self {
115        let default = info.default_plain as i64;
116        Self {
117            info,
118            value: AtomicI64::new(default),
119        }
120    }
121
122    pub fn value(&self) -> i64 {
123        self.value.load(Ordering::Relaxed)
124    }
125
126    pub fn set_value(&self, v: i64) {
127        self.value.store(v, Ordering::Relaxed);
128    }
129
130    pub fn id(&self) -> u32 {
131        self.info.id
132    }
133}
134
135/// Trait for enums used as parameters.
136pub trait ParamEnum: Clone + Copy + Send + Sync + 'static {
137    fn from_index(index: usize) -> Self;
138    fn to_index(&self) -> usize;
139    fn name(&self) -> &'static str;
140    fn variant_count() -> usize;
141    fn variant_names() -> &'static [&'static str];
142}
143
144/// An enum parameter.
145pub struct EnumParam<E: ParamEnum> {
146    pub info: ParamInfo,
147    value: AtomicU32,
148    _phantom: std::marker::PhantomData<E>,
149}
150
151impl<E: ParamEnum> EnumParam<E> {
152    pub fn new(info: ParamInfo) -> Self {
153        let default = info.default_plain as u32;
154        Self {
155            info,
156            value: AtomicU32::new(default),
157            _phantom: std::marker::PhantomData,
158        }
159    }
160
161    pub fn value(&self) -> E {
162        E::from_index(self.value.load(Ordering::Relaxed) as usize)
163    }
164
165    pub fn set_value(&self, v: E) {
166        self.value.store(v.to_index() as u32, Ordering::Relaxed);
167    }
168
169    pub fn set_index(&self, idx: u32) {
170        self.value.store(idx, Ordering::Relaxed);
171    }
172
173    pub fn index(&self) -> u32 {
174        self.value.load(Ordering::Relaxed)
175    }
176
177    pub fn id(&self) -> u32 {
178        self.info.id
179    }
180
181    /// Format a plain value (index as f64) to the variant name string.
182    ///
183    /// Used by the `#[derive(Params)]` macro for default `format_value` on enum fields.
184    pub fn format_by_index(&self, value: f64) -> String {
185        E::from_index(value.round() as usize).name().to_string()
186    }
187}