m8_file_parser/instruments/
wavsynth.rs1use crate::instruments::common::*;
2use crate::reader::*;
3use crate::version::*;
4use crate::writer::Writer;
5use num_enum::IntoPrimitive;
6use num_enum::TryFromPrimitive;
7
8use super::dests;
9use super::CommandPack;
10
11#[repr(u8)]
13#[allow(non_camel_case_types)]
14#[derive(IntoPrimitive, TryFromPrimitive, PartialEq, Copy, Clone, Default, Debug)]
15pub enum WavShape {
16 #[default]
17 PULSE12,
18 PULSE25,
19 PULSE50,
20 PULSE75,
21 SAW,
22 TRIANGLE,
23 SINE,
24 NOISE_PITCHED,
25 NOISE,
26 WT_CRUSH,
27 WT_FOLDING,
28 WT_FREQ,
29 WT_FUZZY,
30 WT_GHOST,
31 WT_GRAPHIC,
32 WT_LFOPLAY,
33 WT_LIQUID,
34 WT_MORPHING,
35 WT_MYSTIC,
36 WT_STICKY,
37 WT_TIDAL,
38 WT_TIDY,
39 WT_TUBE,
40 WT_UMBRELLA,
41 WT_UNWIND,
42 WT_VIRAL,
43 WT_WAVES,
44 WT_DRIP,
45 WT_FROGGY,
46 WT_INSONIC,
47 WT_RADIUS,
48 WT_SCRATCH,
49 WT_SMOOTH,
50 WT_WOBBLE,
51 WT_ASIMMTRY,
52 WT_BLEEN,
53 WT_FRACTAL,
54 WT_GENTLE,
55 WT_HARMONIC,
56 WT_HYPNOTIC,
57 WT_ITERATIV,
58 WT_MICROWAV,
59 WT_PLAITS01,
60 WT_PLAITS02,
61 WT_RISEFALL,
62 WT_TONAL,
63 WT_TWINE,
64 WT_ALIEN,
65 WT_CYBERNET,
66 WT_DISORDR,
67 WT_FORMANT,
68 WT_HYPER,
69 WT_JAGGED,
70 WT_MIXED,
71 WT_MULTIPLY,
72 WT_NOWHERE,
73 WT_PINBALL,
74 WT_RINGS,
75 WT_SHIMMER,
76 WT_SPECTRAL,
77 WT_SPOOKY,
78 WT_TRANSFRM,
79 WT_TWISTED,
80 WT_VOCAL,
81 WT_WASHED,
82 WT_WONDER,
83 WT_WOWEE,
84 WT_ZAP,
85 WT_BRAIDS,
86 WT_VOXSYNTH,
87}
88
89#[derive(PartialEq, Debug, Clone)]
90pub struct WavSynth {
91 pub number: u8,
92 pub name: String,
93 pub transpose: bool,
94 pub table_tick: u8,
95 pub synth_params: SynthParams,
96
97 pub shape: WavShape,
98 pub size: u8,
99 pub mult: u8,
100 pub warp: u8,
101 pub scan: u8,
102}
103
104#[rustfmt::skip] const WAVSYNTH_COMMAND_NAMES : [&'static str; CommandPack::BASE_INSTRUMENT_COMMAND_COUNT + 2] = [
106 "VOL",
107 "PIT",
108 "FIN",
109 "OSC",
110 "SIZ",
111 "MUL",
112 "WRP",
113 "MIR",
114 "FIL",
115 "CUT",
116 "RES",
117 "AMP",
118 "LIM",
119 "PAN",
120 "DRY",
121
122 "SCH",
123 "SDL",
124 "SRV",
125
126 "SNC",
127 "ERR"
128];
129
130#[rustfmt::skip] const DESTINATIONS : [&'static str; 15] = [
132 dests::OFF,
133 dests::VOLUME,
134 dests::PITCH,
135
136 "SIZE",
137 "MULT",
138 "WARP",
139 "SCAN",
140 dests::CUTOFF,
141 dests::RES,
142 dests::AMP,
143 dests::PAN,
144 dests::MOD_AMT,
145 dests::MOD_RATE,
146 dests::MOD_BOTH,
147 dests::MOD_BINV,
148];
149
150#[rustfmt::skip] const WAVSYNTH_FILTER_TYPES : [&'static str; 12] = [
152 "OFF",
153 "LOWPASS",
154 "HIGHPAS",
155 "BANDPAS",
156 "BANDSTP",
157 "LP > HP",
158 "ZDF LP",
159 "ZDF HP",
160 "WAV LP",
161 "WAV HP",
162 "WAV BP",
163 "WAV BS"
164];
165
166impl WavSynth {
167 pub const MOD_OFFSET: usize = 30;
168
169 pub fn command_name(&self, _ver: Version) -> &'static [&'static str] {
170 &WAVSYNTH_COMMAND_NAMES
171 }
172
173 pub fn destination_names(&self, _ver: Version) -> &'static [&'static str] {
174 &DESTINATIONS
175 }
176
177 pub fn filter_types(&self, _ver: Version) -> &'static [&'static str] {
179 &WAVSYNTH_FILTER_TYPES
180 }
181
182 pub fn human_readable_filter(&self) -> &'static str {
183 WAVSYNTH_FILTER_TYPES[self.synth_params.filter_type as usize]
184 }
185
186 pub fn write(&self, ver: Version, w: &mut Writer) {
187 w.write_string(&self.name[..], 12);
188 w.write(TranspEq::from(ver, self.transpose, self.synth_params.associated_eq).into());
189 w.write(self.table_tick);
190 w.write(self.synth_params.volume);
191 w.write(self.synth_params.pitch);
192 w.write(self.synth_params.fine_tune);
193
194 w.write(self.shape.into());
195 w.write(self.size);
196 w.write(self.mult);
197 w.write(self.warp);
198 w.write(self.scan);
199 self.synth_params.write(ver, w, WavSynth::MOD_OFFSET);
200 }
201
202 pub fn from_reader(
203 ver: Version,
204 reader: &mut Reader,
205 number: u8,
206 version: Version,
207 ) -> M8Result<Self> {
208 let name = reader.read_string(12);
209 let transp_eq = TranspEq::from_version(ver, reader.read());
210 let table_tick = reader.read();
211 let volume = reader.read();
212 let pitch = reader.read();
213 let fine_tune = reader.read();
214
215 let shape = reader.read();
216 let size = reader.read();
217 let mult = reader.read();
218 let warp = reader.read();
219 let scan = reader.read();
220 let synth_params = if version.at_least(3, 0) {
221 SynthParams::from_reader3(
222 ver,
223 reader,
224 volume,
225 pitch,
226 fine_tune,
227 transp_eq.eq,
228 WavSynth::MOD_OFFSET,
229 )?
230 } else {
231 SynthParams::from_reader2(reader, volume, pitch, fine_tune)?
232 };
233
234 Ok(WavSynth {
235 number,
236 name,
237 transpose: transp_eq.transpose,
238 table_tick,
239 synth_params,
240
241 shape: shape
242 .try_into()
243 .map_err(|_| ParseError(format!("Invalid wavsynth shape")))?,
244 size,
245 mult,
246 warp,
247 scan,
248 })
249 }
250}