1use 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] = [
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
127#[rustfmt::skip] const DESTINATIONS : [&'static str; 15] = [
129 dests::OFF,
130 dests::VOLUME,
131 dests::PITCH,
132
133 "SIZE",
134 "MULT",
135 "WARP",
136 "SCAN",
137 dests::CUTOFF,
138 dests::RES,
139 dests::AMP,
140 dests::PAN,
141 dests::MOD_AMT,
142 dests::MOD_RATE,
143 dests::MOD_BOTH,
144 dests::MOD_BINV,
145];
146
147#[rustfmt::skip] const WAVSYNTH_FILTER_TYPES : [&'static str; 12] = [
149 "OFF",
150 "LOWPASS",
151 "HIGHPAS",
152 "BANDPAS",
153 "BANDSTP",
154 "LP > HP",
155 "ZDF LP",
156 "ZDF HP",
157 "WAV LP",
158 "WAV HP",
159 "WAV BP",
160 "WAV BS"
161];
162
163impl WavSynth {
164 pub const MOD_OFFSET: usize = 30;
165
166 pub fn command_name(&self, _ver: Version) -> &'static [&'static str] {
167 &WAVSYNTH_COMMAND_NAMES
168 }
169
170 pub fn destination_names(&self, _ver: Version) -> &'static [&'static str] {
171 &DESTINATIONS
172 }
173
174 pub fn human_readable_filter(&self) -> &'static str {
175 WAVSYNTH_FILTER_TYPES[self.synth_params.filter_type as usize]
176 }
177
178 pub fn write(&self, ver: Version, w: &mut Writer) {
179 w.write_string(&self.name[..], 12);
180 w.write(TranspEq::from(ver, self.transpose, self.synth_params.associated_eq).into());
181 w.write(self.table_tick);
182 w.write(self.synth_params.volume);
183 w.write(self.synth_params.pitch);
184 w.write(self.synth_params.fine_tune);
185
186 w.write(self.shape.into());
187 w.write(self.size);
188 w.write(self.mult);
189 w.write(self.warp);
190 w.write(self.scan);
191 self.synth_params.write(ver, w, WavSynth::MOD_OFFSET);
192 }
193
194 pub fn from_reader(
195 ver: Version,
196 reader: &mut Reader,
197 number: u8,
198 version: Version,
199 ) -> M8Result<Self> {
200 let name = reader.read_string(12);
201 let transp_eq = TranspEq::from_version(ver, reader.read());
202 let table_tick = reader.read();
203 let volume = reader.read();
204 let pitch = reader.read();
205 let fine_tune = reader.read();
206
207 let shape = reader.read();
208 let size = reader.read();
209 let mult = reader.read();
210 let warp = reader.read();
211 let scan = reader.read();
212 let synth_params = if version.at_least(3, 0) {
213 SynthParams::from_reader3(
214 ver,
215 reader,
216 volume,
217 pitch,
218 fine_tune,
219 transp_eq.eq,
220 WavSynth::MOD_OFFSET,
221 )?
222 } else {
223 SynthParams::from_reader2(reader, volume, pitch, fine_tune)?
224 };
225
226 Ok(WavSynth {
227 number,
228 name,
229 transpose: transp_eq.transpose,
230 table_tick,
231 synth_params,
232
233 shape: shape
234 .try_into()
235 .map_err(|_| ParseError(format!("Invalid wavsynth shape")))?,
236 size,
237 mult,
238 warp,
239 scan,
240 })
241 }
242}