1use std::sync::atomic::{AtomicBool, AtomicI64, AtomicU32, Ordering};
2
3use crate::info::ParamInfo;
4use crate::smooth::{Smoother, SmoothingStyle};
5
6pub 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
29pub 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 #[inline]
50 pub fn value(&self) -> f32 {
51 self.value.load() as f32
52 }
53
54 #[inline]
56 pub fn set_value(&self, v: f64) {
57 self.value.store(v);
58 }
59
60 #[inline]
62 pub fn smoothed_next(&self) -> f32 {
63 let target = self.value.load();
64 self.smoother.next(target)
65 }
66
67 #[inline]
69 pub fn smoothed(&self) -> f32 {
70 self.smoother.current()
71 }
72
73 pub fn id(&self) -> u32 {
75 self.info.id
76 }
77}
78
79pub 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
107pub 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
135pub 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
144pub 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 pub fn format_by_index(&self, value: f64) -> String {
185 E::from_index(value.round() as usize).name().to_string()
186 }
187}