ot_tools_io/patterns/settings.rs
1/*
2SPDX-License-Identifier: GPL-3.0-or-later
3Copyright © 2024 Mike Robeson [dijksterhuis]
4*/
5
6use ot_tools_io_derive::{AsMutDerive, AsRefDerive};
7use serde::{Deserialize, Serialize};
8
9/// Pattern level scaling settings.
10/// Some of these settings still apply when the pattern is in Per-Track scaling mode.
11#[derive(
12 Copy,
13 Clone,
14 Debug,
15 Eq,
16 Hash,
17 Ord,
18 PartialEq,
19 PartialOrd,
20 Serialize,
21 Deserialize,
22 AsMutDerive,
23 AsRefDerive,
24)]
25pub struct PatternScaleSettings {
26 /// Multiply this value by `master_len_per_track` to get
27 /// the real Master Length in Per Track Pattern mode.
28 ///
29 /// This field must be set to `255` when Master Length in
30 /// Per Track Pattern mode is set to `INF`.
31 ///
32 /// ```text
33 /// 0: From 2 steps to 255 steps.
34 /// 1: From 256 steps to 511 steps.
35 /// 2: From 512 steps to 767 steps.
36 /// 3: From 768 steps to 1023 steps.
37 /// 4: 1024 steps only.
38 /// 255: `INF`.
39 /// ```
40 pub master_len_per_track_multiplier: u8,
41
42 /// Master Length in Per Track Pattern mode.
43 /// Must multiply this by multiplier like this `(x + 1) * (mult + 1)` to get the real number.
44 ///
45 /// This field must be set to `255` when Master Length in
46 /// Per Track Pattern mode is set to `INF`.
47 ///
48 /// Minimum value is 2 when the multiplier equals 0.
49 pub master_len_per_track: u8,
50
51 /// The Audio Track's Scale when Pattern is in Per Track mode.
52 ///
53 /// Options
54 /// ```text
55 /// 0 -> 2x
56 /// 1 -> 3/2x
57 /// 2 -> 1x (Default)
58 /// 3 -> 3/4x
59 /// 4 -> 1/2x
60 /// 5 -> 1/4x
61 /// 6 -> 1/8x
62 /// ```
63 pub master_scale_per_track: u8,
64
65 /// Master Pattern Length.
66 /// Determines Pattern Length for all Tracks when NOT in Per Track mode.
67 pub master_len: u8,
68
69 /// Master Pattern playback multiplier.
70 ///
71 /// Options
72 /// ```text
73 /// 0 -> 2x
74 /// 1 -> 3/2x
75 /// 2 -> 1x (Default)
76 /// 3 -> 3/4x
77 /// 4 -> 1/2x
78 /// 5 -> 1/4x
79 /// 6 -> 1/8x
80 /// ```
81 pub master_scale: u8,
82
83 /// Scale mode for the Pattern.
84 ///
85 /// Options
86 /// ```text
87 /// NORMAL: 0 (Default)
88 /// PER TRACK: 1
89 /// ```
90 pub scale_mode: u8,
91}
92
93// todo
94#[allow(dead_code)]
95enum MasterLenCalc {
96 PerTrack(u16),
97 Global(u16),
98 InvalidScaleMode(u16),
99}
100
101impl PatternScaleSettings {
102 #[allow(dead_code)]
103 fn calculate_master_length(&self) -> MasterLenCalc {
104 match self.scale_mode {
105 // normal
106 0 => MasterLenCalc::Global(self.master_len as u16),
107 // per-track
108 1 => MasterLenCalc::PerTrack(
109 (self.master_len_per_track as u16 + 1)
110 * (self.master_len_per_track_multiplier as u16 + 1),
111 ),
112 // something is wrong
113 _ => MasterLenCalc::InvalidScaleMode(self.scale_mode as u16),
114 }
115 }
116}
117
118impl Default for PatternScaleSettings {
119 fn default() -> Self {
120 Self {
121 master_len_per_track_multiplier: 0,
122 master_len_per_track: 16,
123 master_scale_per_track: 2,
124 master_len: 16,
125 master_scale: 2,
126 scale_mode: 0,
127 }
128 }
129}
130
131/// Chaining behaviour for the pattern.
132#[derive(
133 Copy,
134 Clone,
135 Debug,
136 Eq,
137 Hash,
138 Ord,
139 PartialEq,
140 PartialOrd,
141 Serialize,
142 Deserialize,
143 AsMutDerive,
144 AsRefDerive,
145)]
146pub struct PatternChainBehavior {
147 /// When `use_project_setting` field is set to `1`/`true`
148 /// this field should be set to `N/A` with a value of `255`.
149 pub use_pattern_setting: u8,
150
151 /// Pattern Chain Behaviour -- Use the Project level setting for chain
152 /// behaviour and disable any Pattern level chaining behaviour.
153 /// Numeric Boolean.
154 /// When this is `1` the `use_pattern_setting` should be set to `255`.
155 pub use_project_setting: u8,
156}
157
158// allow the verbose implementation to keep things
159// - (a) standardized across all types
160// - (b) easier for non-rustaceans to follow when reading through data structures
161#[allow(clippy::derivable_impls)]
162impl Default for PatternChainBehavior {
163 fn default() -> Self {
164 Self {
165 use_pattern_setting: 0,
166 use_project_setting: 0,
167 }
168 }
169}
170
171/// Audio & MIDI Track Pattern playback settings.
172#[derive(
173 Copy,
174 Clone,
175 Debug,
176 Eq,
177 Hash,
178 Ord,
179 PartialEq,
180 PartialOrd,
181 Serialize,
182 Deserialize,
183 AsMutDerive,
184 AsRefDerive,
185)]
186pub struct TrackPatternSettings {
187 /// Silence any existing audio playback on the Audio Track when switching Patterns.
188 pub start_silent: u8,
189
190 /// Trigger Audio Track playback without any quantization or syncing to other Audio Tracks.
191 pub plays_free: u8,
192
193 /// Quantization when this Audio Track is Triggered for Playback.
194 ///
195 /// Options
196 /// ```text
197 /// N/A and ONE: 0 (Default)
198 /// ONE2: 1
199 /// HOLD: 2
200 /// ```
201 pub trig_mode: u8,
202
203 /// Track Trigger Quantization.
204 ///
205 /// Options
206 /// ```text
207 /// N/A and TR.LEN: 0 (Default)
208 /// 1/16: 1
209 /// 2/16: 2
210 /// 3/16: 3
211 /// 4/16: 4
212 /// 6/16: 5
213 /// 8/16: 6
214 /// 12/16: 7
215 /// 16/16: 8
216 /// 24/16: 9
217 /// 32/16: 10
218 /// 48/16: 11
219 /// 64/16: 12
220 /// 96/16: 13
221 /// 128/16: 14
222 /// 192/16: 15
223 /// 256/16: 16
224 /// DIRECT: 255
225 /// ```
226 pub trig_quant: u8,
227
228 /// Whether to play the track as a `ONESHOT` track.
229 pub oneshot_trk: u8,
230}
231
232impl Default for TrackPatternSettings {
233 fn default() -> Self {
234 Self {
235 start_silent: 255,
236 plays_free: 0,
237 trig_mode: 0,
238 trig_quant: 0,
239 oneshot_trk: 0,
240 }
241 }
242}
243
244/// Audio Track custom scaling when the Pattern is in PER TRACK scale mode.
245#[derive(
246 Copy,
247 Clone,
248 Debug,
249 Eq,
250 Hash,
251 Ord,
252 PartialEq,
253 PartialOrd,
254 Serialize,
255 Deserialize,
256 AsMutDerive,
257 AsRefDerive,
258)]
259pub struct TrackPerTrackModeScale {
260 /// The Audio Track's Length when Pattern is in Per Track mode.
261 /// Default: 16
262 pub per_track_len: u8,
263
264 /// The Audio Track's Scale when Pattern is in Per Track mode.
265 ///
266 /// Options
267 /// ```text
268 /// 0 -> 2x
269 /// 1 -> 3/2x
270 /// 2 -> 1x (Default)
271 /// 3 -> 3/4x
272 /// 4 -> 1/2x
273 /// 5 -> 1/4x
274 /// 6 -> 1/8x
275 /// ```
276 pub per_track_scale: u8,
277}
278
279impl Default for TrackPerTrackModeScale {
280 fn default() -> Self {
281 Self {
282 per_track_len: 16,
283 per_track_scale: 2,
284 }
285 }
286}