m8_file_parser/instruments/
hypersynth.rs1use 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] const 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 "CVO",
54 "SNC"
55];
56
57#[rustfmt::skip] const 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 "SNC",
81 "ERR"
82];
83
84#[rustfmt::skip] const 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 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 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}