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 MacroSynthOsc {
16 #[default]
17 CSAW,
18 MORPH,
19 SAW_SQUARE,
20 SINE_TRIANGLE,
21 BUZZ,
22 SQUARE_SUB,
23 SAW_SUB,
24 SQUARE_SYNC,
25 SAW_SYNC,
26 TRIPLE_SAW,
27 TRIPLE_SQUARE,
28 TRIPLE_TRIANGLE,
29 TRIPLE_SIN,
30 TRIPLE_RNG,
31 SAW_SWARM,
32 SAW_COMB,
33 TOY,
34 DIGITAL_FILTER_LP,
35 DIGITAL_FILTER_PK,
36 DIGITAL_FILTER_BP,
37 DIGITAL_FILTER_HP,
38 VOSIM,
39 VOWEL,
40 VOWEL_FOF,
41 HARMONICS,
42 FM,
43 FEEDBACK_FM,
44 CHAOTIC_FEEDBACK_FM,
45 PLUCKED,
46 BOWED,
47 BLOWN,
48 FLUTED,
49 STRUCK_BELL,
50 STRUCK_DRUM,
51 KICK,
52 CYMBAL,
53 SNARE,
54 WAVETABLES,
55 WAVE_MAP,
56 WAV_LINE,
57 WAV_PARAPHONIC,
58 FILTERED_NOISE,
59 TWIN_PEAKS_NOISE,
60 CLOCKED_NOISE,
61 GRANULAR_CLOUD,
62 PARTICLE_NOISE,
63 DIGITAL_MOD,
64 MORSE_NOISE,
65}
66
67#[rustfmt::skip] const MACRO_SYNTH_COMMANDS : [&'static str; CommandPack::BASE_INSTRUMENT_COMMAND_COUNT + 1] = [
69 "VOL",
70 "PIT",
71 "FIN",
72 "OSC",
73 "TBR",
74 "COL",
75 "DEG",
76 "RED",
77 "FIL",
78 "CUT",
79 "RES",
80 "AMP",
81 "LIM",
82 "PAN",
83 "DRY",
84
85 "SCH",
86 "SDL",
87 "SRV",
88
89 "TRG"
91];
92
93#[rustfmt::skip] const DESTINATIONS : [&'static str; 15] = [
95 dests::OFF,
96 dests::VOLUME,
97 dests::PITCH,
98
99 "TIMBRE",
100 "COLOR",
101 dests::DEGRADE,
102 "REDUX",
103 dests::CUTOFF,
104 dests::RES,
105 dests::AMP,
106 dests::PAN,
107 dests::MOD_AMT,
108 dests::MOD_RATE,
109 dests::MOD_BOTH,
110 dests::MOD_BINV,
111];
112
113#[derive(PartialEq, Debug, Clone)]
114pub struct MacroSynth {
115 pub number: u8,
116 pub name: String, pub transpose: bool, pub table_tick: u8, pub synth_params: SynthParams, pub shape: MacroSynthOsc, pub timbre: u8, pub color: u8, pub degrade: u8, pub redux: u8, }
127
128impl MacroSynth {
129 pub const MOD_OFFSET: usize = 30;
130
131 pub fn command_name(&self, _ver: Version) -> &'static [&'static str] {
132 &MACRO_SYNTH_COMMANDS
133 }
134
135 pub fn destination_names(&self, _ver: Version) -> &'static [&'static str] {
136 &DESTINATIONS
137 }
138
139 pub fn human_readable_filter(&self) -> &'static str {
140 COMMON_FILTER_TYPES[self.synth_params.filter_type as usize]
141 }
142
143 pub fn write(&self, ver: Version, w: &mut Writer) {
144 w.write_string(&self.name, 12);
145 w.write(TranspEq::from(ver, self.transpose, self.synth_params.associated_eq).into());
146 w.write(self.table_tick);
147 w.write(self.synth_params.volume);
148 w.write(self.synth_params.pitch);
149 w.write(self.synth_params.fine_tune);
150
151 w.write(self.shape.into());
152 w.write(self.timbre);
153 w.write(self.color);
154 w.write(self.degrade);
155 w.write(self.redux);
156
157 self.synth_params.write(ver, w, MacroSynth::MOD_OFFSET);
158 }
159
160 pub fn from_reader(
161 ver: Version,
162 reader: &mut Reader,
163 number: u8,
164 version: Version,
165 ) -> M8Result<Self> {
166 let ms_pos = reader.pos();
167 let name = reader.read_string(12);
168
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 ofs_shape = reader.pos();
176 let shape = reader.read();
177 let timbre = reader.read();
178 let color = reader.read();
179 let degrade = reader.read();
180 let redux = reader.read();
181
182 let synth_params = if version.at_least(3, 0) {
183 SynthParams::from_reader3(
184 ver,
185 reader,
186 volume,
187 pitch,
188 fine_tune,
189 transp_eq.eq,
190 MacroSynth::MOD_OFFSET,
191 )?
192 } else {
193 SynthParams::from_reader2(reader, volume, pitch, fine_tune)?
194 };
195
196 let nc = name.clone();
197 Ok(MacroSynth {
198 number,
199 name,
200 transpose: transp_eq.transpose,
201 table_tick,
202 synth_params,
203
204 shape: shape.try_into().map_err(|_| {
205 ParseError(format!(
206 "I{number:X} Wrong macrosynth@{ms_pos} ({nc}) shape {shape}@0x{ofs_shape}"
207 ))
208 })?,
209 timbre,
210 color,
211 degrade,
212 redux,
213 })
214 }
215}