ot_tools_io/samples/
options.rs

1/*
2SPDX-License-Identifier: GPL-3.0-or-later
3Copyright © 2024 Mike Robeson [dijksterhuis]
4*/
5
6//! Enums for Octatrack options realted to `SampleAttribute` files (`.ot` files).
7
8use crate::{OptionEnumValueConvert, OtToolsIoErrors, RBoxErr};
9use serde::{Deserialize, Serialize};
10
11/// Sample attributes Timestrech options.
12/// See Octatrack Manaul section 13.2.4 ATTRIBUTES
13#[derive(PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq)]
14pub enum SampleAttributeTimestrechMode {
15    /// No timestreching applied.
16    Off,
17
18    /// Regular timestreching.
19    #[default]
20    Normal,
21
22    /// Drum / Rythmic specific algorithm
23    Beat,
24}
25
26impl OptionEnumValueConvert for SampleAttributeTimestrechMode {
27    type T = SampleAttributeTimestrechMode;
28    type V = u32;
29
30    fn from_value(v: &Self::V) -> RBoxErr<Self::T> {
31        match v {
32            0 => Ok(SampleAttributeTimestrechMode::Off),
33            2 => Ok(SampleAttributeTimestrechMode::Normal),
34            3 => Ok(SampleAttributeTimestrechMode::Beat),
35            _ => Err(OtToolsIoErrors::NoMatchingOptionEnumValue.into()),
36        }
37    }
38
39    fn value(&self) -> RBoxErr<Self::V> {
40        match self {
41            SampleAttributeTimestrechMode::Off => Ok(0),
42            SampleAttributeTimestrechMode::Normal => Ok(2),
43            SampleAttributeTimestrechMode::Beat => Ok(3),
44        }
45    }
46}
47
48/// Sample attributes Loop mode options.
49/// See Octatrack Manaul section 13.2.4 ATTRIBUTES
50
51#[derive(PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq)]
52pub enum SampleAttributeLoopMode {
53    /// Loop points are ignored and sample will never loop.
54    #[default]
55    Off,
56
57    /// Loop by starting again at the loop start position once playback of the sample reaches loop end.
58    Normal,
59
60    /// Loop by continuously reversing once playback of the sample reaches loop end/loop start.
61    PingPong,
62}
63
64impl OptionEnumValueConvert for SampleAttributeLoopMode {
65    type T = SampleAttributeLoopMode;
66    type V = u32;
67
68    fn from_value(v: &Self::V) -> RBoxErr<Self::T> {
69        match v {
70            0 => Ok(SampleAttributeLoopMode::Off),
71            1 => Ok(SampleAttributeLoopMode::Normal),
72            2 => Ok(SampleAttributeLoopMode::PingPong),
73            _ => Err(OtToolsIoErrors::NoMatchingOptionEnumValue.into()),
74        }
75    }
76
77    fn value(&self) -> RBoxErr<Self::V> {
78        match self {
79            SampleAttributeLoopMode::Off => Ok(0),
80            SampleAttributeLoopMode::Normal => Ok(1),
81            SampleAttributeLoopMode::PingPong => Ok(2),
82        }
83    }
84}
85
86/// Sample attributes Trig Quantization options
87/// (quantization when manually triggering samples via track buttons).
88/// See Octatrack Manaul section 13.2.4 ATTRIBUTES
89
90#[derive(PartialEq, Debug, Clone, Default, Serialize, Deserialize, Copy, Hash, Eq)]
91pub enum SampleAttributeTrigQuantizationMode {
92    /// Play once the pattern ends
93    PatternLength,
94
95    /// Play back immediately, no quantization.
96    #[default]
97    Direct,
98
99    /// Play after 1 sequencer step(s).
100    OneStep,
101
102    /// Play after 2 sequencer step(s).
103    TwoSteps,
104
105    /// Play after 3 sequencer step(s).
106    ThreeSteps,
107
108    /// Play after 4 sequencer step(s).
109    FourSteps,
110
111    /// Play after 6 sequencer step(s).
112    SixSteps,
113
114    /// Play after 8 sequencer step(s).
115    EightSteps,
116
117    /// Play after 12 sequencer step(s).
118    TwelveSteps,
119
120    /// Play after 16 sequencer step(s).
121    SixteenSteps,
122
123    /// Play after 24 sequencer step(s).
124    TwentyFourSteps,
125
126    /// Play after 32 sequencer step(s).
127    ThirtyTwoSteps,
128
129    /// Play after 48 sequencer step(s).
130    FourtyEightSteps,
131
132    /// Play after 64 sequencer step(s).
133    SixtyFourSteps,
134
135    /// Play after 96 sequencer step(s).
136    NinetySixSteps,
137
138    /// Play after 128 sequencer step(s).
139    OneTwentyEightSteps,
140
141    /// Play after 192 sequencer step(s).
142    OneNinetyTwoSteps,
143
144    /// Play after 256 sequencer step(s).
145    TwoFiveSixSteps,
146}
147
148impl OptionEnumValueConvert for SampleAttributeTrigQuantizationMode {
149    type T = SampleAttributeTrigQuantizationMode;
150    type V = u32;
151
152    fn from_value(v: &Self::V) -> RBoxErr<Self::T> {
153        match v {
154            255 => Ok(SampleAttributeTrigQuantizationMode::Direct),
155            0 => Ok(SampleAttributeTrigQuantizationMode::PatternLength),
156            1 => Ok(SampleAttributeTrigQuantizationMode::OneStep),
157            2 => Ok(SampleAttributeTrigQuantizationMode::TwoSteps),
158            3 => Ok(SampleAttributeTrigQuantizationMode::ThreeSteps),
159            4 => Ok(SampleAttributeTrigQuantizationMode::FourSteps),
160            5 => Ok(SampleAttributeTrigQuantizationMode::SixSteps),
161            6 => Ok(SampleAttributeTrigQuantizationMode::EightSteps),
162            7 => Ok(SampleAttributeTrigQuantizationMode::TwelveSteps),
163            8 => Ok(SampleAttributeTrigQuantizationMode::SixteenSteps),
164            9 => Ok(SampleAttributeTrigQuantizationMode::TwentyFourSteps),
165            10 => Ok(SampleAttributeTrigQuantizationMode::ThirtyTwoSteps),
166            11 => Ok(SampleAttributeTrigQuantizationMode::FourtyEightSteps),
167            12 => Ok(SampleAttributeTrigQuantizationMode::SixtyFourSteps),
168            13 => Ok(SampleAttributeTrigQuantizationMode::NinetySixSteps),
169            14 => Ok(SampleAttributeTrigQuantizationMode::OneTwentyEightSteps),
170            15 => Ok(SampleAttributeTrigQuantizationMode::OneNinetyTwoSteps),
171            16 => Ok(SampleAttributeTrigQuantizationMode::TwoFiveSixSteps),
172            _ => Err(OtToolsIoErrors::NoMatchingOptionEnumValue.into()),
173        }
174    }
175
176    fn value(&self) -> RBoxErr<Self::V> {
177        match self {
178            SampleAttributeTrigQuantizationMode::Direct => Ok(255),
179            SampleAttributeTrigQuantizationMode::PatternLength => Ok(0),
180            SampleAttributeTrigQuantizationMode::OneStep => Ok(1),
181            SampleAttributeTrigQuantizationMode::TwoSteps => Ok(2),
182            SampleAttributeTrigQuantizationMode::ThreeSteps => Ok(3),
183            SampleAttributeTrigQuantizationMode::FourSteps => Ok(4),
184            SampleAttributeTrigQuantizationMode::SixSteps => Ok(5),
185            SampleAttributeTrigQuantizationMode::EightSteps => Ok(6),
186            SampleAttributeTrigQuantizationMode::TwelveSteps => Ok(7),
187            SampleAttributeTrigQuantizationMode::SixteenSteps => Ok(8),
188            SampleAttributeTrigQuantizationMode::TwentyFourSteps => Ok(9),
189            SampleAttributeTrigQuantizationMode::ThirtyTwoSteps => Ok(10),
190            SampleAttributeTrigQuantizationMode::FourtyEightSteps => Ok(11),
191            SampleAttributeTrigQuantizationMode::SixtyFourSteps => Ok(12),
192            SampleAttributeTrigQuantizationMode::NinetySixSteps => Ok(13),
193            SampleAttributeTrigQuantizationMode::OneTwentyEightSteps => Ok(14),
194            SampleAttributeTrigQuantizationMode::OneNinetyTwoSteps => Ok(15),
195            SampleAttributeTrigQuantizationMode::TwoFiveSixSteps => Ok(16),
196        }
197    }
198}
199
200/// "Specification" tests ... ie. guarantee that enum values match correct values.
201#[cfg(test)]
202#[allow(unused_imports)]
203mod test_spec {
204
205    mod ot_trig_quantize_mode {
206
207        mod value {
208            use crate::samples::options::SampleAttributeTrigQuantizationMode;
209            use crate::OptionEnumValueConvert;
210
211            #[test]
212            fn test_direct() {
213                assert_eq!(
214                    SampleAttributeTrigQuantizationMode::Direct.value().unwrap(),
215                    255
216                );
217            }
218            #[test]
219            fn test_patternlen() {
220                assert_eq!(
221                    SampleAttributeTrigQuantizationMode::PatternLength
222                        .value()
223                        .unwrap(),
224                    0
225                );
226            }
227            #[test]
228            fn test_1() {
229                assert_eq!(
230                    SampleAttributeTrigQuantizationMode::OneStep
231                        .value()
232                        .unwrap(),
233                    1
234                );
235            }
236            #[test]
237            fn test_2() {
238                assert_eq!(
239                    SampleAttributeTrigQuantizationMode::TwoSteps
240                        .value()
241                        .unwrap(),
242                    2
243                );
244            }
245            #[test]
246            fn test_3() {
247                assert_eq!(
248                    SampleAttributeTrigQuantizationMode::ThreeSteps
249                        .value()
250                        .unwrap(),
251                    3
252                );
253            }
254            #[test]
255            fn test_4() {
256                assert_eq!(
257                    SampleAttributeTrigQuantizationMode::FourSteps
258                        .value()
259                        .unwrap(),
260                    4
261                );
262            }
263            #[test]
264            fn test_6() {
265                assert_eq!(
266                    SampleAttributeTrigQuantizationMode::SixSteps
267                        .value()
268                        .unwrap(),
269                    5
270                );
271            }
272            #[test]
273            fn test_8() {
274                assert_eq!(
275                    SampleAttributeTrigQuantizationMode::EightSteps
276                        .value()
277                        .unwrap(),
278                    6
279                );
280            }
281            #[test]
282            fn test_12() {
283                assert_eq!(
284                    SampleAttributeTrigQuantizationMode::TwelveSteps
285                        .value()
286                        .unwrap(),
287                    7
288                );
289            }
290            #[test]
291            fn test_16() {
292                assert_eq!(
293                    SampleAttributeTrigQuantizationMode::SixteenSteps
294                        .value()
295                        .unwrap(),
296                    8
297                );
298            }
299            #[test]
300            fn test_24() {
301                assert_eq!(
302                    SampleAttributeTrigQuantizationMode::TwentyFourSteps
303                        .value()
304                        .unwrap(),
305                    9
306                );
307            }
308            #[test]
309            fn test_32() {
310                assert_eq!(
311                    SampleAttributeTrigQuantizationMode::ThirtyTwoSteps
312                        .value()
313                        .unwrap(),
314                    10
315                );
316            }
317            #[test]
318            fn test_48() {
319                assert_eq!(
320                    SampleAttributeTrigQuantizationMode::FourtyEightSteps
321                        .value()
322                        .unwrap(),
323                    11
324                );
325            }
326            #[test]
327            fn test_64() {
328                assert_eq!(
329                    SampleAttributeTrigQuantizationMode::SixtyFourSteps
330                        .value()
331                        .unwrap(),
332                    12
333                );
334            }
335            #[test]
336            fn test_96() {
337                assert_eq!(
338                    SampleAttributeTrigQuantizationMode::NinetySixSteps
339                        .value()
340                        .unwrap(),
341                    13
342                );
343            }
344            #[test]
345            fn test_128() {
346                assert_eq!(
347                    SampleAttributeTrigQuantizationMode::OneTwentyEightSteps
348                        .value()
349                        .unwrap(),
350                    14
351                );
352            }
353            #[test]
354            fn test_192() {
355                assert_eq!(
356                    SampleAttributeTrigQuantizationMode::OneNinetyTwoSteps
357                        .value()
358                        .unwrap(),
359                    15
360                );
361            }
362            #[test]
363            fn test_256() {
364                assert_eq!(
365                    SampleAttributeTrigQuantizationMode::TwoFiveSixSteps
366                        .value()
367                        .unwrap(),
368                    16
369                );
370            }
371        }
372
373        mod from_value {
374            use crate::samples::options::SampleAttributeTrigQuantizationMode;
375            use crate::OptionEnumValueConvert;
376
377            #[test]
378            fn test_error() {
379                assert!(SampleAttributeTrigQuantizationMode::from_value(&200).is_err());
380            }
381            #[test]
382            fn test_direct() {
383                assert_eq!(
384                    SampleAttributeTrigQuantizationMode::Direct,
385                    SampleAttributeTrigQuantizationMode::from_value(&255).unwrap()
386                );
387            }
388            #[test]
389            fn test_patternlen() {
390                assert_eq!(
391                    SampleAttributeTrigQuantizationMode::PatternLength,
392                    SampleAttributeTrigQuantizationMode::from_value(&0).unwrap()
393                );
394            }
395            #[test]
396            fn test_1() {
397                assert_eq!(
398                    SampleAttributeTrigQuantizationMode::OneStep,
399                    SampleAttributeTrigQuantizationMode::from_value(&1).unwrap()
400                );
401            }
402            #[test]
403            fn test_2() {
404                assert_eq!(
405                    SampleAttributeTrigQuantizationMode::TwoSteps,
406                    SampleAttributeTrigQuantizationMode::from_value(&2).unwrap()
407                );
408            }
409            #[test]
410            fn test_3() {
411                assert_eq!(
412                    SampleAttributeTrigQuantizationMode::ThreeSteps,
413                    SampleAttributeTrigQuantizationMode::from_value(&3).unwrap()
414                );
415            }
416            #[test]
417            fn test_4() {
418                assert_eq!(
419                    SampleAttributeTrigQuantizationMode::FourSteps,
420                    SampleAttributeTrigQuantizationMode::from_value(&4).unwrap()
421                );
422            }
423            #[test]
424            fn test_6() {
425                assert_eq!(
426                    SampleAttributeTrigQuantizationMode::SixSteps,
427                    SampleAttributeTrigQuantizationMode::from_value(&5).unwrap()
428                );
429            }
430            #[test]
431            fn test_8() {
432                assert_eq!(
433                    SampleAttributeTrigQuantizationMode::EightSteps,
434                    SampleAttributeTrigQuantizationMode::from_value(&6).unwrap()
435                );
436            }
437            #[test]
438            fn test_12() {
439                assert_eq!(
440                    SampleAttributeTrigQuantizationMode::TwelveSteps,
441                    SampleAttributeTrigQuantizationMode::from_value(&7).unwrap()
442                );
443            }
444            #[test]
445            fn test_16() {
446                assert_eq!(
447                    SampleAttributeTrigQuantizationMode::SixteenSteps,
448                    SampleAttributeTrigQuantizationMode::from_value(&8).unwrap()
449                );
450            }
451            #[test]
452            fn test_24() {
453                assert_eq!(
454                    SampleAttributeTrigQuantizationMode::TwentyFourSteps,
455                    SampleAttributeTrigQuantizationMode::from_value(&9).unwrap()
456                );
457            }
458            #[test]
459            fn test_32() {
460                assert_eq!(
461                    SampleAttributeTrigQuantizationMode::ThirtyTwoSteps,
462                    SampleAttributeTrigQuantizationMode::from_value(&10).unwrap()
463                );
464            }
465            #[test]
466            fn test_48() {
467                assert_eq!(
468                    SampleAttributeTrigQuantizationMode::FourtyEightSteps,
469                    SampleAttributeTrigQuantizationMode::from_value(&11).unwrap()
470                );
471            }
472            #[test]
473            fn test_64() {
474                assert_eq!(
475                    SampleAttributeTrigQuantizationMode::SixtyFourSteps,
476                    SampleAttributeTrigQuantizationMode::from_value(&12).unwrap()
477                );
478            }
479            #[test]
480            fn test_96() {
481                assert_eq!(
482                    SampleAttributeTrigQuantizationMode::NinetySixSteps,
483                    SampleAttributeTrigQuantizationMode::from_value(&13).unwrap()
484                );
485            }
486            #[test]
487            fn test_128() {
488                assert_eq!(
489                    SampleAttributeTrigQuantizationMode::OneTwentyEightSteps,
490                    SampleAttributeTrigQuantizationMode::from_value(&14).unwrap()
491                );
492            }
493            #[test]
494            fn test_192() {
495                assert_eq!(
496                    SampleAttributeTrigQuantizationMode::OneNinetyTwoSteps,
497                    SampleAttributeTrigQuantizationMode::from_value(&15).unwrap()
498                );
499            }
500            #[test]
501            fn test_256() {
502                assert_eq!(
503                    SampleAttributeTrigQuantizationMode::TwoFiveSixSteps,
504                    SampleAttributeTrigQuantizationMode::from_value(&16).unwrap()
505                );
506            }
507        }
508    }
509
510    mod ot_timestrech_mode {
511
512        mod value {
513            use crate::samples::options::SampleAttributeTimestrechMode;
514            use crate::OptionEnumValueConvert;
515
516            #[test]
517            fn test_off_value() {
518                assert_eq!(SampleAttributeTimestrechMode::Off.value().unwrap(), 0);
519            }
520            #[test]
521            fn test_normal_value() {
522                assert_eq!(SampleAttributeTimestrechMode::Normal.value().unwrap(), 2);
523            }
524            #[test]
525            fn test_beat_value() {
526                assert_eq!(SampleAttributeTimestrechMode::Beat.value().unwrap(), 3);
527            }
528        }
529
530        mod from_value {
531            use crate::samples::options::SampleAttributeTimestrechMode;
532            use crate::OptionEnumValueConvert;
533
534            #[test]
535            fn test_error() {
536                // not in a sequental range with other values
537                // dunno why they implemented it to skip value of 1, possible bug or easter egg?
538                assert!(SampleAttributeTimestrechMode::from_value(&1).is_err());
539                // do a slightly exhausitve check, but don't test the whole u32 range
540                // as it's not worth the performance drain
541                for i in 4..u8::MAX {
542                    let b = i as u32;
543                    assert!(SampleAttributeTimestrechMode::from_value(&b).is_err());
544                }
545            }
546            #[test]
547            fn test_off_from_value() {
548                assert_eq!(
549                    SampleAttributeTimestrechMode::Off,
550                    SampleAttributeTimestrechMode::from_value(&0).unwrap()
551                );
552            }
553            #[test]
554            fn test_normal_from_value() {
555                assert_eq!(
556                    SampleAttributeTimestrechMode::Normal,
557                    SampleAttributeTimestrechMode::from_value(&2).unwrap()
558                );
559            }
560            #[test]
561            fn test_beat_from_value() {
562                assert_eq!(
563                    SampleAttributeTimestrechMode::Beat,
564                    SampleAttributeTimestrechMode::from_value(&3).unwrap()
565                );
566            }
567        }
568    }
569
570    mod ot_loop_mode {
571
572        mod value {
573            use crate::samples::options::SampleAttributeLoopMode;
574            use crate::OptionEnumValueConvert;
575
576            #[test]
577            fn test_off_value() {
578                assert_eq!(SampleAttributeLoopMode::Off.value().unwrap(), 0);
579            }
580            #[test]
581            fn test_normal_value() {
582                assert_eq!(SampleAttributeLoopMode::Normal.value().unwrap(), 1);
583            }
584            #[test]
585            fn test_beat_value() {
586                assert_eq!(SampleAttributeLoopMode::PingPong.value().unwrap(), 2);
587            }
588        }
589
590        mod from_value {
591            use crate::samples::options::SampleAttributeLoopMode;
592            use crate::OptionEnumValueConvert;
593
594            #[test]
595            fn test_error() {
596                // do a slightly exhausitve check, but don't test the whole u32 range
597                // as it's not worth the performance drain
598                for i in 3..u8::MAX {
599                    let x = i as u32;
600                    assert!(SampleAttributeLoopMode::from_value(&x).is_err());
601                }
602            }
603            #[test]
604            fn test_off_from_value() {
605                assert_eq!(
606                    SampleAttributeLoopMode::Off,
607                    SampleAttributeLoopMode::from_value(&0).unwrap()
608                );
609            }
610            #[test]
611            fn test_normal_from_value() {
612                assert_eq!(
613                    SampleAttributeLoopMode::Normal,
614                    SampleAttributeLoopMode::from_value(&1).unwrap()
615                );
616            }
617            #[test]
618            fn test_beat_from_value() {
619                assert_eq!(
620                    SampleAttributeLoopMode::PingPong,
621                    SampleAttributeLoopMode::from_value(&2).unwrap()
622                );
623            }
624        }
625    }
626}