rytm_rs/object/sound/machine/
hh_basic.rs1use 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 )]
27#[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 pub const fn get_rst(&self) -> bool {
71 self.rst
72 }
73
74 pub fn set_rst(&mut self, rst: bool) {
76 self.rst = rst;
77 }
78
79 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 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 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}