synthahol_babylon/
lib.rs

1//! Library to read presets for the
2//! [Babylon](https://www.waproduction.com/plugins/view/babylon)
3//! synthesizer
4//!
5//! Babylon is a virtual analog synth by W. A. Production.
6//!
7//! # Reading a Preset
8//!
9//! ```rust
10//! use synthahol_babylon::Preset;
11//!
12//! let path = std::path::Path::new("tests") .join("init-1.0.2.bab");
13//! let preset = Preset::read_file(&path).unwrap();
14//! println!("Preset name: {}", preset.name);
15//! println!("Polyphony: {}", preset.polyphony);
16//! ```
17
18use 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
41/// The standard Preset Info text if the user does not change it.  It is treated as blank.
42const PRESET_INFO_DEFAULT: &str = "Preset Info";
43
44/// ADSR-style envelope.
45#[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    /// A percentage, not milliseconds
58    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    /// Exp to Log
80    DoubleCurve1,
81
82    /// Log to Exp
83    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/// White noise generator.
151#[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/// The third oscillator doesn't have all the capabilities of the first two
162/// oscillators because the first two route to the third.
163#[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    /// Amplitude modulation
183    pub am_enabled: bool,
184    pub am_amount: f64,
185
186    /// Frequency modulation
187    pub fm_enabled: bool,
188    pub fm_amount: f64,
189
190    /// Ring modulations
191    pub rm_enabled: bool,
192    pub rm_amount: f64,
193}
194
195/// The discriminants of the items match the file format.
196#[derive(Copy, Clone, Debug, EnumIter, Eq, PartialEq)]
197#[repr(u32)]
198pub enum MidiPlayMode {
199    Normal,
200
201    /// Mute off-key note
202    Cheat1,
203
204    /// Replace off-key notes
205    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/// The discriminants of the items match the file format.
224#[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    /// Octave of values starting at A natural.
249    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    /// The first voice is the original signal.
263    pub voices: u32,
264    pub detune: f64,
265    pub spread: f64,
266    pub mix: f64,
267}
268
269/// The discriminants of the items match the file format.
270#[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    /// Convert the value into a boolean. Babylon stores booleans as a floating
829    /// point value (!) so traditional conversion methods don't work.
830    fn value_bool(&self) -> Option<bool> {
831        self.value_into().map(|v: f64| (v - 1.0).abs() < 0.0000001)
832    }
833
834    /// Convert the value into a `i32`. Babylon stores integers as a floating
835    /// point values is several places.
836    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/// The Babylon preset as it's stored in XML. This is converted to a [`Preset`].
846#[derive(Debug, Deserialize, Serialize)]
847struct PluginParamTree {
848    // EnvLock, FilterLock, FXLock, PortamentoLock and TunerLock are not read because
849    // they effect the next preset loaded in Babylon and not the current preset.  It is
850    // unclear why they would be stored in the preset file in the first place.
851    #[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    /// The preset ID doesn't appear to have a logical use. The preset IDs
861    /// in the factory presets don't seem to follow any pattern.
862    #[serde(rename = "PresetID")]
863    preset_id: Option<i32>, // -1 appears in some
864
865    /// The preset folder doesn't appear to have a logical use. The folder
866    /// numbers in the factory presets don't seem to follow any pattern.
867    #[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    /// Remove a parameter with the given identifier, returning it.
903    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// Converted from a `PluginParamTree` into a more usable model.
957#[derive(Debug)]
958pub struct Preset {
959    pub name: String,
960    pub description: Option<String>,
961
962    /// The master volume from 0.0 to 1.0. The value 0.0 maps to -inf dB,
963    /// 0.5 maps to 0.0 dB and 1.0 maps to 10.0 dB.
964    #[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    /// Limit the output to 0 dB using soft clipping
976    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    // Oscillators
984    pub oscillators: Vec<Oscillator>,
985
986    /// Sync oscillator 2 to oscillator 1.  Oscillator 2 resets when oscillator 1 does.
987    pub hard_sync: bool,
988    pub noise: Noise,
989
990    // Modulators
991    pub lfos: Vec<Lfo>,
992    pub mod_envelopes: Vec<ModulatorEnvelope>,
993    pub vibrato: Vibrato,
994    pub matrix: Vec<MatrixItem>,
995
996    // Effects
997    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    /// Where in the effect order the effect type occurs.
1009    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        // No idea what this is for. There isn't any difference in the interface regardless
1060        // of the value. "PCH" is often short for "pitch".
1061        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        //
1093        // Oscillators
1094        //
1095
1096        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        //
1147        // Modulators
1148        //
1149
1150        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        //
1236        // Effects
1237        //
1238
1239        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
1356            oscillators,
1357            hard_sync: param_tree.remove_bool_or("OSCSync21", false),
1358            noise,
1359
1360            // Modulators
1361            lfos,
1362            vibrato,
1363            mod_envelopes,
1364            matrix,
1365
1366            // Effects
1367            effect_order,
1368            chorus,
1369            delay,
1370            distortion,
1371            equalizer,
1372            effect_filter,
1373            lofi,
1374            reverb,
1375        };
1376
1377        for param in &param_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    /// Check defaults.
1407    #[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); // 0 dB
1412            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            //
1475            // Oscillators
1476            //
1477
1478            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            //
1522            // Modulators
1523            //
1524
1525            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            //
1568            // Effects
1569            //
1570
1571            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        // ADSR
1632        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        // Modulator envelope 1
1662        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        // Modulator envelope 2
1698        // NOTE: Bug report send to W. A. Productions on 2021-10-21 showing the curve types for
1699        // modulator 2 don't save properly. The labels for attack, decay and release always show
1700        // "L2" but the popup menu shows a different selection. This may also apply to the Filter
1701        // envelope.
1702        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.decay_falloff, EnvelopeCurve::DoubleCurve1.value(), epsilon = 0.00001);
1713        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        // assert_relative_eq!(envelope.release_falloff, EnvelopeCurve::DoubleCurve2.value(), epsilon = 0.00001);
1720
1721        // Filter envelope
1722        let envelope = &preset.filter.envelope;
1723        assert_relative_eq!(envelope.attack.get::<millisecond>(), 2.0, epsilon = 0.00001);
1724        // assert_relative_eq!(envelope.attack_curve, EnvelopeCurve::Logarithmic1.value(), epsilon = 0.00001);
1725        assert_relative_eq!(
1726            envelope.decay.get::<millisecond>(),
1727            150.0,
1728            epsilon = 0.00001
1729        );
1730        // assert_relative_eq!(envelope.decay_falloff, EnvelopeCurve::Linear.value(), epsilon = 0.00001);
1731        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        // assert_relative_eq!(envelope.release_falloff, EnvelopeCurve::Exponential4.value(), epsilon = 0.00001);
1738    }
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}