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