m8_file_parser/instruments/modulator/
mod.rs

1use crate::{reader::*, writer::Writer};
2
3use super::Version;
4
5mod adsr_env;
6mod ahd_env;
7mod drum_env;
8mod lfo;
9mod tracking_env;
10mod trig_env;
11
12pub use adsr_env::*;
13pub use ahd_env::*;
14pub use drum_env::*;
15pub use lfo::*;
16pub use tracking_env::*;
17pub use trig_env::*;
18
19#[derive(PartialEq, Debug, Clone)]
20pub enum Mod {
21    AHDEnv(AHDEnv),
22    ADSREnv(ADSREnv),
23    DrumEnv(DrumEnv),
24    LFO(LFO),
25    TrigEnv(TrigEnv),
26    TrackingEnv(TrackingEnv),
27}
28
29impl Mod {
30    /// Size in bytes of the modulator
31    const SIZE: usize = 6;
32
33    /// Number of commands associated to each modulator
34    pub const COMMAND_PER_MOD: usize = 5;
35
36    pub fn command_name(&self, ver: Version, mod_id: usize) -> &'static [&'static str] {
37        match self {
38            Mod::AHDEnv(_) => AHDEnv::command_names(ver, mod_id),
39            Mod::ADSREnv(_) => ADSREnv::command_name(ver, mod_id),
40            Mod::DrumEnv(_) => DrumEnv::command_names(ver, mod_id),
41            Mod::LFO(_) => LFO::command_name(ver, mod_id),
42            Mod::TrigEnv(_) => TrigEnv::command_name(ver, mod_id),
43            Mod::TrackingEnv(_) => TrackingEnv::command_name(ver, mod_id),
44        }
45    }
46
47    pub fn from_reader(reader: &mut Reader) -> M8Result<Self> {
48        let start_pos = reader.pos();
49        let first_byte = reader.read();
50        let ty = first_byte >> 4;
51        let dest = first_byte & 0x0F;
52
53        // dbg!(ty, dest, start_pos);
54        let r = match ty {
55            0 => Mod::AHDEnv(AHDEnv::from_reader3(reader, dest)?),
56            1 => Mod::ADSREnv(ADSREnv::from_reader(reader, dest)?),
57            2 => Mod::DrumEnv(DrumEnv::from_reader(reader, dest)?),
58            3 => Mod::LFO(LFO::from_reader3(reader, dest)?),
59            4 => Mod::TrigEnv(TrigEnv::from_reader(reader, dest)?),
60            5 => Mod::TrackingEnv(TrackingEnv::from_reader(reader, dest)?),
61            x => return Err(ParseError(format!("Unknown mod type {}", x))),
62        };
63
64        reader.set_pos(start_pos + Self::SIZE);
65        Ok(r)
66    }
67
68    pub fn write(&self, w: &mut Writer) {
69        let start = w.pos();
70
71        match self {
72            Mod::AHDEnv(env) => {
73                w.write(env.dest);
74                env.write(w);
75            }
76            Mod::ADSREnv(env) => {
77                w.write(1 << 4 | env.dest);
78                env.write(w);
79            }
80            Mod::DrumEnv(env) => {
81                w.write(2 << 4 | env.dest);
82                env.write(w);
83            }
84            Mod::LFO(lfo) => {
85                w.write(3 << 4 | lfo.dest);
86                lfo.write(w);
87            }
88            Mod::TrigEnv(env) => {
89                w.write(4 << 4 | env.dest);
90                env.write(w);
91            }
92            Mod::TrackingEnv(env) => {
93                w.write(5 << 4 | env.dest);
94                env.write(w);
95            }
96        }
97
98        w.seek(start + Self::SIZE);
99    }
100}