rytm_rs/object/sound/page/
lfo.rs1#![allow(
5 clippy::cast_lossless,
6 clippy::cast_possible_truncation,
7 clippy::cast_sign_loss
8)]
9
10use crate::{
11 error::{ConversionError, ParameterError, RytmError},
12 object::sound::types::{LfoDestination, LfoMode, LfoMultiplier, LfoWaveform},
13 util::{
14 from_s_u16_t, i8_to_u8_midpoint_of_u8_input_range, scale_f32_to_u16, scale_u16_to_f32,
15 to_s_u16_t_union_a, u8_to_i8_midpoint_of_u8_input_range,
16 },
17};
18use rytm_rs_macro::parameter_range;
19use rytm_sys::ar_sound_t;
20use serde::{Deserialize, Serialize};
21
22#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
24pub struct Lfo {
25 speed: i8,
26 multiplier: LfoMultiplier,
27 fade: i8,
28 destination: LfoDestination,
29 waveform: LfoWaveform,
30 start_phase_or_slew: u8,
31 mode: LfoMode,
32 depth: f32,
33}
34
35impl Default for Lfo {
36 fn default() -> Self {
37 Self {
38 speed: 48,
39 multiplier: LfoMultiplier::default(),
40 fade: 0,
41 destination: LfoDestination::default(),
42 waveform: LfoWaveform::default(),
43 start_phase_or_slew: 0,
44 mode: LfoMode::default(),
45 depth: 0.0,
46 }
47 }
48}
49
50impl TryFrom<&ar_sound_t> for Lfo {
51 type Error = ConversionError;
52 fn try_from(raw_sound: &ar_sound_t) -> Result<Self, Self::Error> {
53 let depth = scale_u16_to_f32(
56 unsafe { from_s_u16_t(raw_sound.lfo_depth) },
57 0u16,
58 32767u16,
59 -128f32,
60 127.99f32,
61 );
62
63 Ok(Self {
64 speed: u8_to_i8_midpoint_of_u8_input_range(raw_sound.lfo_speed, 0, 127),
65 multiplier: raw_sound.lfo_multiplier.try_into()?,
66 fade: u8_to_i8_midpoint_of_u8_input_range(raw_sound.lfo_fade, 0, 127),
67 destination: raw_sound.lfo_dest.try_into()?,
68 waveform: raw_sound.lfo_wav.try_into()?,
69 start_phase_or_slew: raw_sound.lfo_start_phase,
70 mode: raw_sound.lfo_mode.try_into()?,
71 depth,
72 })
73 }
74}
75
76impl Lfo {
77 pub(crate) fn apply_to_raw_sound(&self, raw_sound: &mut ar_sound_t) {
78 let depth = to_s_u16_t_union_a(scale_f32_to_u16(
79 self.depth, -128f32, 127.99f32, 0u16, 32767u16,
80 ));
81
82 raw_sound.lfo_speed = i8_to_u8_midpoint_of_u8_input_range(self.speed, 0, 127);
83 raw_sound.lfo_multiplier = self.multiplier.into();
84 raw_sound.lfo_fade = i8_to_u8_midpoint_of_u8_input_range(self.fade, 0, 127);
85 raw_sound.lfo_dest = self.destination.into();
86 raw_sound.lfo_wav = self.waveform.into();
87 raw_sound.lfo_start_phase = self.start_phase_or_slew;
88 raw_sound.lfo_mode = self.mode.into();
89 raw_sound.lfo_depth = depth;
90 }
91
92 #[parameter_range(range = "speed:-64..=63")]
96 pub fn set_speed(&mut self, speed: isize) -> Result<(), RytmError> {
97 self.speed = speed as i8;
98 Ok(())
99 }
100
101 pub fn set_multiplier(&mut self, multiplier: LfoMultiplier) {
103 self.multiplier = multiplier;
104 }
105
106 #[parameter_range(range = "fade:-64..=63")]
110 pub fn set_fade(&mut self, fade: isize) -> Result<(), RytmError> {
111 self.fade = fade as i8;
112 Ok(())
113 }
114
115 pub fn set_destination(&mut self, destination: LfoDestination) {
117 self.destination = destination;
118 }
119
120 pub fn set_waveform(&mut self, waveform: LfoWaveform) {
122 self.waveform = waveform;
123 }
124
125 #[parameter_range(range = "depth:-128.0..=127.99")]
129 pub fn set_depth(&mut self, depth: f32) -> Result<(), RytmError> {
130 self.depth = depth;
131 Ok(())
132 }
133
134 #[parameter_range(range = "start_phase_or_slew:0..=127")]
138 pub fn set_start_phase(&mut self, start_phase_or_slew: usize) -> Result<(), RytmError> {
139 self.start_phase_or_slew = start_phase_or_slew as u8;
140 Ok(())
141 }
142
143 pub fn set_mode(&mut self, mode: LfoMode) {
145 self.mode = mode;
146 }
147
148 pub const fn speed(&self) -> isize {
152 self.speed as isize
153 }
154
155 pub const fn multiplier(&self) -> LfoMultiplier {
157 self.multiplier
158 }
159
160 pub const fn fade(&self) -> isize {
164 self.fade as isize
165 }
166
167 pub const fn destination(&self) -> LfoDestination {
169 self.destination
170 }
171
172 pub const fn waveform(&self) -> LfoWaveform {
174 self.waveform
175 }
176
177 pub const fn start_phase_or_slew(&self) -> usize {
181 self.start_phase_or_slew as usize
182 }
183
184 pub const fn mode(&self) -> LfoMode {
186 self.mode
187 }
188
189 pub const fn depth(&self) -> f32 {
193 self.depth
194 }
195}