1use std::convert::TryFrom;
19use std::fmt::{Debug, Display, Formatter};
20use std::fs::File;
21use std::io::{BufReader, Error, ErrorKind};
22use std::path::Path;
23use std::str::FromStr;
24
25use log::warn;
26use serde::{Deserialize, Serialize};
27use serde_xml_rs::de::from_reader;
28use strum::IntoEnumIterator;
29use strum_macros::{AsRefStr, EnumIter};
30use uom::num::Zero;
31use uom::si::f64::{Ratio, Time};
32use uom::si::ratio::percent;
33use uom::si::time::{millisecond, second};
34
35pub use effect::*;
36
37mod effect;
38
39const MODULATION_MATRIX_SIZE: usize = 8;
40
41const PRESET_INFO_DEFAULT: &str = "Preset Info";
43
44#[derive(Clone, Debug, PartialEq)]
46pub struct Envelope {
47 pub attack: Time,
48
49 #[doc(alias = "attack_slope")]
50 pub attack_curve: f64,
51
52 pub decay: Time,
53
54 #[doc(alias = "decay_slope")]
55 pub decay_falloff: f64,
56
57 pub sustain: Ratio,
59
60 pub release: Time,
61
62 #[doc(alias = "release_slope")]
63 pub release_falloff: f64,
64}
65
66#[derive(Debug)]
67pub enum EnvelopeCurve {
68 Linear,
69 Exponential1,
70 Exponential2,
71 Exponential3,
72 Exponential4,
73 Logarithmic1,
74 Logarithmic2,
75 Pluck1,
76 Pluck2,
77 Pluck3,
78
79 DoubleCurve1,
81
82 DoubleCurve2,
84}
85
86impl EnvelopeCurve {
87 pub fn value(self) -> f64 {
88 use EnvelopeCurve::*;
89 match self {
90 Linear => 0.000,
91 Exponential1 => 0.070,
92 Exponential2 => 0.133,
93 Exponential3 => 0.200,
94 Exponential4 => 0.267,
95 Logarithmic1 => 0.333,
96 Logarithmic2 => 0.400,
97 Pluck1 => 0.467,
98 Pluck2 => 0.533,
99 Pluck3 => 0.600,
100 DoubleCurve1 => 0.667,
101 DoubleCurve2 => 0.733,
102 }
103 }
104}
105
106impl Display for EnvelopeCurve {
107 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
108 use EnvelopeCurve::*;
109 write!(
110 f,
111 "{}",
112 match self {
113 Linear => "Linear",
114 Exponential1 => "Exponential 1",
115 Exponential2 => "Exponential 2",
116 Exponential3 => "Exponential 3",
117 Exponential4 => "Exponential 4",
118 Logarithmic1 => "Logarithmic 1",
119 Logarithmic2 => "Logarithmic 2",
120 Pluck1 => "Pluck 1",
121 Pluck2 => "Pluck 2",
122 Pluck3 => "Pluck 3",
123 DoubleCurve1 => "Double Curve 1: Exp > Log",
124 DoubleCurve2 => "Double Curve 2: Log > Exp",
125 }
126 )
127 }
128}
129
130#[derive(Debug)]
131pub struct Lfo {
132 pub enabled: bool,
133 pub waveform: Waveform,
134 pub sync: bool,
135 pub invert: bool,
136 pub reverse: bool,
137 pub mono: bool,
138 pub free_run: bool,
139 pub frequency: f64,
140 pub phase: f64,
141}
142
143#[derive(Debug)]
144pub struct MatrixItem {
145 pub source: u32,
146 pub target: u32,
147 pub amount: f64,
148}
149
150#[derive(Debug)]
152pub struct Noise {
153 pub enabled: bool,
154 pub width: f64,
155 pub pan: f64,
156 pub volume: f64,
157}
158
159impl Effect for Noise {}
160
161#[derive(Debug)]
164pub struct Oscillator {
165 pub enabled: bool,
166 pub waveform: Waveform,
167 pub invert: bool,
168 pub pan: f64,
169 pub phase: f64,
170
171 pub pitch: f64,
172 pub fine_tuning: i32,
173 pub semitone_tuning: i32,
174 pub octave_tuning: i32,
175
176 pub reverse: bool,
177 pub free_run: bool,
178 pub sync_all: bool,
179 pub volume: f64,
180 pub unison: Unison,
181
182 pub am_enabled: bool,
184 pub am_amount: f64,
185
186 pub fm_enabled: bool,
188 pub fm_amount: f64,
189
190 pub rm_enabled: bool,
192 pub rm_amount: f64,
193}
194
195#[derive(Copy, Clone, Debug, EnumIter, Eq, PartialEq)]
197#[repr(u32)]
198pub enum MidiPlayMode {
199 Normal,
200
201 Cheat1,
203
204 Cheat2,
206}
207
208impl MidiPlayMode {
209 fn from_or(mode_id: u32, default: MidiPlayMode) -> MidiPlayMode {
210 MidiPlayMode::iter()
211 .find(|id| *id as u32 == mode_id)
212 .unwrap_or(default)
213 }
214}
215
216#[derive(Debug)]
217pub struct ModulatorEnvelope {
218 pub enabled: bool,
219 pub envelope: Envelope,
220 pub curve: f64,
221}
222
223#[derive(Copy, Clone, Debug, EnumIter, Eq, PartialEq)]
225#[repr(u32)]
226pub enum PortamentoMode {
227 Poly,
228 Legato,
229 LegatoNoRetrigger,
230 Porta,
231 PortaPoly,
232}
233
234impl PortamentoMode {
235 fn from_or(mode_id: u32, default: PortamentoMode) -> PortamentoMode {
236 PortamentoMode::iter()
237 .find(|id| *id as u32 == mode_id)
238 .unwrap_or(default)
239 }
240}
241
242#[derive(Debug)]
243pub struct Tuning {
244 pub transpose: f64,
245 pub root_key: u32,
246 pub scale: u32,
247
248 pub tunings: [f64; 12],
250}
251
252#[derive(Debug)]
253pub struct Vibrato {
254 pub enabled: bool,
255 pub attack: f64,
256 pub delay: f64,
257 pub frequency: f64,
258}
259
260#[derive(Debug)]
261pub struct Unison {
262 pub voices: u32,
264 pub detune: f64,
265 pub spread: f64,
266 pub mix: f64,
267}
268
269#[derive(AsRefStr, Copy, Clone, Debug, EnumIter, Eq, PartialEq)]
271#[repr(u32)]
272pub enum Waveform {
273 Sine,
274 SineRoot1_5,
275 SineRoot2,
276 SineRoot3,
277 SineRoot4,
278 SinePower1_5,
279 SinePower2,
280 SinePower3,
281 SinePower4,
282 SineAm1,
283 SineAm2,
284 SineAm3,
285 SineAm4,
286 SineAm5,
287 SineFmA1,
288 SineFmA2,
289 SineFmA3,
290 SineFmA4,
291 SineFmA5,
292 SineFmA6,
293 SineFmB1,
294 SineFmB2,
295 SineFmB3,
296 SineFmB4,
297 SineFmB5,
298 SineFmC1,
299 SineFmC2,
300 SineFmC3,
301 SineFmC4,
302 SineFmC5,
303 SineFmC6,
304 SineFmC7,
305 SineFmC8,
306 SineFmD1,
307 SineFmD2,
308 SineFmD3,
309 SineFmD4,
310 SineFmD5,
311 SineFmD6,
312 SineFmD7,
313 SineFmD8,
314 SineFmD9,
315 SineFmD10,
316 SineFmD11,
317 SineFmD12,
318 SineFmD13,
319 SineFmD14,
320 SineFmD15,
321 SineFmKick1,
322 SineFmKick2,
323 SineFmKick3,
324 SineFmKick4,
325 SineFmKick5,
326 SineFmKick6,
327 SineFmKick7,
328 SineFmKick8,
329 SineFmKick9,
330 SineFmKick10,
331 SineFmKick11,
332 SineFmKick12,
333
334 Triangle,
335 TriangleRoot2,
336 TriangleRoot3,
337 TriangleRoot4,
338 TriangleRoot5,
339
340 Saw,
341 SawPower1,
342 SawPower2,
343 SawSine1,
344 SawSine2,
345 SawSine3,
346 Saw2x,
347
348 Square,
349 SquareSmooth1,
350 SquareSmooth2,
351 SquareHalfRoot,
352 SquareHalfRootPower,
353 SquarePower,
354 SquareDoublePower1,
355 SquareDoublePower2,
356 SquareAttackPower,
357 SquareTristate1,
358 SquareTristate2,
359 SquareTristate3,
360 SquareTristate4,
361 SquareTristate5,
362 SquareTristate6,
363 SquareFm1,
364 SquareFm2,
365 SquareFm3,
366 SquareFm4,
367 SquareFm5,
368 SquareFm6,
369 SquareFm7,
370 SquareFm8,
371
372 Pulse1,
373 Pulse2,
374 Pulse3,
375 Pulse4,
376 PulseSquare,
377 PulseSquareSmooth,
378 PulseSmooth1,
379 PulseSmooth2,
380
381 Voice1,
382 Voice2,
383 Voice3,
384 Voice4,
385 Voice5,
386 Voice6,
387 Voice7,
388 Voice8,
389 Voice9,
390 Voice10,
391 Voice11,
392 Voice12,
393 Voice13,
394 Voice14,
395 Voice15,
396 Voice16,
397 Voice17,
398 Voice18,
399 Voice19,
400 Voice20,
401 Voice21,
402 Voice22,
403 Voice23,
404 Voice24,
405 Voice25,
406 Voice26,
407 Voice27,
408 Voice28,
409 Voice29,
410 Voice30,
411
412 FormantA1,
413 FormantA2,
414 FormantA3,
415 FormantA4,
416 FormantA5,
417 FormantA6,
418 FormantA7,
419 FormantA8,
420 FormantB1,
421 FormantB2,
422 FormantB3,
423 FormantB4,
424 FormantB5,
425 FormantB6,
426 FormantB7,
427 FormantB8,
428
429 SyntheticVoice1,
430 SyntheticVoice2,
431 SyntheticVoice3,
432 SyntheticVoice4,
433 SyntheticVoice5,
434 SyntheticVoice6,
435 SyntheticVoice7,
436 SyntheticVoice8,
437 SyntheticVoice9,
438 SyntheticVoice10,
439 SyntheticVoice11,
440 SyntheticVoice12,
441 SyntheticVoice13,
442 SyntheticVoice14,
443 SyntheticVoice15,
444 SyntheticVoice16,
445 SyntheticVoice17,
446 SyntheticVoice18,
447 SyntheticVoice19,
448 SyntheticVoice20,
449 SyntheticVoice21,
450 SyntheticVoice22,
451 SyntheticVoice23,
452 SyntheticVoice24,
453 SyntheticVoice25,
454 SyntheticVoice26,
455 SyntheticVoice27,
456 SyntheticVoice28,
457 SyntheticVoice29,
458
459 Organ1,
460 Organ2,
461 Organ3,
462 Organ4,
463 Organ5,
464 Organ6,
465 Organ7,
466 Organ8,
467 Organ9,
468 Organ10,
469 Organ11,
470 Organ12,
471 Organ13,
472 Organ14,
473 Organ15,
474 Organ16,
475 Organ17,
476 Organ18,
477 Organ19,
478 Organ20,
479 Organ21,
480 Organ22,
481 Organ23,
482 EPiano1,
483 EPiano2,
484 EPiano3,
485 EPiano4,
486 Key1,
487 Key2,
488 Key3,
489 DistGuitar1,
490 DistGuitar2,
491 Rhode,
492 Brass1,
493 Brass2,
494 Chip1,
495 Chip2,
496 Chip3,
497 Chip4,
498 Chip5,
499 Chip6,
500 Chip7,
501
502 Gritty1,
503 Gritty2,
504 Gritty3,
505 Gritty4,
506 Gritty5,
507 Gritty6,
508 Dirty1A,
509 Dirty1B,
510 Dirty1C,
511 Dirty2A,
512 Dirty2B,
513 Dirty2C,
514 Dirty3A,
515 Dirty3B,
516 Dirty3C,
517 Dirty4A,
518 Dirty4B,
519 Dirty4C,
520 Dirty5A,
521 Dirty5B,
522 Dirty5C,
523 Dirty6A,
524 Dirty6B,
525 Dirty6C,
526 Dirty7A,
527 Dirty7B,
528 Dirty7C,
529 Dirty8A,
530 Dirty8B,
531 Dirty8C,
532
533 Gate1,
534 Gate2,
535 Gate3,
536 Gate4,
537 Duck1,
538 Duck2,
539 Duck3,
540}
541
542impl Waveform {
543 fn from_or(waveform_id: u32, default: Waveform) -> Waveform {
544 Waveform::iter()
545 .find(|id| *id as u32 == waveform_id)
546 .unwrap_or(default)
547 }
548}
549
550impl Display for Waveform {
551 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
552 use Waveform::*;
553 let s = match self {
554 Sine => "Sine",
555 SineRoot1_5 => "Sine Root 1.5",
556 SineRoot2 => "Sine Root 2",
557 SineRoot3 => "Sine Root 3",
558 SineRoot4 => "Sine Root 4",
559 SinePower1_5 => "Sine Power 1.5",
560 SinePower2 => "Sine Power 2",
561 SinePower3 => "Sine Power 3",
562 SinePower4 => "Sine Power 4",
563 SineAm1 => "Sine AM 1",
564 SineAm2 => "Sine AM 2",
565 SineAm3 => "Sine AM 3",
566 SineAm4 => "Sine AM 4",
567 SineAm5 => "Sine AM 5",
568 SineFmA1 => "Sine FM A 1",
569 SineFmA2 => "Sine FM A 2",
570 SineFmA3 => "Sine FM A 3",
571 SineFmA4 => "Sine FM A 4",
572 SineFmA5 => "Sine FM A 5",
573 SineFmA6 => "Sine FM A 6",
574 SineFmB1 => "Sine FM B 1",
575 SineFmB2 => "Sine FM B 2",
576 SineFmB3 => "Sine FM B 3",
577 SineFmB4 => "Sine FM B 4",
578 SineFmB5 => "Sine FM B 5",
579 SineFmC1 => "Sine FM C 1",
580 SineFmC2 => "Sine FM C 2",
581 SineFmC3 => "Sine FM C 3",
582 SineFmC4 => "Sine FM C 4",
583 SineFmC5 => "Sine FM C 5",
584 SineFmC6 => "Sine FM C 6",
585 SineFmC7 => "Sine FM C 7",
586 SineFmC8 => "Sine FM C 8",
587 SineFmD1 => "Sine FM D 1",
588 SineFmD2 => "Sine FM D 2",
589 SineFmD3 => "Sine FM D 3",
590 SineFmD4 => "Sine FM D 4",
591 SineFmD5 => "Sine FM D 5",
592 SineFmD6 => "Sine FM D 6",
593 SineFmD7 => "Sine FM D 7",
594 SineFmD8 => "Sine FM D 8",
595 SineFmD9 => "Sine FM D 9",
596 SineFmD10 => "Sine FM D 10",
597 SineFmD11 => "Sine FM D 11",
598 SineFmD12 => "Sine FM D 12",
599 SineFmD13 => "Sine FM D 13",
600 SineFmD14 => "Sine FM D 14",
601 SineFmD15 => "Sine FM D 15",
602 SineFmKick1 => "Sine FM Kick 1",
603 SineFmKick2 => "Sine FM Kick 2",
604 SineFmKick3 => "Sine FM Kick 3",
605 SineFmKick4 => "Sine FM Kick 4",
606 SineFmKick5 => "Sine FM Kick 5",
607 SineFmKick6 => "Sine FM Kick 6",
608 SineFmKick7 => "Sine FM Kick 7",
609 SineFmKick8 => "Sine FM Kick 8",
610 SineFmKick9 => "Sine FM Kick 9",
611 SineFmKick10 => "Sine FM Kick 10",
612 SineFmKick11 => "Sine FM Kick 11",
613 SineFmKick12 => "Sine FM Kick 12",
614 Triangle => "Triangle",
615 TriangleRoot2 => "Triangle Root 2",
616 TriangleRoot3 => "Triangle Root 3",
617 TriangleRoot4 => "Triangle Root 4",
618 TriangleRoot5 => "Triangle Root 5",
619 Saw => "Saw",
620 SawPower1 => "Saw Power 1",
621 SawPower2 => "Saw Power 2",
622 SawSine1 => "Saw Sine 1",
623 SawSine2 => "Saw Sine 2",
624 SawSine3 => "Saw Sine 3",
625 Saw2x => "Saw 2x",
626 Square => "Square",
627 SquareSmooth1 => "Square Smooth 1",
628 SquareSmooth2 => "Square Smooth 2",
629 SquareHalfRoot => "Square Half Root",
630 SquareHalfRootPower => "Square Half Root Power",
631 SquarePower => "Square Power",
632 SquareDoublePower1 => "Square Double Power 1",
633 SquareDoublePower2 => "Square Double Power 2",
634 SquareAttackPower => "Square Attack Power",
635 SquareTristate1 => "Square Tristate 1",
636 SquareTristate2 => "Square Tristate 2",
637 SquareTristate3 => "Square Tristate 3",
638 SquareTristate4 => "Square Tristate 4",
639 SquareTristate5 => "Square Tristate 5",
640 SquareTristate6 => "Square Tristate 6",
641 SquareFm1 => "Square FM 1",
642 SquareFm2 => "Square FM 2",
643 SquareFm3 => "Square FM 3",
644 SquareFm4 => "Square FM 4",
645 SquareFm5 => "Square FM 5",
646 SquareFm6 => "Square FM 6",
647 SquareFm7 => "Square FM 7",
648 SquareFm8 => "Square FM 8",
649 Pulse1 => "Pulse 1",
650 Pulse2 => "Pulse 2",
651 Pulse3 => "Pulse 3",
652 Pulse4 => "Pulse 4",
653 PulseSquare => "Pulse Square",
654 PulseSquareSmooth => "Pulse Square Smooth",
655 PulseSmooth1 => "Pulse Smooth 1",
656 PulseSmooth2 => "Pulse Smooth 2",
657 Voice1 => "Voice 1",
658 Voice2 => "Voice 2",
659 Voice3 => "Voice 3",
660 Voice4 => "Voice 4",
661 Voice5 => "Voice 5",
662 Voice6 => "Voice 6",
663 Voice7 => "Voice 7",
664 Voice8 => "Voice 8",
665 Voice9 => "Voice 9",
666 Voice10 => "Voice 10",
667 Voice11 => "Voice 11",
668 Voice12 => "Voice 12",
669 Voice13 => "Voice 13",
670 Voice14 => "Voice 14",
671 Voice15 => "Voice 15",
672 Voice16 => "Voice 16",
673 Voice17 => "Voice 17",
674 Voice18 => "Voice 18",
675 Voice19 => "Voice 19",
676 Voice20 => "Voice 20",
677 Voice21 => "Voice 21",
678 Voice22 => "Voice 22",
679 Voice23 => "Voice 23",
680 Voice24 => "Voice 24",
681 Voice25 => "Voice 25",
682 Voice26 => "Voice 26",
683 Voice27 => "Voice 27",
684 Voice28 => "Voice 28",
685 Voice29 => "Voice 29",
686 Voice30 => "Voice 30",
687 FormantA1 => "Formant A 1",
688 FormantA2 => "Formant A 2",
689 FormantA3 => "Formant A 3",
690 FormantA4 => "Formant A 4",
691 FormantA5 => "Formant A 5",
692 FormantA6 => "Formant A 6",
693 FormantA7 => "Formant A 7",
694 FormantA8 => "Formant A 8",
695 FormantB1 => "Formant B 1",
696 FormantB2 => "Formant B 2",
697 FormantB3 => "Formant B 3",
698 FormantB4 => "Formant B 4",
699 FormantB5 => "Formant B 5",
700 FormantB6 => "Formant B 6",
701 FormantB7 => "Formant B 7",
702 FormantB8 => "Formant B 8",
703 SyntheticVoice1 => "Synthetic Voice 1",
704 SyntheticVoice2 => "Synthetic Voice 2",
705 SyntheticVoice3 => "Synthetic Voice 3",
706 SyntheticVoice4 => "Synthetic Voice 4",
707 SyntheticVoice5 => "Synthetic Voice 5",
708 SyntheticVoice6 => "Synthetic Voice 6",
709 SyntheticVoice7 => "Synthetic Voice 7",
710 SyntheticVoice8 => "Synthetic Voice 8",
711 SyntheticVoice9 => "Synthetic Voice 9",
712 SyntheticVoice10 => "Synthetic Voice 10",
713 SyntheticVoice11 => "Synthetic Voice 11",
714 SyntheticVoice12 => "Synthetic Voice 12",
715 SyntheticVoice13 => "Synthetic Voice 13",
716 SyntheticVoice14 => "Synthetic Voice 14",
717 SyntheticVoice15 => "Synthetic Voice 15",
718 SyntheticVoice16 => "Synthetic Voice 16",
719 SyntheticVoice17 => "Synthetic Voice 17",
720 SyntheticVoice18 => "Synthetic Voice 18",
721 SyntheticVoice19 => "Synthetic Voice 19",
722 SyntheticVoice20 => "Synthetic Voice 20",
723 SyntheticVoice21 => "Synthetic Voice 21",
724 SyntheticVoice22 => "Synthetic Voice 22",
725 SyntheticVoice23 => "Synthetic Voice 23",
726 SyntheticVoice24 => "Synthetic Voice 24",
727 SyntheticVoice25 => "Synthetic Voice 25",
728 SyntheticVoice26 => "Synthetic Voice 26",
729 SyntheticVoice27 => "Synthetic Voice 27",
730 SyntheticVoice28 => "Synthetic Voice 28",
731 SyntheticVoice29 => "Synthetic Voice 39",
732 Organ1 => "Organ 1",
733 Organ2 => "Organ 2",
734 Organ3 => "Organ 3",
735 Organ4 => "Organ 4",
736 Organ5 => "Organ 5",
737 Organ6 => "Organ 6",
738 Organ7 => "Organ 7",
739 Organ8 => "Organ 8",
740 Organ9 => "Organ 9",
741 Organ10 => "Organ 10",
742 Organ11 => "Organ 11",
743 Organ12 => "Organ 12",
744 Organ13 => "Organ 13",
745 Organ14 => "Organ 14",
746 Organ15 => "Organ 15",
747 Organ16 => "Organ 16",
748 Organ17 => "Organ 17",
749 Organ18 => "Organ 18",
750 Organ19 => "Organ 19",
751 Organ20 => "Organ 20",
752 Organ21 => "Organ 21",
753 Organ22 => "Organ 22",
754 Organ23 => "Organ 23",
755 EPiano1 => "E Piano 1",
756 EPiano2 => "E Piano 2",
757 EPiano3 => "E Piano 3",
758 EPiano4 => "E Piano 4",
759 Key1 => "Key 1",
760 Key2 => "Key 2",
761 Key3 => "Key 3",
762 DistGuitar1 => "Dist Guitar 1",
763 DistGuitar2 => "Dist Guitar 2",
764 Rhode => "Rhode",
765 Brass1 => "Brass 1",
766 Brass2 => "Brass 2",
767 Chip1 => "Chip 1",
768 Chip2 => "Chip 2",
769 Chip3 => "Chip 3",
770 Chip4 => "Chip 4",
771 Chip5 => "Chip 5",
772 Chip6 => "Chip 6",
773 Chip7 => "Chip 7",
774 Gritty1 => "Gritty 1",
775 Gritty2 => "Gritty 2",
776 Gritty3 => "Gritty 3",
777 Gritty4 => "Gritty 4",
778 Gritty5 => "Gritty 5",
779 Gritty6 => "Gritty 6",
780 Dirty1A => "Dirty 1 A",
781 Dirty1B => "Dirty 1 B",
782 Dirty1C => "Dirty 1 C",
783 Dirty2A => "Dirty 2 A",
784 Dirty2B => "Dirty 2 B",
785 Dirty2C => "Dirty 2 C",
786 Dirty3A => "Dirty 3 A",
787 Dirty3B => "Dirty 3 B",
788 Dirty3C => "Dirty 3 C",
789 Dirty4A => "Dirty 4 A",
790 Dirty4B => "Dirty 4 B",
791 Dirty4C => "Dirty 4 C",
792 Dirty5A => "Dirty 5 A",
793 Dirty5B => "Dirty 5 B",
794 Dirty5C => "Dirty 5 C",
795 Dirty6A => "Dirty 6 A",
796 Dirty6B => "Dirty 6 B",
797 Dirty6C => "Dirty 6 C",
798 Dirty7A => "Dirty 7 A",
799 Dirty7B => "Dirty 7 B",
800 Dirty7C => "Dirty 7 C",
801 Dirty8A => "Dirty 8 A",
802 Dirty8B => "Dirty 8 B",
803 Dirty8C => "Dirty 8 C",
804 Gate1 => "Gate 1",
805 Gate2 => "Gate 2",
806 Gate3 => "Gate 3",
807 Gate4 => "Gate 4",
808 Duck1 => "Duck 1",
809 Duck2 => "Duck 2",
810 Duck3 => "Duck 3",
811 };
812 f.write_str(s)
813 }
814}
815
816#[derive(Debug, Deserialize, Serialize)]
817#[serde(rename = "PARAM")]
818pub struct Param {
819 pub id: String,
820 pub value: Option<String>,
821}
822
823impl Param {
824 fn value_into<T: FromStr>(&self) -> Option<T> {
825 self.value.as_ref().and_then(|v| v.parse::<T>().ok())
826 }
827
828 fn value_bool(&self) -> Option<bool> {
831 self.value_into().map(|v: f64| (v - 1.0).abs() < 0.0000001)
832 }
833
834 fn value_i32(&self) -> Option<i32> {
837 self.value_into().map(|v: f64| v as i32)
838 }
839
840 fn value_u32(&self) -> Option<u32> {
841 self.value_into().map(|v: f64| v as u32)
842 }
843}
844
845#[derive(Debug, Deserialize, Serialize)]
847struct PluginParamTree {
848 #[serde(rename = "Scale")]
852 scale: u32,
853
854 #[serde(rename = "CustomScale")]
855 custom_scale: u32,
856
857 #[serde(rename = "Root")]
858 root_key: u32,
859
860 #[serde(rename = "PresetID")]
863 preset_id: Option<i32>, #[serde(rename = "PresetFolder")]
868 preset_folder: Option<u32>,
869
870 #[serde(rename = "PresetName")]
871 preset_name: String,
872
873 #[serde(rename = "PresetInfo")]
874 preset_info: String,
875
876 #[serde(rename = "FX_Order_0")]
877 fx_order0: Option<u32>,
878
879 #[serde(rename = "FX_Order_1")]
880 fx_order1: Option<u32>,
881
882 #[serde(rename = "FX_Order_2")]
883 fx_order2: Option<u32>,
884
885 #[serde(rename = "FX_Order_3")]
886 fx_order3: Option<u32>,
887
888 #[serde(rename = "FX_Order_4")]
889 fx_order4: Option<u32>,
890
891 #[serde(rename = "FX_Order_5")]
892 fx_order5: Option<u32>,
893
894 #[serde(rename = "FX_Order_6")]
895 fx_order6: Option<u32>,
896
897 #[serde(rename = "PARAM", default)]
898 params: Vec<Param>,
899}
900
901impl PluginParamTree {
902 fn remove(&mut self, id: &str) -> Option<Param> {
904 let index_result = self.params.iter().position(|param| param.id == id);
905 match index_result {
906 Some(index) => Some(self.params.remove(index)),
907 None => None,
908 }
909 }
910
911 fn remove_or<T: FromStr>(&mut self, id: &str, default: T) -> T {
912 match self.remove(id) {
913 Some(param) => param.value_into().unwrap_or(default),
914 None => default,
915 }
916 }
917
918 fn remove_bool_or(&mut self, id: &str, default: bool) -> bool {
919 match self.remove(id) {
920 Some(param) => param.value_bool().unwrap_or(default),
921 None => default,
922 }
923 }
924
925 fn remove_milliseconds_or(&mut self, id: &str, default: f64) -> Time {
926 let millis: f64 = match self.remove(id) {
927 Some(param) => param.value_into().unwrap_or(default),
928 None => default,
929 };
930 Time::new::<millisecond>(millis)
931 }
932
933 fn remove_percent_or(&mut self, id: &str, default: f64) -> Ratio {
934 let pct: f64 = match self.remove(id) {
935 Some(param) => param.value_into().unwrap_or(default),
936 None => default,
937 };
938 Ratio::new::<percent>(pct)
939 }
940
941 fn remove_u32_or(&mut self, id: &str, default: u32) -> u32 {
942 match self.remove(id) {
943 Some(param) => param.value_u32().unwrap_or(default),
944 None => default,
945 }
946 }
947
948 fn remove_i32_or(&mut self, id: &str, default: i32) -> i32 {
949 match self.remove(id) {
950 Some(param) => param.value_i32().unwrap_or(default),
951 None => default,
952 }
953 }
954}
955
956#[derive(Debug)]
958pub struct Preset {
959 pub name: String,
960 pub description: Option<String>,
961
962 #[doc(alias = "main_volume")]
965 pub master_volume_normalized: f64,
966
967 pub polyphony: u32,
968 pub portamento_mode: PortamentoMode,
969 pub midi_play_mode: MidiPlayMode,
970 pub glide: f64,
971 pub velocity_curve: f64,
972 pub key_track_curve: f64,
973 pub pitch_bend_range: f64,
974
975 pub limit_enabled: bool,
977 pub tuning: Tuning,
978 pub envelope: Envelope,
979 pub envelope_curve: f64,
980 pub filter: Filter,
981 pub filter_envelope_curve: f64,
982
983 pub oscillators: Vec<Oscillator>,
985
986 pub hard_sync: bool,
988 pub noise: Noise,
989
990 pub lfos: Vec<Lfo>,
992 pub mod_envelopes: Vec<ModulatorEnvelope>,
993 pub vibrato: Vibrato,
994 pub matrix: Vec<MatrixItem>,
995
996 pub effect_order: Vec<EffectType>,
998 pub chorus: Chorus,
999 pub delay: Delay,
1000 pub distortion: Distortion,
1001 pub equalizer: Equalizer,
1002 pub effect_filter: Filter,
1003 pub lofi: LoFi,
1004 pub reverb: Reverb,
1005}
1006
1007impl Preset {
1008 pub fn effect_position(&self, effect_type: EffectType) -> Option<u8> {
1010 self.effect_order
1011 .iter()
1012 .position(|e| e == &effect_type)
1013 .map(|pos| pos as u8)
1014 }
1015
1016 pub fn read_file<P: AsRef<Path>>(path: P) -> Result<Preset, Error> {
1017 let input = File::open(&path)?;
1018 let reader = BufReader::new(input);
1019
1020 let mut param_tree: PluginParamTree = match from_reader(reader) {
1021 Ok(param_tree) => param_tree,
1022 Err(error) => return Err(Error::new(ErrorKind::InvalidData, error)),
1023 };
1024
1025 let name = param_tree.preset_name.clone();
1026 let description: String = param_tree.preset_info.clone();
1027 let description = (description.as_str() != PRESET_INFO_DEFAULT).then_some(description);
1028
1029 let envelope = Envelope {
1030 attack: param_tree.remove_milliseconds_or("EnvAttack", 2.0),
1031 attack_curve: param_tree.remove_or("AttCurveType", 0.07),
1032 decay: param_tree.remove_milliseconds_or("EnvDecay", 150.0),
1033 decay_falloff: param_tree.remove_or("DecCurveType", 0.07),
1034 sustain: param_tree.remove_percent_or("EnvSustain", 0.9),
1035 release: param_tree.remove_milliseconds_or("EnvRelease", 4.0),
1036 release_falloff: param_tree.remove_or("RelCurveType", 0.07),
1037 };
1038
1039 let mut tunings = [0.0; 12];
1040 tunings[0] = param_tree.remove_or("TuneA", 0.0);
1041 tunings[1] = param_tree.remove_or("TuneASharp", 0.0);
1042 tunings[2] = param_tree.remove_or("TuneB", 0.0);
1043 tunings[3] = param_tree.remove_or("TuneC", 0.0);
1044 tunings[4] = param_tree.remove_or("TuneCSharp", 0.0);
1045 tunings[5] = param_tree.remove_or("TuneD", 0.0);
1046 tunings[6] = param_tree.remove_or("TuneDSharp", 0.0);
1047 tunings[7] = param_tree.remove_or("TuneE", 0.0);
1048 tunings[8] = param_tree.remove_or("TuneF", 0.0);
1049 tunings[9] = param_tree.remove_or("TuneFSharp", 0.0);
1050 tunings[10] = param_tree.remove_or("TuneG", 0.0);
1051 tunings[11] = param_tree.remove_or("TuneGSharp", 0.0);
1052 let tuning = Tuning {
1053 transpose: param_tree.remove_or("Transpose", 0.0),
1054 root_key: param_tree.root_key,
1055 scale: param_tree.scale,
1056 tunings,
1057 };
1058
1059 let _ = param_tree.remove_or("PCH", 0.0);
1062
1063 let filter_envelope = Envelope {
1064 attack: param_tree.remove_milliseconds_or("FilterEnvAttack", 2.0),
1065 attack_curve: param_tree.remove_or("FilterAttCurveType", 0.07),
1066 decay: param_tree.remove_milliseconds_or("FilterEnvDecay", 150.0),
1067 decay_falloff: param_tree.remove_or("FilterDecCurveType", 0.07),
1068 sustain: param_tree.remove_percent_or("FilterEnvSustain", 0.02),
1069 release: param_tree.remove_milliseconds_or("FilterEnvRelease", 23.0),
1070 release_falloff: param_tree.remove_or("FilterRelCurveType", 0.07),
1071 };
1072
1073 let filter = Filter {
1074 enabled: param_tree.remove_bool_or("FilterSwitch", false),
1075 mode: FilterMode::from_or(
1076 param_tree.remove_u32_or("FilterType", FilterMode::LowPass as u32),
1077 FilterMode::LowPass,
1078 ),
1079 resonance: param_tree.remove_or("FilterRes", 0.0),
1080 cutoff_frequency: param_tree.remove_or("FilterCut", 1.0) * 100.0,
1081 key_tracking: param_tree.remove_or("FilterKey", 0.0),
1082 envelope: filter_envelope,
1083 envelope_amount: param_tree.remove_or("FilterEnv", 0.0),
1084 effect_enabled: param_tree.remove_bool_or("FilterDriveSwitch", false),
1085 effect_mode: FilterEffectMode::from_or(
1086 param_tree.remove_u32_or("FilterDriveType", FilterEffectMode::Off as u32),
1087 FilterEffectMode::Off,
1088 ),
1089 effect_amount: param_tree.remove_or("FilterDrive", 0.5),
1090 };
1091
1092 let mut oscillators = Vec::new();
1097 for index in 1..=3 {
1098 let oscillator = Oscillator {
1099 enabled: param_tree.remove_bool_or(format!("OSCSwitch_{}", index).as_str(), true),
1100 waveform: Waveform::from_or(
1101 param_tree.remove_u32_or(
1102 format!("OSCWaveType_{}", index).as_str(),
1103 Waveform::Sine as u32,
1104 ),
1105 Waveform::Sine,
1106 ),
1107 invert: param_tree.remove_bool_or(format!("OSCInvert_{}", index).as_str(), false),
1108 pan: param_tree.remove_or(format!("OSCPan_{}", index).as_str(), 0.5),
1109 phase: param_tree.remove_or(format!("OSCPhase_{}", index).as_str(), 0.0),
1110 pitch: param_tree.remove_or(format!("OSCPitch_{}", index).as_str(), 0.0),
1111 fine_tuning: param_tree.remove_i32_or(format!("OSCFine_{}", index).as_str(), 0),
1112 semitone_tuning: param_tree.remove_i32_or(format!("OSCSemi_{}", index).as_str(), 0),
1113 octave_tuning: param_tree.remove_i32_or(format!("OSCOctave_{}", index).as_str(), 0),
1114 reverse: param_tree.remove_bool_or(format!("OSCReverse_{}", index).as_str(), false),
1115 free_run: param_tree
1116 .remove_bool_or(format!("OSCFreeRun_{}", index).as_str(), false),
1117 sync_all: param_tree
1118 .remove_bool_or(format!("OSCSyncAll_{}", index).as_str(), false),
1119 volume: param_tree.remove_or(format!("OSCVol_{}", index).as_str(), 0.294),
1120 unison: Unison {
1121 voices: param_tree.remove_u32_or(format!("OSCNumVoice_{}", index).as_str(), 1),
1122 detune: param_tree.remove_or(format!("OSCDetune_{}", index).as_str(), 0.2),
1123 spread: param_tree.remove_or(format!("OSCSpread_{}", index).as_str(), 0.5),
1124 mix: param_tree.remove_or(format!("OSCUniMix_{}", index).as_str(), 1.0),
1125 },
1126 am_enabled: param_tree
1127 .remove_bool_or(format!("OSCAMSwitch_{}", index).as_str(), false),
1128 am_amount: param_tree.remove_or(format!("OSCAM_{}", index).as_str(), 0.0),
1129 fm_enabled: param_tree
1130 .remove_bool_or(format!("OSCFMSwitch_{}", index).as_str(), false),
1131 fm_amount: param_tree.remove_or(format!("OSCFM_{}", index).as_str(), 0.0),
1132 rm_enabled: param_tree
1133 .remove_bool_or(format!("OSCRMSwitch_{}", index).as_str(), false),
1134 rm_amount: param_tree.remove_or(format!("OSCRM_{}", index).as_str(), 0.0),
1135 };
1136 oscillators.push(oscillator);
1137 }
1138
1139 let noise = Noise {
1140 enabled: param_tree.remove_bool_or("OSCSwitch_N", false),
1141 width: param_tree.remove_or("OSCWidth_N", 1.0),
1142 pan: param_tree.remove_or("OSCPan_N", 0.5),
1143 volume: param_tree.remove_or("OSCVol_N", 0.32),
1144 };
1145
1146 let lfo1 = Lfo {
1151 enabled: param_tree.remove_bool_or("LFOSwitch_1", false),
1152 waveform: Waveform::from_or(
1153 param_tree.remove_u32_or("LFOWaveType_1", Waveform::Sine as u32),
1154 Waveform::Sine,
1155 ),
1156 sync: param_tree.remove_bool_or("LFOSync_1", true),
1157 invert: param_tree.remove_bool_or("LFOInvert_1", false),
1158 reverse: param_tree.remove_bool_or("LFOReverse_1", false),
1159 mono: param_tree.remove_bool_or("LFOMono_1", false),
1160 free_run: param_tree.remove_bool_or("LFOFreeRun_1", false),
1161 frequency: param_tree.remove_or("LFOFreq_1", 0.35),
1162 phase: param_tree.remove_or("LFOPhase_1", 0.0),
1163 };
1164
1165 let lfo2 = Lfo {
1166 enabled: param_tree.remove_bool_or("LFOSwitch_2", false),
1167 waveform: Waveform::from_or(
1168 param_tree.remove_u32_or("LFOWaveType_2", Waveform::Sine as u32),
1169 Waveform::Sine,
1170 ),
1171 sync: param_tree.remove_bool_or("LFOSync_2", true),
1172 invert: param_tree.remove_bool_or("LFOInvert_2", false),
1173 reverse: param_tree.remove_bool_or("LFOReverse_2", false),
1174 mono: param_tree.remove_bool_or("LFOMono_2", false),
1175 free_run: param_tree.remove_bool_or("LFOFreeRun_2", false),
1176 frequency: param_tree.remove_or("LFOFreq_2", 0.35),
1177 phase: param_tree.remove_or("LFOPhase_2", 0.0),
1178 };
1179
1180 let lfos = vec![lfo1, lfo2];
1181
1182 let mod_envelope1 = ModulatorEnvelope {
1183 enabled: param_tree.remove_bool_or("ModEnvSwitch_1", false),
1184 curve: param_tree.remove_or("ModEnvCurveType_1", 0.14),
1185 envelope: Envelope {
1186 attack: param_tree.remove_milliseconds_or("ModEnvAttack_1", 1.0),
1187 attack_curve: param_tree.remove_or("ModAttCurveType_1", 0.07),
1188 decay: param_tree.remove_milliseconds_or("ModEnvDecay_1", 150.0),
1189 decay_falloff: param_tree.remove_or("ModDecCurveType_1", 0.07),
1190 sustain: param_tree.remove_percent_or("ModEnvSustain_1", 1.9),
1191 release: param_tree.remove_milliseconds_or("ModEnvRelease_1", 1.0),
1192 release_falloff: param_tree.remove_or("ModRelCurveType_1", 0.07),
1193 },
1194 };
1195 let mod_envelope2 = ModulatorEnvelope {
1196 enabled: param_tree.remove_bool_or("ModEnvSwitch_2", false),
1197 curve: param_tree.remove_or("ModEnvCurveType_2", 0.14),
1198 envelope: Envelope {
1199 attack: param_tree.remove_milliseconds_or("ModEnvAttack_2", 1.0),
1200 attack_curve: param_tree.remove_or("ModAttCurveType_2", 0.07),
1201 decay: param_tree.remove_milliseconds_or("ModEnvDecay_2", 150.0),
1202 decay_falloff: param_tree.remove_or("ModDecCurveType_2", 0.07),
1203 sustain: param_tree.remove_percent_or("ModEnvSustain_2", 0.9),
1204 release: param_tree.remove_milliseconds_or("ModEnvRelease_2", 1.0),
1205 release_falloff: param_tree.remove_or("ModRelCurveType_2", 0.07),
1206 },
1207 };
1208 let mod_envelopes = vec![mod_envelope1, mod_envelope2];
1209
1210 let vibrato = Vibrato {
1211 enabled: param_tree.remove_bool_or("VibSwitch", false),
1212 attack: param_tree.remove_or("VibAttack", 232.0),
1213 frequency: param_tree.remove_or("VibFrequency", 6.1),
1214 delay: param_tree.remove_or("VibDelay", 232.0),
1215 };
1216
1217 let mut matrix = Vec::new();
1218 for index in 1..=MODULATION_MATRIX_SIZE {
1219 matrix.push(MatrixItem {
1220 source: param_tree.remove_or(
1221 format!("MatrixSource_{}", index).as_str(),
1222 if index == 1 { 7 } else { 0 },
1223 ),
1224 target: param_tree.remove_or(
1225 format!("MatrixTarget_{}", index).as_str(),
1226 if index == 1 { 2 } else { 0 },
1227 ),
1228 amount: param_tree.remove_or(
1229 format!("MatrixAmount_{}", index).as_str(),
1230 if index == 1 { 1.0 } else { 0.0 },
1231 ),
1232 });
1233 }
1234
1235 let effect_type_ids = [
1240 param_tree.fx_order0.unwrap_or(0),
1241 param_tree.fx_order1.unwrap_or(1),
1242 param_tree.fx_order2.unwrap_or(2),
1243 param_tree.fx_order3.unwrap_or(3),
1244 param_tree.fx_order4.unwrap_or(4),
1245 param_tree.fx_order5.unwrap_or(5),
1246 param_tree.fx_order6.unwrap_or(6),
1247 ];
1248 let mut effect_order = Vec::with_capacity(effect_type_ids.len());
1249 for effect_type_id in effect_type_ids.iter() {
1250 match EffectType::try_from(*effect_type_id) {
1251 Ok(effect) => effect_order.push(effect),
1252 Err(msg) => return Err(Error::new(ErrorKind::InvalidData, msg)),
1253 }
1254 }
1255
1256 let chorus = Chorus {
1257 enabled: param_tree.remove_bool_or("ChorusSwitch", false),
1258 depth: param_tree.remove_or("ChorusDepth", 0.5),
1259 mix: param_tree.remove_or("ChorusMix", 0.5),
1260 pre_delay: param_tree.remove_or("ChorusPdelay", 0.5),
1261 ratio: param_tree.remove_or("ChorusRatio", 0.5),
1262 };
1263
1264 let delay_filter_mode_float: f64 = param_tree.remove_or("DelayLP", 0.0);
1265 let delay_filter_mode = DelayFilterMode::from_or(
1266 (delay_filter_mode_float * 1000.0) as u32,
1267 DelayFilterMode::Off,
1268 );
1269 let delay = Delay {
1270 enabled: param_tree.remove_bool_or("DelaySwitch", false),
1271 ping_pong: param_tree.remove_bool_or("DelayMode", false),
1272 feedback: param_tree.remove_or("DelayFeed", 0.3),
1273 filter_mode: delay_filter_mode,
1274 sync: param_tree.remove_bool_or("DelaySync", true),
1275 time: param_tree.remove_or("DelayTime", 0.17),
1276 mix: param_tree.remove_or("DelayMix", 0.2),
1277 };
1278
1279 let distortion = Distortion {
1280 enabled: param_tree.remove_bool_or("DistSwitch", false),
1281 gain: param_tree.remove_or("DistGain", 0.2),
1282 };
1283
1284 let equalizer = Equalizer {
1285 enabled: param_tree.remove_bool_or("EQSwitch", false),
1286 high_gain: param_tree.remove_or("EQHigh", Ratio::new::<percent>(0.5)),
1287 low_gain: param_tree.remove_or("EQLow", Ratio::new::<percent>(0.5)),
1288 mid_gain: param_tree.remove_or("EQMid", Ratio::new::<percent>(0.5)),
1289 };
1290
1291 let effect_filter = Filter {
1292 enabled: param_tree.remove_bool_or("FXFilterSwitch", false),
1293 mode: FilterMode::from_or(
1294 param_tree.remove_u32_or("FXFilterType", FilterMode::LowPass as u32),
1295 FilterMode::LowPass,
1296 ),
1297 resonance: param_tree.remove_or("FXFilterRes", 0.0),
1298 cutoff_frequency: param_tree.remove_or("FXFilterCut", 1.0),
1299 key_tracking: 0.0,
1300 envelope: Envelope {
1301 attack: Time::new::<second>(-1.01),
1302 attack_curve: -1.0,
1303 decay: Time::new::<second>(-1.1),
1304 decay_falloff: -1.0,
1305 sustain: Ratio::zero(),
1306 release: Time::new::<second>(-1.1),
1307 release_falloff: -1.0,
1308 },
1309 envelope_amount: 1.0,
1310 effect_enabled: false,
1311 effect_mode: FilterEffectMode::Off,
1312 effect_amount: 0.0,
1313 };
1314
1315 let lofi = LoFi {
1316 enabled: param_tree.remove_bool_or("LoFiSwitch", false),
1317 bitrate: param_tree.remove_or("LoFiBitRate", 1.0),
1318 sample_rate: param_tree.remove_or("LoFiSampleRate", 1.0),
1319 mix: param_tree.remove_or("LoFiMix", 1.0),
1320 };
1321
1322 let reverb = Reverb {
1323 enabled: param_tree.remove_bool_or("ReverbSwitch", false),
1324 dampen: param_tree.remove_or("ReverbDamp", 0.3),
1325 room: param_tree.remove_or("ReverbRoom", 0.3),
1326 filter: param_tree.remove_or("ReverbLP", 0.0),
1327 width: param_tree.remove_or("ReverbWidth", 0.8),
1328 mix: param_tree.remove_or("ReverbMix", 0.2),
1329 };
1330
1331 let preset = Preset {
1332 name,
1333 description,
1334 master_volume_normalized: param_tree.remove_or("MainVol", 0.0),
1335 polyphony: param_tree.remove_or("MaxVoices", 8),
1336 portamento_mode: PortamentoMode::from_or(
1337 param_tree.remove_u32_or("PortaMode", PortamentoMode::Poly as u32),
1338 PortamentoMode::Poly,
1339 ),
1340 midi_play_mode: MidiPlayMode::from_or(
1341 param_tree.remove_u32_or("MidiPlayMode", MidiPlayMode::Normal as u32),
1342 MidiPlayMode::Normal,
1343 ),
1344 glide: param_tree.remove_or("Glide", 30.0),
1345 velocity_curve: param_tree.remove_or("VeloCurve", 0.5),
1346 key_track_curve: param_tree.remove_or("KeyTrackCurve", 0.0),
1347 pitch_bend_range: param_tree.remove_or("PBRange", 2.0),
1348 limit_enabled: param_tree.remove_bool_or("LimitSwitch", false),
1349 tuning,
1350 envelope,
1351 envelope_curve: param_tree.remove_or("EnvCurveType", 0.14),
1352 filter,
1353 filter_envelope_curve: param_tree.remove_or("FilterEnvCurveType", 0.14),
1354
1355 oscillators,
1357 hard_sync: param_tree.remove_bool_or("OSCSync21", false),
1358 noise,
1359
1360 lfos,
1362 vibrato,
1363 mod_envelopes,
1364 matrix,
1365
1366 effect_order,
1368 chorus,
1369 delay,
1370 distortion,
1371 equalizer,
1372 effect_filter,
1373 lofi,
1374 reverb,
1375 };
1376
1377 for param in ¶m_tree.params {
1378 warn!(
1379 "Unrecognized parameter while reading {}, parameter {} is {:?}",
1380 path.as_ref().to_string_lossy(),
1381 param.id,
1382 param.value
1383 );
1384 }
1385
1386 Ok(preset)
1387 }
1388}
1389
1390#[cfg(test)]
1391mod test {
1392 use std::io::Result;
1393 use std::path::Path;
1394
1395 use approx::assert_relative_eq;
1396 use uom::si::ratio::percent;
1397
1398 use super::effect::{EffectType, FilterEffectMode, FilterMode};
1399 use super::*;
1400
1401 fn read_preset(filename: &str) -> Result<Preset> {
1402 let path = &Path::new("tests").join(&filename);
1403 Preset::read_file(path)
1404 }
1405
1406 #[test]
1408 fn init() {
1409 for file in &["init-1.0.2.bab", "init-1.0.4.bab"] {
1410 let preset = read_preset(file).unwrap();
1411 assert_eq!(preset.master_volume_normalized, 0.5); assert_eq!(preset.polyphony, 8);
1413 assert_eq!(preset.portamento_mode, PortamentoMode::Poly);
1414 assert_eq!(preset.midi_play_mode, MidiPlayMode::Normal);
1415 assert_eq!(preset.velocity_curve, 0.5);
1416 assert_eq!(preset.key_track_curve, 0.0);
1417 assert_eq!(preset.pitch_bend_range, 2.0);
1418 assert!(!preset.limit_enabled);
1419 assert_relative_eq!(preset.glide, 30.0, epsilon = 0.0001);
1420
1421 assert!(preset.name.starts_with("init"));
1422 assert!(preset.description.is_none());
1423
1424 let envelope = &preset.envelope;
1425 assert_relative_eq!(envelope.attack.get::<millisecond>(), 2.0, epsilon = 0.0001);
1426 assert_relative_eq!(envelope.attack_curve, 0.07, epsilon = 0.0001);
1427 assert_relative_eq!(envelope.decay.get::<millisecond>(), 150.0, epsilon = 0.0001);
1428 assert_relative_eq!(envelope.decay_falloff, 0.07, epsilon = 0.0001);
1429 assert_relative_eq!(envelope.sustain.get::<percent>(), 0.9, epsilon = 0.0001);
1430 assert_relative_eq!(envelope.release.get::<millisecond>(), 4.0, epsilon = 0.0001);
1431 assert_relative_eq!(envelope.release_falloff, 0.07, epsilon = 0.0001);
1432 assert_relative_eq!(preset.envelope_curve, 0.14, epsilon = 0.0001);
1433
1434 let tuning = &preset.tuning;
1435 assert_eq!(tuning.transpose, 0.0);
1436 assert_eq!(tuning.scale, 0);
1437 assert_eq!(tuning.root_key, 0);
1438 let tunings = tuning.tunings;
1439 assert_eq!(tunings, [0.0_f64; 12]);
1440
1441 let filter = &preset.filter;
1442 assert!(!filter.enabled);
1443 assert_eq!(filter.mode, FilterMode::LowPass);
1444 assert_relative_eq!(filter.resonance, 0.0, epsilon = 0.0001);
1445 assert_relative_eq!(filter.key_tracking, 0.0, epsilon = 0.0001);
1446 assert_relative_eq!(filter.cutoff_frequency, 100.0, epsilon = 0.0001);
1447 assert_relative_eq!(filter.envelope_amount, 0.0, epsilon = 0.0001);
1448 assert!(!filter.effect_enabled);
1449 assert_relative_eq!(filter.effect_amount, 0.5, epsilon = 0.0001);
1450 assert_eq!(filter.effect_mode, FilterEffectMode::Off);
1451
1452 let filter_env = &filter.envelope;
1453 assert_relative_eq!(
1454 filter_env.attack.get::<millisecond>(),
1455 2.0,
1456 epsilon = 0.0001
1457 );
1458 assert_relative_eq!(filter_env.attack_curve, 0.07, epsilon = 0.0001);
1459 assert_relative_eq!(
1460 filter_env.decay.get::<millisecond>(),
1461 150.0,
1462 epsilon = 0.0001
1463 );
1464 assert_relative_eq!(filter_env.decay_falloff, 0.07, epsilon = 0.0001);
1465 assert_relative_eq!(filter_env.sustain.get::<percent>(), 0.02, epsilon = 0.0001);
1466 assert_relative_eq!(
1467 filter_env.release.get::<millisecond>(),
1468 4.0,
1469 epsilon = 0.0001
1470 );
1471 assert_relative_eq!(filter_env.release_falloff, 0.07, epsilon = 0.0001);
1472 assert_relative_eq!(preset.filter_envelope_curve, 0.14, epsilon = 0.0001);
1473
1474 assert_eq!(preset.oscillators.len(), 3);
1479 assert!(preset.oscillators[0].enabled);
1480 assert!(!preset.oscillators[1].enabled);
1481 assert!(!preset.oscillators[2].enabled);
1482 for osc in &preset.oscillators {
1483 assert!(!osc.invert);
1484 assert!(!osc.reverse);
1485 assert!(!osc.free_run);
1486 assert!(!osc.sync_all);
1487
1488 assert!(!osc.am_enabled);
1489 assert_eq!(osc.am_amount, 0.0);
1490 assert!(!osc.fm_enabled);
1491 assert_eq!(osc.fm_amount, 0.0);
1492 assert!(!osc.rm_enabled);
1493 assert_eq!(osc.rm_amount, 0.0);
1494
1495 assert_eq!(osc.waveform, Waveform::Sine);
1496
1497 assert_relative_eq!(osc.pan, 0.5, epsilon = 0.0001);
1498 assert_relative_eq!(osc.phase, 0.0, epsilon = 0.0001);
1499 assert_relative_eq!(osc.volume, 0.5, epsilon = 0.0001);
1500
1501 assert_relative_eq!(osc.pitch, 0.0, epsilon = 0.0001);
1502 assert_eq!(osc.fine_tuning, 0);
1503 assert_eq!(osc.semitone_tuning, 0);
1504 assert_eq!(osc.octave_tuning, 0);
1505
1506 let unison = &osc.unison;
1507 assert_eq!(unison.voices, 1);
1508 assert_relative_eq!(unison.detune, 0.2, epsilon = 0.0001);
1509 assert_relative_eq!(unison.spread, 0.5, epsilon = 0.0001);
1510 assert_relative_eq!(unison.mix, 1.0, epsilon = 0.0001);
1511 }
1512
1513 assert!(!preset.hard_sync);
1514
1515 let noise = &preset.noise;
1516 assert!(!noise.enabled);
1517 assert_relative_eq!(noise.width, 1.0, epsilon = 0.0001);
1518 assert_relative_eq!(noise.pan, 0.5, epsilon = 0.0001);
1519 assert_relative_eq!(noise.volume, 0.32, epsilon = 0.0001);
1520
1521 assert_eq!(preset.lfos.len(), 2);
1526 for lfo in &preset.lfos {
1527 assert!(!lfo.enabled);
1528 assert_eq!(lfo.waveform, Waveform::Sine);
1529 assert!(lfo.sync);
1530 assert!(!lfo.invert);
1531 assert!(!lfo.reverse);
1532 assert!(!lfo.mono);
1533 assert!(!lfo.free_run);
1534 assert_relative_eq!(lfo.frequency, 0.35, epsilon = 0.0001);
1535 assert_relative_eq!(lfo.phase, 0.0, epsilon = 0.0001);
1536 }
1537
1538 assert_eq!(preset.mod_envelopes.len(), 2);
1539 for mod_envelope in &preset.mod_envelopes {
1540 assert!(!mod_envelope.enabled);
1541 assert_relative_eq!(mod_envelope.curve, 0.14, epsilon = 0.0001);
1542 let env = &mod_envelope.envelope;
1543 assert_relative_eq!(env.attack.get::<millisecond>(), 1.0, epsilon = 0.0001);
1544 assert_relative_eq!(env.attack_curve, 0.07, epsilon = 0.0001);
1545 assert_relative_eq!(env.decay.get::<millisecond>(), 150.0, epsilon = 0.0001);
1546 assert_relative_eq!(env.decay_falloff, 0.07, epsilon = 0.0001);
1547 assert_relative_eq!(env.sustain.get::<percent>(), 0.9, epsilon = 0.0001);
1548 assert_relative_eq!(env.release.get::<millisecond>(), 1.0, epsilon = 0.0001);
1549 assert_relative_eq!(env.release_falloff, 0.07, epsilon = 0.0001);
1550 }
1551
1552 let vibrato = &preset.vibrato;
1553 assert!(!vibrato.enabled);
1554 assert_relative_eq!(vibrato.attack, 232.0, epsilon = 0.0001);
1555 assert_relative_eq!(vibrato.delay, 232.0, epsilon = 0.0001);
1556 assert_relative_eq!(vibrato.frequency, 6.1, epsilon = 0.0001);
1557
1558 assert_eq!(preset.matrix[0].source, 7);
1559 assert_eq!(preset.matrix[0].target, 2);
1560 assert_eq!(preset.matrix[0].amount, 1.0);
1561 for index in 1..MODULATION_MATRIX_SIZE {
1562 assert_eq!(preset.matrix[index].source, 0);
1563 assert_eq!(preset.matrix[index].target, 0);
1564 assert_eq!(preset.matrix[index].amount, 0.0);
1565 }
1566
1567 let expected_effect_order: Vec<EffectType> = EffectType::iter().collect();
1572 assert_eq!(&preset.effect_order, &expected_effect_order);
1573
1574 let chorus = &preset.chorus;
1575 assert!(!chorus.enabled);
1576 assert_eq!(chorus.depth, 0.5);
1577 assert_eq!(chorus.mix, 0.5);
1578 assert_eq!(chorus.pre_delay, 0.5);
1579 assert_eq!(chorus.ratio, 0.5);
1580
1581 let delay = &preset.delay;
1582 assert!(!delay.enabled);
1583 assert!(!delay.ping_pong);
1584 assert!(delay.sync);
1585 assert_eq!(delay.filter_mode, DelayFilterMode::Off);
1586 assert_relative_eq!(delay.time, 0.17, epsilon = 0.0001);
1587 assert_relative_eq!(delay.feedback, 0.3, epsilon = 0.0001);
1588 assert_relative_eq!(delay.mix, 0.2, epsilon = 0.0001);
1589
1590 let distortion = &preset.distortion;
1591 assert!(!distortion.enabled);
1592 assert_relative_eq!(distortion.gain, 0.2, epsilon = 0.0001);
1593
1594 let effect_filter = &preset.effect_filter;
1595 assert!(!effect_filter.enabled);
1596 assert_eq!(effect_filter.mode, FilterMode::LowPass);
1597 assert_eq!(effect_filter.effect_mode, FilterEffectMode::Off);
1598 assert_relative_eq!(effect_filter.cutoff_frequency, 0.5, epsilon = 0.0001);
1599 assert_relative_eq!(effect_filter.resonance, 0.1, epsilon = 0.0001);
1600 assert_relative_eq!(effect_filter.resonance, 0.1, epsilon = 0.0001);
1601 assert_relative_eq!(effect_filter.key_tracking, 0.0, epsilon = 0.0001);
1602 assert_relative_eq!(effect_filter.effect_amount, 0.0, epsilon = 0.0001);
1603 assert_relative_eq!(preset.filter_envelope_curve, 0.14, epsilon = 0.0001);
1604
1605 let equalizer = preset.equalizer;
1606 assert!(!equalizer.enabled);
1607 assert_eq!(equalizer.low_gain.get::<percent>(), 0.5);
1608 assert_eq!(equalizer.mid_gain.get::<percent>(), 0.5);
1609 assert_eq!(equalizer.high_gain.get::<percent>(), 0.5);
1610
1611 let lofi = &preset.lofi;
1612 assert!(!lofi.enabled);
1613 assert_relative_eq!(lofi.bitrate, 1.0, epsilon = 0.0001);
1614 assert_relative_eq!(lofi.sample_rate, 1.0, epsilon = 0.0001);
1615 assert_relative_eq!(lofi.mix, 1.0, epsilon = 0.0001);
1616
1617 let reverb = &preset.reverb;
1618 assert!(!reverb.enabled);
1619 assert_relative_eq!(reverb.dampen, 0.3, epsilon = 0.0001);
1620 assert_relative_eq!(reverb.filter, 0.0, epsilon = 0.0001);
1621 assert_relative_eq!(reverb.room, 0.3, epsilon = 0.0001);
1622 assert_relative_eq!(reverb.width, 0.8, epsilon = 0.0001);
1623 assert_relative_eq!(reverb.mix, 0.2, epsilon = 0.0001);
1624 }
1625 }
1626
1627 #[test]
1628 fn envelopes() {
1629 let preset = read_preset("envelopes-1.0.2.bab").unwrap();
1630
1631 let envelope = &preset.envelope;
1633 assert_relative_eq!(envelope.attack.get::<millisecond>(), 1.0, epsilon = 0.00001);
1634 assert_relative_eq!(
1635 envelope.attack_curve,
1636 EnvelopeCurve::Linear.value(),
1637 epsilon = 0.00001
1638 );
1639 assert_relative_eq!(
1640 envelope.decay.get::<millisecond>(),
1641 15000.0,
1642 epsilon = 0.00001
1643 );
1644 assert_relative_eq!(
1645 envelope.decay_falloff,
1646 EnvelopeCurve::Exponential1.value(),
1647 epsilon = 0.00001
1648 );
1649 assert_relative_eq!(envelope.sustain.get::<percent>(), 0.42, epsilon = 0.00001);
1650 assert_relative_eq!(
1651 envelope.release.get::<millisecond>(),
1652 76.0,
1653 epsilon = 0.00001
1654 );
1655 assert_relative_eq!(
1656 envelope.release_falloff,
1657 EnvelopeCurve::Exponential2.value(),
1658 epsilon = 0.00001
1659 );
1660
1661 let mod_envelope = &preset.mod_envelopes.get(0).unwrap();
1663 assert!(mod_envelope.enabled);
1664 let envelope = &mod_envelope.envelope;
1665 assert_relative_eq!(
1666 envelope.attack.get::<millisecond>(),
1667 748.0,
1668 epsilon = 0.00001
1669 );
1670 assert_relative_eq!(
1671 envelope.attack_curve,
1672 EnvelopeCurve::Pluck1.value(),
1673 epsilon = 0.00001
1674 );
1675 assert_relative_eq!(
1676 envelope.decay.get::<millisecond>(),
1677 150.0,
1678 epsilon = 0.00001
1679 );
1680 assert_relative_eq!(
1681 envelope.decay_falloff,
1682 EnvelopeCurve::Pluck2.value(),
1683 epsilon = 0.00001
1684 );
1685 assert_relative_eq!(envelope.sustain.get::<percent>(), 0.90, epsilon = 0.00001);
1686 assert_relative_eq!(
1687 envelope.release.get::<millisecond>(),
1688 1.0,
1689 epsilon = 0.00001
1690 );
1691 assert_relative_eq!(
1692 envelope.release_falloff,
1693 EnvelopeCurve::Pluck3.value(),
1694 epsilon = 0.00001
1695 );
1696
1697 let mod_envelope = &preset.mod_envelopes.get(1).unwrap();
1703 assert!(!mod_envelope.enabled);
1704 let envelope = &mod_envelope.envelope;
1705 assert_relative_eq!(envelope.attack.get::<millisecond>(), 1.0, epsilon = 0.00001);
1706 assert_relative_eq!(
1707 envelope.attack_curve,
1708 EnvelopeCurve::Logarithmic2.value(),
1709 epsilon = 0.00001
1710 );
1711 assert_relative_eq!(envelope.decay.get::<millisecond>(), 2.0, epsilon = 0.00001);
1712 assert_relative_eq!(envelope.sustain.get::<percent>(), 0.0, epsilon = 0.00001);
1714 assert_relative_eq!(
1715 envelope.release.get::<millisecond>(),
1716 1.0,
1717 epsilon = 0.00001
1718 );
1719 let envelope = &preset.filter.envelope;
1723 assert_relative_eq!(envelope.attack.get::<millisecond>(), 2.0, epsilon = 0.00001);
1724 assert_relative_eq!(
1726 envelope.decay.get::<millisecond>(),
1727 150.0,
1728 epsilon = 0.00001
1729 );
1730 assert_relative_eq!(envelope.sustain.get::<percent>(), 0.02, epsilon = 0.00001);
1732 assert_relative_eq!(
1733 envelope.release.get::<millisecond>(),
1734 4.0,
1735 epsilon = 0.00001
1736 );
1737 }
1739
1740 #[test]
1741 fn envelope_curves() {
1742 let preset = read_preset("envelope_curve-ae3-de4-rl1-1.0.3.bab").unwrap();
1743 assert_relative_eq!(
1744 preset.envelope.attack_curve,
1745 EnvelopeCurve::Exponential3.value(),
1746 epsilon = 0.0001
1747 );
1748 assert_relative_eq!(
1749 preset.envelope.decay_falloff,
1750 EnvelopeCurve::Exponential4.value(),
1751 epsilon = 0.0001
1752 );
1753 assert_relative_eq!(
1754 preset.envelope.release_falloff,
1755 EnvelopeCurve::Logarithmic1.value(),
1756 epsilon = 0.0001
1757 );
1758
1759 let preset = read_preset("envelope_curve-ap3-dd1-rd2-1.0.3.bab").unwrap();
1760 assert_relative_eq!(
1761 preset.envelope.attack_curve,
1762 EnvelopeCurve::Pluck3.value(),
1763 epsilon = 0.0001
1764 );
1765 assert_relative_eq!(
1766 preset.envelope.decay_falloff,
1767 EnvelopeCurve::DoubleCurve1.value(),
1768 epsilon = 0.0001
1769 );
1770 assert_relative_eq!(
1771 preset.envelope.release_falloff,
1772 EnvelopeCurve::DoubleCurve2.value(),
1773 epsilon = 0.0001
1774 );
1775 }
1776
1777 #[test]
1778 fn master_volume() {
1779 let preset = read_preset("master-volume-10-1.0.3.bab").unwrap();
1780 assert_eq!(preset.master_volume_normalized, 1.0);
1781
1782 let preset = read_preset("master-volume--398-1.0.3.bab").unwrap();
1783 assert_relative_eq!(preset.master_volume_normalized, 0.007, epsilon = 0.001);
1784
1785 let preset = read_preset("master-volume--inf-1.0.3.bab").unwrap();
1786 assert_eq!(preset.master_volume_normalized, 0.0);
1787 }
1788
1789 #[test]
1790 fn midi_play_mode() {
1791 let preset = read_preset("playmode-cheat1-1.0.2.bab").unwrap();
1792 assert_eq!(preset.midi_play_mode, MidiPlayMode::Cheat1);
1793 }
1794
1795 #[test]
1796 fn waveforms() {
1797 fn read_waveform_preset(filename: &str) -> Result<Preset> {
1798 let path = &Path::new("tests").join("waveforms").join(&filename);
1799 Preset::read_file(path)
1800 }
1801
1802 let preset = read_waveform_preset("waveforms-formanta1-svoice1-organ1-1.0.3.bab").unwrap();
1803 assert_eq!(preset.oscillators[0].waveform, Waveform::FormantA1);
1804 assert_eq!(preset.oscillators[1].waveform, Waveform::SyntheticVoice1);
1805 assert_eq!(preset.oscillators[2].waveform, Waveform::Organ1);
1806
1807 let preset =
1808 read_waveform_preset("waveforms-gritty1-gate1-sinefmkick12-1.0.3.bab").unwrap();
1809 assert_eq!(preset.oscillators[0].waveform, Waveform::Gritty1);
1810 assert_eq!(preset.oscillators[1].waveform, Waveform::Gate1);
1811 assert_eq!(preset.oscillators[2].waveform, Waveform::SineFmKick12);
1812
1813 let preset = read_waveform_preset("waveforms-sine-triangle-saw-1.0.3.bab").unwrap();
1814 assert_eq!(preset.oscillators[0].waveform, Waveform::Sine);
1815 assert_eq!(preset.oscillators[1].waveform, Waveform::Triangle);
1816 assert_eq!(preset.oscillators[2].waveform, Waveform::Saw);
1817
1818 let preset = read_waveform_preset("waveforms-square-pulse-voice1-1.0.3.bab").unwrap();
1819 assert_eq!(preset.oscillators[0].waveform, Waveform::Square);
1820 assert_eq!(preset.oscillators[1].waveform, Waveform::Pulse1);
1821 assert_eq!(preset.oscillators[2].waveform, Waveform::Voice1);
1822 }
1823}