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