ksynth/k5000/
filter.rs

1//! Data model for the filter (DCF).
2//!
3
4use std::convert::TryFrom;
5use std::fmt;
6
7use num_enum::TryFromPrimitive;
8
9use crate::{
10    SystemExclusiveData,
11    ParseError
12};
13use crate::k5000::{
14    EnvelopeTime,
15    EnvelopeLevel,
16    ControlTime,
17    EnvelopeDepth,
18    Cutoff,
19    Resonance,
20    Level
21};
22use crate::k5000::control::VelocityCurve;
23
24/// Filter mode.
25#[derive(Debug, Eq, PartialEq, Copy, Clone, TryFromPrimitive)]
26#[repr(u8)]
27pub enum FilterMode {
28    LowPass = 0,
29    HighPass = 1,
30}
31
32impl fmt::Display for FilterMode {
33    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34        write!(f, "{}", match self {
35            FilterMode::LowPass => String::from("Low pass"),
36            FilterMode::HighPass => String::from("High pass"),
37        })
38    }
39}
40
41/// Filter envelope.
42#[derive(Debug)]
43pub struct Envelope {
44    pub attack_time: EnvelopeTime,
45    pub decay1_time: EnvelopeTime,
46    pub decay1_level: EnvelopeLevel,
47    pub decay2_time: EnvelopeTime,
48    pub decay2_level: EnvelopeLevel,
49    pub release_time: EnvelopeTime,
50}
51
52impl Envelope {
53    pub fn new() -> Envelope {
54        Envelope {
55            attack_time: EnvelopeTime::new(0),
56            decay1_time: EnvelopeTime::new(0),
57            decay1_level: EnvelopeLevel::new(0),
58            decay2_time: EnvelopeTime::new(0),
59            decay2_level: EnvelopeLevel::new(0),
60            release_time: EnvelopeTime::new(0),
61        }
62    }
63}
64
65impl Default for Envelope {
66    fn default() -> Self {
67        Envelope::new()
68    }
69}
70
71impl fmt::Display for Envelope {
72    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
73        write!(f, "A={} D1={}/{} D2={}/{} R={}",
74            self.attack_time, self.decay1_time, self.decay1_level,
75            self.decay2_time, self.decay2_level, self.release_time
76        )
77    }
78}
79
80impl SystemExclusiveData for Envelope {
81    fn from_bytes(data: &[u8]) -> Result<Self, ParseError> {
82        Ok(Envelope {
83            attack_time: EnvelopeTime::from(data[0]),
84            decay1_time: EnvelopeTime::from(data[1]),
85            decay1_level: EnvelopeLevel::from(data[2]),
86            decay2_time: EnvelopeTime::from(data[3]),
87            decay2_level: EnvelopeLevel::from(data[4]),
88            release_time: EnvelopeTime::from(data[5]),
89        })
90    }
91
92    fn to_bytes(&self) -> Vec<u8> {
93        vec![
94            self.attack_time.into(),
95            self.decay1_time.into(),
96            self.decay1_level.into(),
97            self.decay2_time.into(),
98            self.decay2_level.into(),
99            self.release_time.into(),
100        ]
101    }
102
103    fn data_size() -> usize { 6 }
104}
105
106/// Filter key scaling control.
107#[derive(Debug)]
108pub struct KeyScalingControl {
109    pub attack_time: ControlTime,
110    pub decay1_time: ControlTime,
111}
112
113impl Default for KeyScalingControl {
114    fn default() -> Self {
115        KeyScalingControl {
116            attack_time: ControlTime::new(0),
117            decay1_time: ControlTime::new(0),
118        }
119    }
120}
121
122impl fmt::Display for KeyScalingControl {
123    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
124        write!(f, "Atk={} Dcy1={}", self.attack_time, self.decay1_time)
125    }
126}
127
128impl SystemExclusiveData for KeyScalingControl {
129    fn from_bytes(data: &[u8]) -> Result<Self, ParseError> {
130        Ok(KeyScalingControl {
131            attack_time: ControlTime::from(data[0]),
132            decay1_time: ControlTime::from(data[1]),
133        })
134    }
135
136    fn to_bytes(&self) -> Vec<u8> {
137        vec![
138            self.attack_time.into(),
139            self.decay1_time.into(),
140        ]
141    }
142
143    fn data_size() -> usize { 2 }
144}
145
146/// Filter velocity control.
147#[derive(Debug)]
148pub struct VelocityControl {
149    pub depth: EnvelopeDepth,
150    pub attack_time: ControlTime,
151    pub decay1_time: ControlTime,
152}
153
154impl Default for VelocityControl {
155    fn default() -> Self {
156        VelocityControl {
157            depth: EnvelopeDepth::new(0),
158            attack_time: ControlTime::new(0),
159            decay1_time: ControlTime::new(0),
160        }
161    }
162}
163
164impl fmt::Display for VelocityControl {
165    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
166        write!(f, "Depth={} Atk={} Dcy1={}",
167            self.depth, self.attack_time, self.decay1_time)
168    }
169}
170
171impl SystemExclusiveData for VelocityControl {
172    fn from_bytes(data: &[u8]) -> Result<Self, ParseError> {
173        Ok(VelocityControl {
174            depth: EnvelopeDepth::from(data[0]),
175            attack_time: ControlTime::from(data[1]),
176            decay1_time: ControlTime::from(data[2]),
177        })
178    }
179
180    fn to_bytes(&self) -> Vec<u8> {
181        vec![
182            self.depth.into(),
183            self.attack_time.into(),
184            self.decay1_time.into(),
185        ]
186    }
187
188    fn data_size() -> usize { 3 }
189}
190
191/// Modulation settings for the filter.
192#[derive(Default, Debug)]
193pub struct Modulation {
194    pub ks_to_env: KeyScalingControl,
195    pub vel_to_env: VelocityControl,
196}
197
198impl fmt::Display for Modulation {
199    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200        write!(f, "KS->Env={} Vel->Env={}", self.ks_to_env, self.vel_to_env)
201    }
202}
203
204impl SystemExclusiveData for Modulation {
205    fn from_bytes(data: &[u8]) -> Result<Self, ParseError> {
206        Ok(Modulation {
207            ks_to_env: KeyScalingControl::from_bytes(&data[..2])?,
208            vel_to_env: VelocityControl::from_bytes(&data[2..5])?,
209        })
210    }
211
212    fn to_bytes(&self) -> Vec<u8> {
213        let mut result: Vec<u8> = Vec::new();
214
215        result.extend(self.ks_to_env.to_bytes());
216        result.extend(self.vel_to_env.to_bytes());
217
218        result
219    }
220
221    fn data_size() -> usize {
222        KeyScalingControl::data_size() + VelocityControl::data_size()
223    }
224}
225
226
227/// Filter settings.
228#[derive(Debug)]
229pub struct Filter {
230    pub is_active: bool,
231    pub mode: FilterMode,
232    pub velocity_curve: VelocityCurve,
233    pub resonance: Resonance,
234    pub level: Level,
235    pub cutoff: Cutoff,
236    pub ks_to_cutoff: EnvelopeDepth,
237    pub vel_to_cutoff: EnvelopeDepth,
238    pub envelope_depth: EnvelopeDepth,
239    pub envelope: Envelope,
240    pub modulation: Modulation,
241}
242
243impl Filter {
244    pub fn new() -> Filter {
245        Filter {
246            is_active: true,
247            cutoff: Cutoff::new(0),
248            resonance: Resonance::new(0),
249            mode: FilterMode::LowPass,
250            velocity_curve: VelocityCurve::Curve1,
251            level: Level::new(0),
252            ks_to_cutoff: EnvelopeDepth::new(0),
253            vel_to_cutoff: EnvelopeDepth::new(0),
254            envelope_depth: EnvelopeDepth::new(0),
255            envelope: Envelope::new(),
256            modulation: Modulation::default()
257        }
258    }
259}
260
261impl Default for Filter {
262    fn default() -> Self {
263        Filter::new()
264    }
265}
266
267impl fmt::Display for Filter {
268    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
269        write!(f, "Active={} Cutoff={} Resonance={} Mode={}\nVel Curve={} Level=0{}\nKS to Cutoff={} Vel. to Cutoff={} Env Depth={}\nEnvelope: {}\nModulation: {}",
270            self.is_active, self.cutoff, self.resonance,
271            self.mode, self.velocity_curve, self.level,
272            self.ks_to_cutoff, self.vel_to_cutoff, self.envelope_depth,
273            self.envelope, self.modulation
274        )
275    }
276}
277
278impl SystemExclusiveData for Filter {
279    fn from_bytes(data: &[u8]) -> Result<Self, ParseError> {
280        Ok(Filter {
281            is_active: data[0] != 1,  // value of 1 means filter is bypassed
282            mode: FilterMode::try_from(data[1]).unwrap(),
283            velocity_curve: VelocityCurve::try_from(data[2]).unwrap(),  // from 0 ~ 11 to enum
284            resonance: Resonance::from(data[3]),
285            level: Level::from(data[4]),
286            cutoff: Cutoff::from(data[5]),
287            ks_to_cutoff: EnvelopeDepth::from(data[6]),
288            vel_to_cutoff: EnvelopeDepth::from(data[7]),
289            envelope_depth: EnvelopeDepth::from(data[8]),
290            envelope: Envelope::from_bytes(&data[9..15])?,
291            modulation: Modulation::from_bytes(&data[15..20])?,
292        })
293    }
294
295    fn to_bytes(&self) -> Vec<u8> {
296        let mut result: Vec<u8> = Vec::new();
297
298        let bs = vec![
299            if self.is_active { 0 } else { 1 },  // is this the right way around?
300            self.mode as u8,
301            self.velocity_curve as u8,  // raw enum values map to 0~11
302            self.resonance.into(),
303            self.level.into(),
304            self.cutoff.into(),
305            self.ks_to_cutoff.into(),
306            self.vel_to_cutoff.into(),
307            self.envelope_depth.into(),
308        ];
309        result.extend(bs);
310        result.extend(self.envelope.to_bytes());
311        result.extend(self.modulation.to_bytes());
312
313        result
314    }
315
316    fn data_size() -> usize {
317        9
318        + Envelope::data_size()
319        + Modulation::data_size()
320    }
321}