1use num_enum::{IntoPrimitive, TryFromPrimitive};
2
3use crate::{reader::*, Version, FIRMWARE_4_0_SONG_VERSION, FIRMWARE_6_0_SONG_VERSION, FIRMWARE_6_2_SONG_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.after(&FIRMWARE_6_0_SONG_VERSION) {
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.after(&FIRMWARE_6_2_SONG_VERSION) {
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#[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 Comb
187}
188
189#[derive(PartialEq, Debug, Clone)]
190pub struct OttConfiguration {
191 pub time: u8,
192 pub color: u8
193}
194
195impl OttConfiguration {
196 pub(crate) fn from_reader(reader: &mut Reader, _version: Version) -> M8Result<Self> {
197 Ok(Self {
198 time: reader.read(),
199 color: reader.read()
200 })
201 }
202}
203
204#[derive(PartialEq, Debug, Clone)]
205pub struct EffectsSettings {
206 pub mfx_kind : Option<FxKind>,
207 pub chorus_mod_depth: u8,
208 pub chorus_mod_freq: u8,
209 pub chorus_width: u8,
210 pub chorus_reverb_send: u8,
211
212 pub delay_filter: Option<EffectFilter>,
213 pub delay_time_l: u8,
214 pub delay_time_r: u8,
215 pub delay_feedback: u8,
216 pub delay_width: u8,
217 pub delay_reverb_send: u8,
218
219 pub reverb_filter: Option<EffectFilter>,
220 pub reverb_size: u8,
221 pub reverb_damping: u8,
222 pub reverb_mod_depth: u8,
223 pub reverb_mod_freq: u8,
224 pub reverb_width: u8,
225 pub reverb_shimmer: Option<u8>,
226 pub ott_configuration: Option<OttConfiguration>
227}
228
229impl EffectsSettings {
230 pub(crate) fn from_reader(reader: &mut Reader, version: Version) -> M8Result<Self> {
231 let chorus_mod_depth = reader.read();
232 let chorus_mod_freq = reader.read();
233 let chorus_width = reader.read();
234 let chorus_reverb_send = reader.read();
235 reader.read_bytes(3); let delay_filter= EffectFilter::from_reader(reader)?;
238 let delay_filter = if version.after(&FIRMWARE_4_0_SONG_VERSION) {
239 None
240 } else {
241 Some(delay_filter)
242 };
243
244 let delay_time_l = reader.read();
245 let delay_time_r = reader.read();
246 let delay_feedback = reader.read();
247 let delay_width = reader.read();
248 let delay_reverb_send = reader.read();
249 reader.read_bytes(1); let reverb_filter= EffectFilter::from_reader(reader)?;
252 let reverb_filter = if version.after(&FIRMWARE_4_0_SONG_VERSION) {
253 None
254 } else {
255 Some(reverb_filter)
256 };
257
258 let reverb_size = reader.read();
259 let reverb_damping = reader.read();
260 let reverb_mod_depth = reader.read();
261 let reverb_mod_freq = reader.read();
262 let reverb_width = reader.read();
263 let (reverb_shimmer, ott_configuration, mfx_kind) =
264 if version.after(&FIRMWARE_6_2_SONG_VERSION) {
265 let shimmer = Some(reader.read());
266 let ott = OttConfiguration::from_reader(reader, version)?;
267 let mfx = reader.read();
268 let kind =
269 mfx.try_into().map_err(| _| ParseError(format!("Unknown MFX kind {}", mfx)))?;
270 (shimmer, Some(ott), Some(kind))
271
272 } else {
273 (None, None, None)
274 };
275
276 Ok(Self {
277 mfx_kind,
278 chorus_mod_depth,
279 chorus_mod_freq,
280 chorus_width,
281 chorus_reverb_send,
282
283 delay_filter,
284 delay_time_l,
285 delay_time_r,
286 delay_feedback,
287 delay_width,
288 delay_reverb_send,
289
290 reverb_filter,
291 reverb_size,
292 reverb_damping,
293 reverb_mod_depth,
294 reverb_mod_freq,
295 reverb_width,
296 reverb_shimmer,
297 ott_configuration
298 })
299 }
300}
301
302#[derive(PartialEq, Debug, Clone)]
303pub struct MidiMapping {
304 pub channel: u8,
305 pub control_number: u8,
306 pub value: u8,
307 pub typ: u8,
308 pub param_index: u8,
309 pub min_value: u8,
310 pub max_value: u8,
311}
312
313impl MidiMapping {
314 pub(crate) fn from_reader(reader: &mut Reader) -> M8Result<Self> {
315 Ok(Self {
316 channel: reader.read(),
317 control_number: reader.read(),
318 value: reader.read(),
319 typ: reader.read(),
320 param_index: reader.read(),
321 min_value: reader.read(),
322 max_value: reader.read(),
323 })
324 }
325
326 pub fn empty(&self) -> bool {
327 self.channel == 0
328 }
329}