1use core::fmt;
12
13pub const TIMBRE_PARAM_SIZE: usize = 246;
15
16pub const COMMON_PARAM_SIZE: usize = 14;
18
19pub const PARTIAL_PARAM_SIZE: usize = 58;
21
22pub const MELODIC_PARTS_COUNT: usize = 8;
24
25pub const RHYTHM_KEYS_COUNT: usize = 85;
27
28#[derive(Default, Copy, Clone, PartialEq, Eq)]
30pub enum PartialType {
31 #[default]
33 Oscillator,
34 Pcm,
36}
37
38impl fmt::Debug for PartialType {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 match self {
42 PartialType::Oscillator => write!(f, "PartialType::Oscillator"),
43 PartialType::Pcm => write!(f, "PartialType::Pcm"),
44 }
45 }
46}
47
48#[derive(Default, Copy, Clone, PartialEq, Eq)]
50pub enum PairMode {
51 #[default]
53 Mix,
54 RingPlusTop,
56 RingOnly,
58 Stereo,
60}
61
62impl fmt::Debug for PairMode {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 match self {
66 PairMode::Mix => write!(f, "PairMode::Mix"),
67 PairMode::RingPlusTop => write!(f, "PairMode::RingPlusTop"),
68 PairMode::RingOnly => write!(f, "PairMode::RingOnly"),
69 PairMode::Stereo => write!(f, "PairMode::Stereo"),
70 }
71 }
72}
73
74use PairMode::{Mix, RingOnly, RingPlusTop, Stereo};
75use PartialType::{Oscillator, Pcm};
76
77pub const PAIR_STRUCTURES: [(PartialType, PartialType, PairMode); 13] = [
79 (Oscillator, Oscillator, Mix), (Oscillator, Oscillator, RingPlusTop), (Pcm, Oscillator, Mix), (Pcm, Oscillator, RingPlusTop), (Oscillator, Pcm, RingPlusTop), (Pcm, Pcm, Mix), (Pcm, Pcm, RingPlusTop), (Oscillator, Oscillator, Stereo), (Pcm, Pcm, Stereo), (Oscillator, Oscillator, RingOnly), (Pcm, Oscillator, RingOnly), (Oscillator, Pcm, RingOnly), (Pcm, Pcm, RingOnly), ];
93
94#[derive(Debug, Copy, Clone)]
95#[repr(C, packed)]
96pub(crate) struct RawTvpParam {
97 pub depth: u8,
98 pub velo_sensitivity: u8,
99 pub time_keyfollow: u8,
100 pub time: [u8; 4],
101 pub level: [u8; 5],
102}
103
104#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
106pub struct TvpParam {
107 pub depth: i32,
108 pub velo_sensitivity: i32,
109 pub time_keyfollow: i32,
110 pub time: [i32; 4],
111 pub level: [i32; 5],
112}
113
114impl From<&RawTvpParam> for TvpParam {
115 fn from(raw: &RawTvpParam) -> Self {
116 Self {
117 depth: raw.depth.min(10) as i32,
118 velo_sensitivity: raw.velo_sensitivity.min(3) as i32,
119 time_keyfollow: raw.time_keyfollow.min(4) as i32,
120 time: [
121 raw.time[0].min(100) as i32,
122 raw.time[1].min(100) as i32,
123 raw.time[2].min(100) as i32,
124 raw.time[3].min(100) as i32,
125 ],
126 level: [
127 raw.level[0].min(100) as i32 - 50,
128 raw.level[1].min(100) as i32 - 50,
129 raw.level[2].min(100) as i32 - 50,
130 raw.level[3].min(100) as i32 - 50,
131 raw.level[4].min(100) as i32 - 50,
132 ],
133 }
134 }
135}
136
137#[derive(Debug, Copy, Clone)]
138#[repr(C, packed)]
139pub(crate) struct RawTvfParam {
140 pub cutoff: u8,
141 pub resonance: u8,
142 pub keyfollow: u8,
143 pub bias_point: u8,
144 pub bias_level: u8,
145 pub env_depth: u8,
146 pub env_velo_sensitivity: u8,
147 pub env_depth_keyfollow: u8,
148 pub env_time_keyfollow: u8,
149 pub env_time: [u8; 5],
150 pub env_level: [u8; 4],
151}
152
153#[derive(Debug, Copy, Clone, PartialEq, Eq)]
155pub struct TvfParam {
156 pub cutoff: i32,
157 pub resonance: i32,
158 pub keyfollow: usize,
159 pub bias_point: i32,
160 pub bias_level: usize,
161 pub env_depth: i32,
162 pub env_velo_sensitivity: i32,
163 pub env_depth_keyfollow: i32,
164 pub env_time_keyfollow: i32,
165 pub env_time: [i32; 5],
166 pub env_level: [u8; 4],
167}
168
169impl Default for TvfParam {
170 fn default() -> Self {
171 Self {
172 cutoff: 0,
173 resonance: 0,
174 keyfollow: 0,
175 bias_point: 0,
176 bias_level: 0,
177 env_depth: 0,
178 env_velo_sensitivity: 0,
179 env_depth_keyfollow: 0,
180 env_time_keyfollow: 0,
181 env_time: [0; 5],
182 env_level: [100; 4],
183 }
184 }
185}
186
187impl From<&RawTvfParam> for TvfParam {
188 fn from(raw: &RawTvfParam) -> Self {
189 Self {
190 cutoff: raw.cutoff.min(100) as i32,
191 resonance: raw.resonance.min(30) as i32,
192 keyfollow: raw.keyfollow.min(16) as usize,
193 bias_point: (raw.bias_point & 0x7F) as i32,
194 bias_level: raw.bias_level.min(14) as usize,
195 env_depth: raw.env_depth.min(100) as i32,
196 env_velo_sensitivity: raw.env_velo_sensitivity.min(100) as i32,
197 env_depth_keyfollow: raw.env_depth_keyfollow.min(4) as i32,
198 env_time_keyfollow: raw.env_time_keyfollow.min(4) as i32,
199 env_time: [
200 raw.env_time[0].min(100) as i32,
201 raw.env_time[1].min(100) as i32,
202 raw.env_time[2].min(100) as i32,
203 raw.env_time[3].min(100) as i32,
204 raw.env_time[4].min(100) as i32,
205 ],
206 env_level: [
207 raw.env_level[0].min(100),
208 raw.env_level[1].min(100),
209 raw.env_level[2].min(100),
210 raw.env_level[3].min(100),
211 ],
212 }
213 }
214}
215
216#[derive(Debug, Copy, Clone)]
217#[repr(C, packed)]
218pub(crate) struct RawTvaParam {
219 pub level: u8,
220 pub velo_sensitivity: u8,
221 pub bias_point_1: u8,
222 pub bias_level_1: u8,
223 pub bias_point_2: u8,
224 pub bias_level_2: u8,
225 pub env_time_keyfollow: u8,
226 pub env_time_velo_sensitivity: u8,
227 pub env_time: [u8; 5],
228 pub env_level: [u8; 4],
229}
230
231#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
233pub struct TvaParam {
234 pub level: usize,
235 pub velo_sensitivity: i32,
236 pub bias_point_1: i32,
237 pub bias_level_1: usize,
238 pub bias_point_2: i32,
239 pub bias_level_2: usize,
240 pub env_time_keyfollow: i32,
241 pub env_time_velo_sensitivity: i32,
242 pub env_time: [i32; 5],
243 pub env_level: [u8; 4],
244}
245
246impl From<&RawTvaParam> for TvaParam {
247 fn from(raw: &RawTvaParam) -> Self {
248 Self {
249 level: raw.level.min(100) as usize,
250 velo_sensitivity: raw.velo_sensitivity.min(100) as i32,
251 bias_point_1: (raw.bias_point_1 & 0x7F) as i32,
252 bias_level_1: raw.bias_level_1.min(12) as usize,
253 bias_point_2: (raw.bias_point_2 & 0x7F) as i32,
254 bias_level_2: raw.bias_level_2.min(12) as usize,
255 env_time_keyfollow: raw.env_time_keyfollow.min(4) as i32,
256 env_time_velo_sensitivity: raw.env_time_velo_sensitivity.min(4)
257 as i32,
258 env_time: [
259 raw.env_time[0].min(100) as i32,
260 raw.env_time[1].min(100) as i32,
261 raw.env_time[2].min(100) as i32,
262 raw.env_time[3].min(100) as i32,
263 raw.env_time[4].min(100) as i32,
264 ],
265 env_level: [
266 raw.env_level[0].min(100),
267 raw.env_level[1].min(100),
268 raw.env_level[2].min(100),
269 raw.env_level[3].min(100),
270 ],
271 }
272 }
273}
274
275#[derive(Debug, Copy, Clone)]
276#[repr(C, packed)]
277pub(crate) struct RawPartialParam {
278 pub wg_pitch_coarse: u8,
279 pub wg_pitch_fine: u8,
280 pub wg_pitch_keyfollow: u8,
281 pub wg_pitch_bender_enabled: u8,
282 pub wg_waveform: u8,
283 pub wg_pcm_wave: u8,
284 pub wg_pulse_width: u8,
285 pub wg_pw_velo_sensitivity: u8,
286 pub tvp: RawTvpParam,
287 pub pitch_lfo_rate: u8,
288 pub pitch_lfo_depth: u8,
289 pub pitch_lfo_mod_sensitivity: u8,
290 pub tvf: RawTvfParam,
291 pub tva: RawTvaParam,
292}
293
294#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
296pub struct PartialParam {
297 pub wg_pitch_coarse_offset: i32,
298 pub wg_pitch_fine_offset: i32,
299 pub wg_pitch_keyfollow: usize,
300 pub wg_pitch_bender_enabled: bool,
301 pub wg_waveform: usize,
302 pub wg_pcm_wave: usize,
303 pub wg_pulse_width: usize,
304 pub wg_pw_velo_sensitivity: i32,
305 pub tvp: TvpParam,
306 pub pitch_lfo_rate: u8,
307 pub pitch_lfo_depth: u8,
308 pub pitch_lfo_mod_sensitivity: u8,
309 pub tvf: TvfParam,
310 pub tva: TvaParam,
311}
312
313impl From<&RawPartialParam> for PartialParam {
314 fn from(raw: &RawPartialParam) -> Self {
315 let mut pcm_wave = (raw.wg_pcm_wave & 0x7F) as usize;
316 let waveform = raw.wg_waveform.min(2) as usize;
317 if waveform > 1 {
318 pcm_wave += 128;
319 }
320
321 let coarse = raw.wg_pitch_coarse.min(108) as i32;
322 let coarse_offset = (coarse - 36) * 4096 / 12;
323
324 let fine = raw.wg_pitch_fine.min(100) as i32;
325 let fine_offset = (fine - 50) * 4096 / 1200;
326
327 let keyfollow = raw.wg_pitch_keyfollow.min(16) as usize;
328 let pulse_width = raw.wg_pulse_width.min(100) as usize;
329 let pw_velo_sensitivity = raw.wg_pw_velo_sensitivity.min(14) as i32;
330
331 Self {
332 wg_pitch_coarse_offset: coarse_offset,
333 wg_pitch_fine_offset: fine_offset,
334 wg_pitch_keyfollow: keyfollow,
335 wg_pitch_bender_enabled: (raw.wg_pitch_bender_enabled & 1) != 0,
336 wg_waveform: waveform,
337 wg_pcm_wave: pcm_wave,
338 wg_pulse_width: pulse_width,
339 wg_pw_velo_sensitivity: pw_velo_sensitivity,
340 tvp: TvpParam::from(&raw.tvp),
341 pitch_lfo_rate: raw.pitch_lfo_rate.min(100),
342 pitch_lfo_depth: raw.pitch_lfo_depth.min(100),
343 pitch_lfo_mod_sensitivity: raw.pitch_lfo_mod_sensitivity.min(100),
344 tvf: TvfParam::from(&raw.tvf),
345 tva: TvaParam::from(&raw.tva),
346 }
347 }
348}
349
350#[derive(Debug, Copy, Clone)]
351#[repr(C, packed)]
352pub(crate) struct RawTimbreParam {
353 pub name: [u8; 10],
354 pub partial_structure_12: u8,
355 pub partial_structure_34: u8,
356 pub partial_mute: u8,
357 pub no_sustain: u8,
358 pub partials: [RawPartialParam; 4],
359}
360
361#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
363pub struct TimbreParam {
364 pub partial_types: [PartialType; 4],
365 pub pair_modes: [PairMode; 2],
366 pub partial_mute: u8,
367 pub no_sustain: bool,
368 pub partials: [PartialParam; 4],
369}
370
371impl From<&RawTimbreParam> for TimbreParam {
372 fn from(raw: &RawTimbreParam) -> Self {
373 let idx12 = raw.partial_structure_12.min(12) as usize;
374 let idx34 = raw.partial_structure_34.min(12) as usize;
375 let (type0, type1, mode12) = PAIR_STRUCTURES[idx12];
376 let (type2, type3, mode34) = PAIR_STRUCTURES[idx34];
377
378 TimbreParam {
379 partial_types: [type0, type1, type2, type3],
380 pair_modes: [mode12, mode34],
381 partial_mute: raw.partial_mute,
382 no_sustain: raw.no_sustain != 0,
383 partials: [
384 PartialParam::from(&raw.partials[0]),
385 PartialParam::from(&raw.partials[1]),
386 PartialParam::from(&raw.partials[2]),
387 PartialParam::from(&raw.partials[3]),
388 ],
389 }
390 }
391}
392
393#[derive(Debug, Copy, Clone)]
394#[repr(C, packed)]
395pub(crate) struct RawRhythmKey {
396 pub timbre: u8,
397 pub level: u8,
398 pub panpot: u8,
399 pub reverb: u8,
400}
401
402#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
404pub struct RhythmKey {
405 pub timbre: usize,
406 pub level: usize,
407 pub panpot: i32,
408 pub reverb: bool,
409}
410
411impl From<&RawRhythmKey> for RhythmKey {
412 fn from(raw: &RawRhythmKey) -> Self {
414 let timbre = (raw.timbre & 0x7F) as usize;
415 let level = raw.level.min(100) as usize;
416 let panpot = raw.panpot.min(14) as i32;
417 let reverb = (raw.reverb & 1) != 0;
418
419 RhythmKey {
420 timbre,
421 level,
422 panpot,
423 reverb,
424 }
425 }
426}
427
428#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
430pub struct PatchParam {
431 pub timbre_group: u8,
432 pub timbre_num: u8,
433 pub key_shift: i32,
434 pub fine_tune: i32,
435 pub bender_range: u8,
436 pub assign_mode: u8,
437 pub reverb_switch: bool,
438}
439
440#[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
442pub struct PatchTemp {
443 pub patch: PatchParam,
444 pub output_level: usize,
445 pub panpot: i32,
446}
447
448#[derive(Debug, Copy, Clone)]
449#[repr(C, packed)]
450pub(crate) struct RawPatchParam {
451 pub timbre_group: u8,
452 pub timbre_num: u8,
453 pub key_shift: u8,
454 pub fine_tune: u8,
455 pub bender_range: u8,
456 pub assign_mode: u8,
457 pub reverb_switch: u8,
458 pub dummy: u8,
459}
460
461impl From<&RawPatchParam> for PatchParam {
462 fn from(raw: &RawPatchParam) -> Self {
463 PatchParam {
464 timbre_group: raw.timbre_group.min(3),
465 timbre_num: raw.timbre_num.min(63),
466 key_shift: raw.key_shift.min(48) as i32,
467 fine_tune: raw.fine_tune.min(100) as i32,
468 bender_range: raw.bender_range.min(24),
469 assign_mode: raw.assign_mode.min(3),
470 reverb_switch: raw.reverb_switch != 0,
471 }
472 }
473}
474
475#[derive(Debug, Copy, Clone)]
476#[repr(C, packed)]
477pub(crate) struct RawPatchTemp {
478 pub patch: RawPatchParam,
479 pub output_level: u8,
480 pub panpot: u8,
481 pub dummy: [u8; 6],
482}
483
484impl From<&RawPatchTemp> for PatchTemp {
485 fn from(raw: &RawPatchTemp) -> Self {
486 PatchTemp {
487 patch: PatchParam::from(&raw.patch),
488 output_level: raw.output_level.min(100) as usize,
489 panpot: raw.panpot.min(14) as i32,
490 }
491 }
492}
493
494#[derive(Debug, Copy, Clone)]
495#[repr(C, packed)]
496pub(crate) struct RawRhythmTemp {
497 pub timbre: u8,
498 pub level: u8,
499 pub panpot: u8,
500 pub reverb_switch: u8,
501}
502
503impl From<&RawRhythmTemp> for RhythmKey {
504 fn from(raw: &RawRhythmTemp) -> Self {
505 RhythmKey {
506 timbre: (raw.timbre & 0x7F) as usize,
507 level: raw.level.min(100) as usize,
508 panpot: raw.panpot.min(14) as i32,
509 reverb: raw.reverb_switch != 0,
510 }
511 }
512}
513
514pub(crate) fn cast_raw_timbre(
515 raw: &[u8; TIMBRE_PARAM_SIZE],
516) -> &RawTimbreParam {
517 unsafe { &*(raw.as_ptr() as *const RawTimbreParam) }
518}