m8_file_parser/instruments/
external_inst.rs1use array_concat::concat_arrays;
2
3use super::common::SynthParams;
4use super::common::TranspEq;
5use super::dests;
6use super::midi::ControlChange;
7use super::params;
8use super::CommandPack;
9use super::Version;
10use crate::reader::*;
11use crate::writer::Writer;
12use crate::FIRMWARE_6_2_SONG_VERSION;
13use crate::SEND_COMMAND_NAMES;
14use crate::SEND_COMMAND_NAMES_6_2;
15
16#[derive(PartialEq, Debug, Clone)]
17pub struct ExternalInst {
18 pub number: u8,
19 pub name: String,
20 pub transpose: bool,
21 pub table_tick: u8,
22 pub synth_params: SynthParams,
23
24 pub input: u8,
25 pub port: u8,
26 pub channel: u8,
27 pub bank: u8,
28 pub program: u8,
29 pub cca: ControlChange,
30 pub ccb: ControlChange,
31 pub ccc: ControlChange,
32 pub ccd: ControlChange,
33}
34
35#[rustfmt::skip] const EXTERNAL_INST_BASE_COMMANDS : [&'static str; CommandPack::BASE_INSTRUMENT_COMMAND_COUNT - 3] = [
37 "VOL",
38 "PIT",
39 "MPB",
40 "MPG",
41 "CCA",
42 "CCB",
43 "CCC",
44 "CCD",
45 "FLT",
46 "CUT",
47 "RES",
48 "AMP",
49 "LIM",
50 "PAN",
51 "DRY",
52];
53
54#[rustfmt::skip] const EXTERNAL_INST_EXTRA_COMMANDS : [&'static str; 2] = [
56 "ADD",
58 "CHD"
59];
60
61const EXTERNAL_INST_COMMANDS : [&'static str; CommandPack::BASE_INSTRUMENT_COMMAND_COUNT + 2] =
62 concat_arrays!(EXTERNAL_INST_BASE_COMMANDS, SEND_COMMAND_NAMES, EXTERNAL_INST_EXTRA_COMMANDS);
63
64const EXTERNAL_INST_COMMANDS_6_2 : [&'static str; CommandPack::BASE_INSTRUMENT_COMMAND_COUNT + 2] =
65 concat_arrays!(EXTERNAL_INST_BASE_COMMANDS, SEND_COMMAND_NAMES_6_2, EXTERNAL_INST_EXTRA_COMMANDS);
66
67#[rustfmt::skip] const DESTINATIONS : [&'static str; 14] = [
69 dests::OFF,
70 dests::VOLUME,
71 dests::CUTOFF,
72 dests::RES,
73 dests::AMP,
74 dests::PAN,
75 params::CCA,
76 params::CCB,
77 params::CCC,
78 params::CCD,
79 dests::MOD_AMT,
80 dests::MOD_RATE,
81 dests::MOD_BOTH,
82 dests::MOD_BINV,
83];
84
85impl ExternalInst {
86 const MOD_OFFSET: usize = 22;
87
88 pub fn command_name(&self, ver: Version) -> &'static [&'static str] {
89 if ver.after(&FIRMWARE_6_2_SONG_VERSION) {
90 &EXTERNAL_INST_COMMANDS_6_2
91 } else {
92 &EXTERNAL_INST_COMMANDS
93 }
94 }
95
96 pub fn destination_names(&self, _ver: Version) -> &'static [&'static str] {
97 &DESTINATIONS
98 }
99
100 pub fn filter_types(&self, _ver: Version) -> &'static [&'static str] {
102 &super::common::COMMON_FILTER_TYPES
103 }
104
105 pub fn human_readable_port(&self) -> &'static str {
107 crate::instruments::midi::PORTS[self.port as usize]
108 }
109
110 pub fn write(&self, ver: Version, w: &mut Writer) {
111 w.write_string(&self.name, 12);
112 w.write(TranspEq::from(ver, self.transpose, self.synth_params.associated_eq).into());
113 w.write(self.table_tick);
114 w.write(self.synth_params.volume);
115 w.write(self.synth_params.pitch);
116 w.write(self.synth_params.fine_tune);
117
118 w.write(self.input);
119 w.write(self.port);
120 w.write(self.channel);
121 w.write(self.bank);
122 w.write(self.program);
123
124 self.cca.write(w);
125 self.ccb.write(w);
126 self.ccc.write(w);
127 self.ccd.write(w);
128
129 self.synth_params.write(ver, w, ExternalInst::MOD_OFFSET);
130 }
131
132 pub fn from_reader(ver: Version, reader: &mut Reader, number: u8) -> M8Result<Self> {
133 let name = reader.read_string(12);
134 let transp_eq = TranspEq::from_version(ver, reader.read());
135
136 let table_tick = reader.read();
137 let volume = reader.read();
138 let pitch = reader.read();
139 let fine_tune = reader.read();
140
141 let input = reader.read();
142 let port = reader.read();
143 let channel = reader.read();
144 let bank = reader.read();
145 let program = reader.read();
146 let cca = ControlChange::from_reader(reader)?;
147 let ccb = ControlChange::from_reader(reader)?;
148 let ccc = ControlChange::from_reader(reader)?;
149 let ccd = ControlChange::from_reader(reader)?;
150
151 let synth_params = SynthParams::from_reader3(
152 ver,
153 reader,
154 volume,
155 pitch,
156 fine_tune,
157 transp_eq.eq,
158 ExternalInst::MOD_OFFSET,
159 )?;
160
161 Ok(ExternalInst {
162 number,
163 name,
164 transpose: transp_eq.transpose,
165 table_tick,
166 synth_params,
167
168 input,
169 port,
170 channel,
171 bank,
172 program,
173 cca,
174 ccb,
175 ccc,
176 ccd,
177 })
178 }
179}