m8_file_parser/instruments/
hypersynth.rs

1use super::common::SynthParams;
2use super::common::TranspEq;
3use super::common::COMMON_FILTER_TYPES;
4use super::dests;
5use super::CommandPack;
6use super::Version;
7use crate::reader::*;
8use crate::writer::Writer;
9
10use arr_macro::arr;
11
12#[derive(PartialEq, Debug, Clone)]
13pub struct HyperSynth {
14    pub number: u8,
15    pub name: String,
16    pub transpose: bool,
17    pub table_tick: u8,
18    pub synth_params: SynthParams,
19
20    pub scale: u8,
21    pub default_chord: [u8; 7],
22    pub shift: u8,
23    pub swarm: u8,
24    pub width: u8,
25    pub subosc: u8,
26
27    pub chords: [[u8; 6]; 0x10],
28}
29
30#[rustfmt::skip] // Keep constants with important order vertical for maintenance
31const HYPERSYNTH_COMMAND_NAMES : [&'static str; CommandPack::BASE_INSTRUMENT_COMMAND_COUNT + 2] = [
32    "VOL",
33    "PIT",
34    "FIN",
35    "CRD",
36    "SHF",
37    "SWM",
38    "WID",
39    "SUB",
40    "FLT",
41    "CUT",
42    "RES",
43    "AMP",
44    "LIM",
45    "PAN",
46    "DRY",
47    
48    "SCH",
49    "SDL",
50    "SRV",
51
52    // EXTRA
53    "CVO",
54    "SNC"
55];
56
57#[rustfmt::skip] // Keep constants with important order vertical for maintenance
58const HYPERSYNTH_COMMAND_NAMES_6 : [&'static str; CommandPack::BASE_INSTRUMENT_COMMAND_COUNT + 2] = [
59    "VOL",
60    "PIT",
61    "FIN",
62    "CRD",
63    "CVO",
64    "SWM",
65    "WID",
66    "SUB",
67    "FLT",
68    "CUT",
69    "RES",
70    "AMP",
71    "LIM",
72    "PAN",
73    "DRY",
74    
75    "SCH",
76    "SDL",
77    "SRV",
78
79    // EXTRA
80    "SNC",
81    "ERR"
82];
83
84#[rustfmt::skip] // Keep constants with important order vertical for maintenance
85const DESTINATIONS : [&'static str; 15] = [
86    dests::OFF,
87    dests::VOLUME,
88    dests::PITCH,
89
90    "SHIFT",
91    "SWARM",
92    "WIDTH",
93    "SUBOSC",
94    dests::CUTOFF,
95    dests::RES,
96    dests::AMP,
97    dests::PAN,
98    dests::MOD_AMT,
99    dests::MOD_RATE,
100    dests::MOD_BOTH,
101    dests::MOD_BINV,
102];
103
104impl HyperSynth {
105    const MOD_OFFSET: usize = 23;
106
107    pub fn command_name(&self, ver: Version) -> &'static [&'static str] {
108        if ver.at_least(6, 0) {
109            &HYPERSYNTH_COMMAND_NAMES_6
110        } else {
111            &HYPERSYNTH_COMMAND_NAMES
112        }
113    }
114
115    pub fn destination_names(&self, _ver: Version) -> &'static [&'static str] {
116        &DESTINATIONS
117    }
118
119    /// List of all the applyable filter types for the instrument
120    pub fn filter_types(&self, _ver: Version) -> &'static [&'static str] {
121        &super::common::COMMON_FILTER_TYPES
122    }
123
124    pub fn human_readable_filter(&self) -> &'static str {
125        COMMON_FILTER_TYPES[self.synth_params.filter_type as usize]
126    }
127
128    pub fn write(&self, ver: Version, w: &mut Writer) {
129        w.write_string(&self.name, 12);
130        w.write(TranspEq::from(ver, self.transpose, self.synth_params.associated_eq).into());
131        w.write(self.table_tick);
132        w.write(self.synth_params.volume);
133        w.write(self.synth_params.pitch);
134        w.write(self.synth_params.fine_tune);
135
136        for c in self.default_chord {
137            w.write(c);
138        }
139
140        w.write(self.scale);
141        w.write(self.shift);
142        w.write(self.swarm);
143        w.write(self.width);
144        w.write(self.subosc);
145
146        self.synth_params.write(ver, w, HyperSynth::MOD_OFFSET);
147
148        for chd in self.chords {
149            w.write(0xFF);
150            for k in chd {
151                w.write(k);
152            }
153        }
154    }
155
156    fn load_chord(reader: &mut Reader) -> [u8; 6] {
157        // padding
158        let _ = reader.read();
159        arr![reader.read(); 6]
160    }
161
162    pub fn from_reader(ver: Version, reader: &mut Reader, number: u8) -> M8Result<Self> {
163        let name = reader.read_string(12);
164        let transp_eq = TranspEq::from_version(ver, reader.read());
165        let table_tick = reader.read();
166        let volume = reader.read();
167        let pitch = reader.read();
168        let fine_tune = reader.read();
169
170        let default_chord = arr![reader.read(); 7];
171        let scale = reader.read();
172        let shift = reader.read();
173        let swarm = reader.read();
174        let width = reader.read();
175        let subosc = reader.read();
176        let synth_params = SynthParams::from_reader3(
177            ver,
178            reader,
179            volume,
180            pitch,
181            fine_tune,
182            transp_eq.eq,
183            HyperSynth::MOD_OFFSET,
184        )?;
185
186        let chords = arr![HyperSynth::load_chord(reader); 0x10];
187
188        Ok(HyperSynth {
189            number,
190            name,
191            transpose: transp_eq.transpose,
192            table_tick,
193            synth_params,
194
195            scale,
196            default_chord,
197            shift,
198            swarm,
199            width,
200            subosc,
201            chords,
202        })
203    }
204}