Skip to main content

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}