m8_file_parser/
settings.rs

1use num_enum::{IntoPrimitive, TryFromPrimitive};
2
3use crate::{reader::*, Version};
4
5#[derive(PartialEq, Debug, Clone)]
6pub struct MidiSettings {
7    pub receive_sync: bool,
8    pub receive_transport: u8,
9    pub send_sync: bool,
10    pub send_transport: u8,
11    pub record_note_channel: u8,
12    pub record_note_velocity: bool,
13    pub record_note_delay_kill_commands: u8,
14    pub control_map_channel: u8,
15    pub song_row_cue_channel: u8,
16    pub track_input_channel: [u8; 8],
17    pub track_input_intrument: [u8; 8],
18    pub track_input_program_change: bool,
19    pub track_input_mode: u8,
20}
21
22impl TryFrom<&mut Reader> for MidiSettings {
23    type Error = ParseError;
24
25    fn try_from(reader: &mut Reader) -> M8Result<Self> {
26        Ok(Self {
27            receive_sync: reader.read_bool(),
28            receive_transport: reader.read(),
29            send_sync: reader.read_bool(),
30            send_transport: reader.read(),
31            record_note_channel: reader.read(),
32            record_note_velocity: reader.read_bool(),
33            record_note_delay_kill_commands: reader.read(),
34            control_map_channel: reader.read(),
35            song_row_cue_channel: reader.read(),
36            track_input_channel: reader.read_bytes(8).try_into().unwrap(),
37            track_input_intrument: reader.read_bytes(8).try_into().unwrap(),
38            track_input_program_change: reader.read_bool(),
39            track_input_mode: reader.read(),
40        })
41    }
42}
43
44#[derive(PartialEq, Debug, Clone)]
45pub struct LimiterParameter {
46    pub level: u8,
47    pub attack_release: Option<(u8, u8, bool)>
48}
49
50#[derive(PartialEq, Debug, Clone)]
51pub struct MixerSettings {
52    pub master_volume: u8,
53    pub track_volume: [u8; 8],
54    pub chorus_volume: u8,
55    pub delay_volume: u8,
56    pub reverb_volume: u8,
57    pub analog_input: AnalogInputSettings,
58    pub usb_input: InputMixerSettings,
59    pub dj_filter: u8,
60    pub dj_peak: u8,
61    pub dj_filter_type: u8,
62    pub limiter: LimiterParameter,
63    pub ott_level: Option<u8>
64}
65
66impl MixerSettings {
67    pub(crate) fn from_reader(reader: &mut Reader, ver: Version) -> M8Result<Self> {
68        let master_volume = reader.read();
69        let master_limit = reader.read();
70        let track_volume: [u8; 8] = reader.read_bytes(8).try_into().unwrap();
71        let chorus_volume = reader.read();
72        let delay_volume = reader.read();
73        let reverb_volume = reader.read();
74        let analog_input_volume = (reader.read(), reader.read());
75        let usb_input_volume = reader.read();
76
77        let analog_input_l =
78            InputMixerSettings::from_reader(reader, analog_input_volume.0);
79        let analog_input_r =
80            InputMixerSettings::from_reader(reader, analog_input_volume.0);
81        let usb_input_chorus = reader.read();
82        let usb_input_delay = reader.read();
83        let usb_input_reverb = reader.read();
84
85        let analog_input = if analog_input_volume.1 == 255 {
86            AnalogInputSettings::Stereo(analog_input_l)
87        } else {
88            AnalogInputSettings::DualMono((analog_input_l, analog_input_r))
89        };
90        let usb_input = InputMixerSettings {
91            volume: usb_input_volume,
92            mfx: usb_input_chorus,
93            delay: usb_input_delay,
94            reverb: usb_input_reverb,
95        };
96
97        let dj_filter = reader.read();
98        let dj_peak = reader.read();
99        let dj_filter_type = reader.read();
100
101        let limiter_conf = if !ver.at_least(6, 0) {
102            None
103        } else {
104            let limiter_attack = reader.read();
105            let limiter_release = reader.read();
106            let soft_clip = reader.read();
107            Some((limiter_attack, limiter_release, soft_clip != 0))
108        };
109
110        let ott_level = if ver.at_least(6, 1) {
111            Some(reader.read())
112        } else {
113            None
114        };
115
116        Ok(Self {
117            master_volume,
118            track_volume,
119            chorus_volume,
120            delay_volume,
121            reverb_volume,
122            analog_input,
123            usb_input,
124            dj_filter,
125            dj_peak,
126            dj_filter_type,
127            limiter: LimiterParameter {
128                level: master_limit,
129                attack_release: limiter_conf 
130            },
131            ott_level
132        })
133    }
134}
135
136#[derive(PartialEq, Debug, Clone)]
137pub struct InputMixerSettings {
138    pub volume: u8,
139    pub mfx: u8,
140    pub delay: u8,
141    pub reverb: u8,
142}
143
144impl InputMixerSettings {
145    pub fn from_reader(reader: &mut Reader, volume: u8) -> Self {
146        let chorus = reader.read();
147        let delay = reader.read();
148        let reverb = reader.read();
149
150        Self {
151            volume, mfx: chorus, delay, reverb
152        }
153    }
154}
155
156#[derive(PartialEq, Debug, Clone)]
157pub enum AnalogInputSettings {
158    Stereo(InputMixerSettings),
159    DualMono((InputMixerSettings, InputMixerSettings)),
160}
161
162/// Effect filter configuration only used in old versions
163/// of the firmware before being replaced with EQ
164#[derive(PartialEq, Debug, Clone)]
165pub struct EffectFilter {
166    pub high_pass: u8,
167    pub low_pass: u8
168}
169
170impl EffectFilter {
171    fn from_reader(reader: &mut Reader) -> M8Result<Self> {
172        let high_pass = reader.read();
173        let low_pass = reader.read();
174        Ok(EffectFilter { high_pass, low_pass })
175    }
176}
177
178#[repr(u8)]
179#[allow(non_camel_case_types)]
180#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Copy, Clone, Default, Debug)]
181pub enum FxKind {
182    #[default]
183    Chorus,
184    Phaser,
185    Flanger
186}
187
188#[derive(PartialEq, Debug, Clone)]
189pub struct OttConfiguration {
190    pub time: u8,
191    pub color: u8
192}
193
194impl OttConfiguration {
195    pub(crate) fn from_reader(reader: &mut Reader, _version: Version) -> M8Result<Self> {
196        Ok(Self {
197            time: reader.read(),
198            color: reader.read()
199        })
200    }
201}
202
203#[derive(PartialEq, Debug, Clone)]
204pub struct EffectsSettings {
205    pub mfx_kind : Option<FxKind>,
206    pub chorus_mod_depth: u8,
207    pub chorus_mod_freq: u8,
208    pub chorus_width: u8,
209    pub chorus_reverb_send: u8,
210
211    pub delay_filter: Option<EffectFilter>,
212    pub delay_time_l: u8,
213    pub delay_time_r: u8,
214    pub delay_feedback: u8,
215    pub delay_width: u8,
216    pub delay_reverb_send: u8,
217
218    pub reverb_filter: Option<EffectFilter>,
219    pub reverb_size: u8,
220    pub reverb_damping: u8,
221    pub reverb_mod_depth: u8,
222    pub reverb_mod_freq: u8,
223    pub reverb_width: u8,
224    pub reverb_shimmer: Option<u8>,
225    pub ott_configuration: Option<OttConfiguration>
226}
227
228impl EffectsSettings {
229    pub(crate) fn from_reader(reader: &mut Reader, version: Version) -> M8Result<Self> {
230        let chorus_mod_depth = reader.read();
231        let chorus_mod_freq = reader.read();
232        let chorus_width = reader.read();
233        let chorus_reverb_send = reader.read();
234        reader.read_bytes(3); //unused
235
236        let delay_filter=  EffectFilter::from_reader(reader)?;
237        let delay_filter = if version.at_least(4, 0) {
238            None
239        } else {
240            Some(delay_filter)
241        };
242
243        let delay_time_l = reader.read();
244        let delay_time_r = reader.read();
245        let delay_feedback = reader.read();
246        let delay_width = reader.read();
247        let delay_reverb_send = reader.read();
248        reader.read_bytes(1); //unused
249
250        let reverb_filter= EffectFilter::from_reader(reader)?;
251        let reverb_filter = if version.at_least(4, 0) {
252            None
253        } else {
254            Some(reverb_filter)
255        };
256
257        let reverb_size = reader.read();
258        let reverb_damping = reader.read();
259        let reverb_mod_depth = reader.read();
260        let reverb_mod_freq = reader.read();
261        let reverb_width = reader.read();
262        let (reverb_shimmer, ott_configuration, mfx_kind) =
263            if version.at_least(6, 1) {
264                let shimmer = Some(reader.read());
265                let ott = OttConfiguration::from_reader(reader, version)?;
266                let mfx = reader.read();
267                let kind =
268                   mfx.try_into().map_err(| _| ParseError(format!("Unknown MFX kind {}", mfx)))?;
269                (shimmer, Some(ott), Some(kind))
270
271            } else {
272                (None, None, None)
273            };
274
275        Ok(Self {
276            mfx_kind,
277            chorus_mod_depth,
278            chorus_mod_freq,
279            chorus_width,
280            chorus_reverb_send,
281
282            delay_filter,
283            delay_time_l,
284            delay_time_r,
285            delay_feedback,
286            delay_width,
287            delay_reverb_send,
288
289            reverb_filter,
290            reverb_size,
291            reverb_damping,
292            reverb_mod_depth,
293            reverb_mod_freq,
294            reverb_width,
295            reverb_shimmer,
296            ott_configuration
297        })
298    }
299}
300
301#[derive(PartialEq, Debug, Clone)]
302pub struct MidiMapping {
303    pub channel: u8,
304    pub control_number: u8,
305    pub value: u8,
306    pub typ: u8,
307    pub param_index: u8,
308    pub min_value: u8,
309    pub max_value: u8,
310}
311
312impl MidiMapping {
313    pub(crate) fn from_reader(reader: &mut Reader) -> M8Result<Self> {
314        Ok(Self {
315            channel: reader.read(),
316            control_number: reader.read(),
317            value: reader.read(),
318            typ: reader.read(),
319            param_index: reader.read(),
320            min_value: reader.read(),
321            max_value: reader.read(),
322        })
323    }
324
325    pub fn empty(&self) -> bool {
326        self.channel == 0
327    }
328}