rytm_rs/object/sound/machine/
hh_basic.rs

1use crate::{
2    error::{ParameterError, RytmError},
3    object::pattern::plock::ParameterLockPool,
4    util::{
5        from_s_u16_t, i8_to_u8_midpoint_of_u8_input_range, to_s_u16_t_union_a,
6        u8_to_i8_midpoint_of_u8_input_range,
7    },
8    RytmError::OrphanTrig,
9};
10use derivative::Derivative;
11use parking_lot::Mutex;
12use rytm_rs_macro::{machine_parameters, parameter_range};
13use rytm_sys::ar_sound_t;
14use serde::{Deserialize, Serialize};
15use std::sync::Arc;
16
17#[machine_parameters(
18    lev: "0..=127" #1,
19    tun: "-64..=63" #2,
20    dec: "0..=127" #3,
21    ton:  "-64..=63" #4,
22    trd: "0..=127" #5,
23    // rst #6 
24    // Unavailable #7
25    // Unavailable #8
26)]
27/// Parameters for the `HhBasic` machine.
28#[derive(Derivative, Clone, Serialize, Deserialize)]
29#[derivative(Debug)]
30pub struct HhBasicParameters {
31    lev: u8,
32    tun: i8,
33    dec: u8,
34    ton: i8,
35    trd: u8,
36    rst: bool,
37
38    #[derivative(Debug = "ignore")]
39    #[serde(skip)]
40    parameter_lock_pool: Option<Arc<Mutex<ParameterLockPool>>>,
41    assigned_track: Option<usize>,
42}
43
44impl Default for HhBasicParameters {
45    fn default() -> Self {
46        Self {
47            lev: 110,
48            tun: 0,
49            dec: 29,
50            ton: 0,
51            trd: 68,
52            rst: false,
53            parameter_lock_pool: None,
54            assigned_track: None,
55        }
56    }
57}
58
59impl HhBasicParameters {
60    pub(crate) fn link_parameter_lock_pool(&mut self, pool: Arc<Mutex<ParameterLockPool>>) {
61        self.parameter_lock_pool = Some(pool);
62    }
63
64    pub(crate) fn apply_to_raw_sound(&self, raw_sound: &mut ar_sound_t) {
65        self.apply_to_raw_sound_values(raw_sound);
66        raw_sound.synth_param_6 = to_s_u16_t_union_a(((self.rst as u8) as u16) << 8);
67    }
68
69    /// Returns the `rst` parameter.
70    pub const fn get_rst(&self) -> bool {
71        self.rst
72    }
73
74    /// Sets the `rst` parameter.
75    pub fn set_rst(&mut self, rst: bool) {
76        self.rst = rst;
77    }
78
79    /// Sets the parameter lock for the `rst` parameter.
80    pub fn plock_set_rst(&self, rst: bool, trig_index: usize) -> Result<(), RytmError> {
81        if let Some(ref pool) = self.parameter_lock_pool {
82            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
83            pool.lock().set_basic_plock(
84                trig_index,
85                assigned_track as u8,
86                rytm_sys::AR_PLOCK_TYPE_MP6 as u8,
87                rst as u8,
88            )?;
89            return Ok(());
90        }
91        Err(OrphanTrig)
92    }
93
94    /// Gets the parameter lock for the `rst` parameter.
95    pub fn plock_get_rst(&self, trig_index: usize) -> Result<Option<bool>, RytmError> {
96        if let Some(ref pool) = self.parameter_lock_pool {
97            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
98            let rst = pool.lock().get_basic_plock(
99                trig_index,
100                assigned_track as u8,
101                rytm_sys::AR_PLOCK_TYPE_MP6 as u8,
102            );
103            if let Some(rst) = rst {
104                return Ok(Some(rst != 0));
105            }
106            return Ok(None);
107        }
108        Err(OrphanTrig)
109    }
110
111    /// Clears the parameter lock for the `rst` parameter if set.
112    pub fn plock_clear_rst(&self, trig_index: usize) -> Result<(), RytmError> {
113        if let Some(ref pool) = self.parameter_lock_pool {
114            let assigned_track = self.assigned_track.ok_or(OrphanTrig)?;
115            pool.lock().clear_basic_plock(
116                trig_index,
117                assigned_track as u8,
118                rytm_sys::AR_PLOCK_TYPE_MP6 as u8,
119            );
120            return Ok(());
121        }
122        Err(OrphanTrig)
123    }
124
125    #[parameter_range(range = "track_index[opt]:0..=11")]
126    pub(crate) fn from_raw_sound(
127        raw_sound: &ar_sound_t,
128        track_index: Option<usize>,
129    ) -> Result<Self, RytmError> {
130        unsafe {
131            Ok(Self {
132                parameter_lock_pool: None,
133                assigned_track: track_index,
134                lev: (from_s_u16_t(raw_sound.synth_param_1) >> 8) as u8,
135                tun: u8_to_i8_midpoint_of_u8_input_range(
136                    (from_s_u16_t(raw_sound.synth_param_2) >> 8) as u8,
137                    0,
138                    127,
139                ),
140                dec: (from_s_u16_t(raw_sound.synth_param_3) >> 8) as u8,
141                ton: u8_to_i8_midpoint_of_u8_input_range(
142                    (from_s_u16_t(raw_sound.synth_param_4) >> 8) as u8,
143                    0,
144                    127,
145                ),
146                trd: (from_s_u16_t(raw_sound.synth_param_5) >> 8) as u8,
147                rst: from_s_u16_t(raw_sound.synth_param_6) >> 8 != 0,
148            })
149        }
150    }
151}