rusty_daw_core/
time.rs

1//! Structs for accurate timekeeping in musical audio applications.
2
3use std::hash::Hash;
4use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
5
6/// (`56,448,000`) This number was chosen because it is nicely divisible by a whole slew of factors
7/// including `2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 24, 32, 64, 128, 256, 512, 1024,
8/// and 1920`, as well as common sampling rates such as `22050, 24000, 44100, 48000, 88200, 96000,
9/// 176400, and 192000`. This ensures that any recording of note or sample data in this format
10/// will always be at-least sample-accurate.
11pub static SUPER_UNITS: u32 = 56_448_000;
12
13/// Sampling rate in samples per second.
14#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
15pub struct SampleRate(pub f64);
16
17impl SampleRate {
18    pub fn new(sample_rate: f64) -> Self {
19        assert!(sample_rate > 0.0);
20
21        SampleRate(sample_rate)
22    }
23
24    /// Returns the reciprocal of the sample rate (`1.0 / sample_rate`).
25    ///
26    /// Note this is *NOT* cached, so this will always use a division operation.
27    pub fn recip(&self) -> f64 {
28        self.0.recip()
29    }
30
31    pub fn as_f32(&self) -> f32 {
32        self.0 as f32
33    }
34
35    pub fn as_f64(&self) -> f64 {
36        self.0 as f64
37    }
38
39    pub fn as_u16(&self) -> u16 {
40        self.0.round() as u16
41    }
42
43    pub fn as_u32(&self) -> u32 {
44        self.0.round() as u32
45    }
46
47    pub fn as_usize(&self) -> usize {
48        self.0.round() as usize
49    }
50}
51
52impl Default for SampleRate {
53    fn default() -> Self {
54        SampleRate(44_100.0)
55    }
56}
57
58impl From<u16> for SampleRate {
59    fn from(sr: u16) -> Self {
60        SampleRate(f64::from(sr))
61    }
62}
63impl From<u32> for SampleRate {
64    fn from(sr: u32) -> Self {
65        SampleRate(f64::from(sr))
66    }
67}
68impl From<f32> for SampleRate {
69    fn from(sr: f32) -> Self {
70        SampleRate(f64::from(sr))
71    }
72}
73impl From<f64> for SampleRate {
74    fn from(sr: f64) -> Self {
75        SampleRate(sr)
76    }
77}
78
79impl Mul<SampleRate> for f32 {
80    type Output = Self;
81    fn mul(self, rhs: SampleRate) -> Self::Output {
82        self * rhs.0 as f32
83    }
84}
85impl Mul<SampleRate> for f64 {
86    type Output = Self;
87    fn mul(self, rhs: SampleRate) -> Self::Output {
88        self * rhs.0
89    }
90}
91impl Div<SampleRate> for f32 {
92    type Output = Self;
93    fn div(self, rhs: SampleRate) -> Self::Output {
94        self / rhs.0 as f32
95    }
96}
97impl Div<SampleRate> for f64 {
98    type Output = Self;
99    fn div(self, rhs: SampleRate) -> Self::Output {
100        self / rhs.0
101    }
102}
103
104/// Musical time in units of beats + super-beats.
105///
106/// Note this value is always positive.
107#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
108pub struct MusicalTime {
109    /// The time in musical beats.
110    beats: u32,
111
112    /// The number of super-beats (after the time in `self.beats`). A "super-beat" is a unit of time
113    /// equal to 1 / 508,032,000 of a beat. This will auto-wrap so this will always be within the
114    /// range `[0, 508,032,000)`.
115    ///
116    /// This number was chosen because it is nicely divisible by a whole slew of factors
117    /// including `2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 18, 20, 24, 32, 64, 128, 256, 512,
118    /// and 1920`, as well as common sampling rates such as `22050, 24000, 44100, 48000, 88200, 96000,
119    /// 176400, and 192000`. This ensures that any recording of note data in this format will always be
120    /// at-least sample-accurate.
121    super_beats: u32,
122}
123
124impl MusicalTime {
125    /// * `beats` - The time in musical beats.
126    /// * `super_beats` - The number of super-beats (after the time in `self.beats`) (Note this value
127    /// will be constrained to the range `[0, 508,032,000)`).
128    ///
129    /// A "super-beat" is a unit of time equal to 1 / 508,032,000 of a beat. This number was chosen
130    /// because it is nicely divisible by a whole slew of factors including `2, 3, 4, 5, 6, 7, 8, 9,
131    /// 10, 12, 14, 15, 16, 18, 20, 24, 32, 64, 128, 256, 512, and 1920`, as well as common sampling
132    /// rates such as `22050, 24000, 44100, 48000, 88200, 96000, 176400, and 192000`. This ensures that
133    /// any recording of note data in this format will always be at-least sample-accurate.
134    pub fn new(beats: u32, super_beats: u32) -> Self {
135        Self {
136            beats,
137            super_beats: super_beats.min(SUPER_UNITS - 1),
138        }
139    }
140
141    /// The time in musical beats.
142    pub fn beats(&self) -> u32 {
143        self.beats
144    }
145
146    /// The number of super-beats (after the time in `self.beats()`).
147    ///
148    /// A "super-beat" is a unit of time equal to 1 / 508,032,000 of a beat. This number was chosen
149    /// because it is nicely divisible by a whole slew of factors including `2, 3, 4, 5, 6, 7, 8, 9,
150    /// 10, 12, 14, 15, 16, 18, 20, 24, 32, 64, 128, 256, 512, and 1920`, as well as common sampling
151    /// rates such as `22050, 24000, 44100, 48000, 88200, 96000, 176400, and 192000`. This ensures that
152    /// any recording of note data in this format will always be at-least sample-accurate.
153    ///
154    /// This value will always be in the range `[0, 508,032,000)`.
155    pub fn super_beats(&self) -> u32 {
156        self.super_beats
157    }
158
159    /// * `beats` - The time in musical beats.
160    pub fn from_beats(beats: u32) -> Self {
161        Self {
162            beats,
163            super_beats: 0,
164        }
165    }
166
167    /// * `beats` - The time in musical beats.
168    /// * `half_beats` - The number of half-beats (after the time `beats`). This will be
169    /// constrained to the range `[0, 1]`.
170    pub fn from_half_beats(beats: u32, half_beats: u32) -> Self {
171        static N: u32 = 2;
172
173        Self {
174            beats,
175            super_beats: half_beats.min(N - 1) * (SUPER_UNITS / N),
176        }
177    }
178
179    /// * `beats` - The time in musical beats.
180    /// * `quarter_beats` - The number of quarter-beats (after the time `beats`). This will be
181    /// constrained to the range `[0, 3]`.
182    pub fn from_quarter_beats(beats: u32, quarter_beats: u32) -> Self {
183        static N: u32 = 4;
184
185        Self {
186            beats,
187            super_beats: quarter_beats.min(N - 1) * (SUPER_UNITS / N),
188        }
189    }
190
191    /// * `beats` - The time in musical beats.
192    /// * `eighth_beats` - The number of eighth-beats (after the time `beats`). This will be
193    /// constrained to the range `[0, 7]`.
194    pub fn from_eighth_beats(beats: u32, eighth_beats: u32) -> Self {
195        static N: u32 = 8;
196
197        Self {
198            beats,
199            super_beats: eighth_beats.min(N - 1) * (SUPER_UNITS / N),
200        }
201    }
202
203    /// * `beats` - The time in musical beats.
204    /// * `sixteenth_beats` - The number of sixteenth-beats (after the time `beats`). This will be
205    /// constrained to the range `[0, 15]`.
206    pub fn from_sixteenth_beats(beats: u32, sixteenth_beats: u32) -> Self {
207        static N: u32 = 16;
208
209        Self {
210            beats,
211            super_beats: sixteenth_beats.min(N - 1) * (SUPER_UNITS / N),
212        }
213    }
214
215    /// * `beats` - The time in musical beats.
216    /// * `_32nd_beats` - The number of 32nd-beats (after the time `beats`). This will be
217    /// constrained to the range `[0, 31]`.
218    pub fn from_32nd_beats(beats: u32, _32nd_beats: u32) -> Self {
219        static N: u32 = 32;
220
221        Self {
222            beats,
223            super_beats: _32nd_beats.min(N - 1) * (SUPER_UNITS / N),
224        }
225    }
226
227    /// * `beats` - The time in musical beats.
228    /// * `_64th_beats` - The number of 64th-beats (after the time `beats`). This will be
229    /// constrained to the range `[0, 63]`.
230    pub fn from_64th_beats(beats: u32, _64th_beats: u32) -> Self {
231        static N: u32 = 64;
232
233        Self {
234            beats,
235            super_beats: _64th_beats.min(N - 1) * (SUPER_UNITS / N),
236        }
237    }
238
239    /// * `beats` - The time in musical beats.
240    /// * `_128th_beats` - The number of 128th-beats (after the time `beats`). This will be
241    /// constrained to the range `[0, 127]`.
242    pub fn from_128th_beats(beats: u32, _128th_beats: u32) -> Self {
243        static N: u32 = 128;
244
245        Self {
246            beats,
247            super_beats: _128th_beats.min(N - 1) * (SUPER_UNITS / N),
248        }
249    }
250
251    /// * `beats` - The time in musical beats.
252    /// * `third_beats` - The number of third-beats (after the time `beats`). This will be
253    /// constrained to the range `[0, 2]`.
254    pub fn from_third_beats(beats: u32, third_beats: u32) -> Self {
255        static N: u32 = 3;
256
257        Self {
258            beats,
259            super_beats: third_beats.min(N - 1) * (SUPER_UNITS / N),
260        }
261    }
262
263    /// * `beats` - The time in musical beats.
264    /// * `fifth_beats` - The number of fifth-beats (after the time `beats`). This will be
265    /// constrained to the range `[0, 4]`.
266    pub fn from_fifth_beats(beats: u32, fifth_beats: u32) -> Self {
267        static N: u32 = 5;
268
269        Self {
270            beats,
271            super_beats: fifth_beats.min(N - 1) * (SUPER_UNITS / N),
272        }
273    }
274
275    /// * `beats` - The time in musical beats.
276    /// * `sixth_beats` - The number of sixth-beats (after the time `beats`). This will be
277    /// constrained to the range `[0, 5]`.
278    pub fn from_sixth_beats(beats: u32, fifth_beats: u32) -> Self {
279        static N: u32 = 6;
280
281        Self {
282            beats,
283            super_beats: fifth_beats.min(N - 1) * (SUPER_UNITS / N),
284        }
285    }
286
287    /// * `beats` - The time in musical beats.
288    /// * `seventh_beats` - The number of seventh-beats (after the time `beats`). This will be
289    /// constrained to the range `[0, 6]`.
290    pub fn from_seventh_beats(beats: u32, seventh_beats: u32) -> Self {
291        static N: u32 = 7;
292
293        Self {
294            beats,
295            super_beats: seventh_beats.min(N - 1) * (SUPER_UNITS / N),
296        }
297    }
298
299    /// * `beats` - The time in musical beats.
300    /// * `ninth_beats` - The number of ninth-beats (after the time `beats`). This will be
301    /// constrained to the range `[0, 8]`.
302    pub fn from_ninth_beats(beats: u32, ninth_beats: u32) -> Self {
303        static N: u32 = 9;
304
305        Self {
306            beats,
307            super_beats: ninth_beats.min(N - 1) * (SUPER_UNITS / N),
308        }
309    }
310
311    /// * `beats` - The time in musical beats.
312    /// * `tenth_beats` - The number of tenth-beats (after the time `beats`). This will be
313    /// constrained to the range `[0, 9]`.
314    pub fn from_tenth_beats(beats: u32, tenth_beats: u32) -> Self {
315        static N: u32 = 10;
316
317        Self {
318            beats,
319            super_beats: tenth_beats.min(N - 1) * (SUPER_UNITS / N),
320        }
321    }
322
323    /// * `beats` - The time in musical beats.
324    /// * `twelth_beats` - The number of twelth-beats (after the time `beats`). This will be
325    /// constrained to the range `[0, 11]`.
326    pub fn from_twelth_beats(beats: u32, twelth_beats: u32) -> Self {
327        static N: u32 = 12;
328
329        Self {
330            beats,
331            super_beats: twelth_beats.min(N - 1) * (SUPER_UNITS / N),
332        }
333    }
334
335    /// * `beats` - The time in musical beats.
336    /// * `_24th_beats` - The number of 24th-beats (after the time `beats`). This will be
337    /// constrained to the range `[0, 23]`.
338    pub fn from_24th_beats(beats: u32, _24th_beats: u32) -> Self {
339        static N: u32 = 24;
340
341        Self {
342            beats,
343            super_beats: _24th_beats.min(N - 1) * (SUPER_UNITS / N),
344        }
345    }
346
347    /// Get the corresponding musical time from the number of beats (as an `f64`).
348    ///
349    /// Note that this conversion is *NOT* lossless.
350    ///
351    /// If `beats` is negative, then a MusicalTime of 0 will be returned instead.
352    pub fn from_beats_f64(beats: f64) -> Self {
353        if beats > 0.0 {
354            Self {
355                beats: beats.floor() as u32,
356                super_beats: (beats.fract() * f64::from(SUPER_UNITS)).round() as u32,
357            }
358        } else {
359            Self {
360                beats: 0,
361                super_beats: 0,
362            }
363        }
364    }
365
366    /// Convert the corresponding musical time in units of beats (as an `f64` value).
367    ///
368    /// Note that this conversion is *NOT* lossless.
369    ///
370    /// This is useful for displaying notes in UI.
371    pub fn as_beats_f64(&self) -> f64 {
372        f64::from(self.beats) + (f64::from(self.super_beats) / f64::from(SUPER_UNITS))
373    }
374
375    pub fn snap_to_nearest_beat(&self) -> MusicalTime {
376        let beats = if self.super_beats < (SUPER_UNITS / 2) {
377            self.beats
378        } else {
379            self.beats + 1
380        };
381
382        MusicalTime {
383            beats,
384            super_beats: 0,
385        }
386    }
387
388    /// Snap to the nearest multiple of whole beats.
389    pub fn snap_to_nearest_whole_beats(&self, beats: u32) -> MusicalTime {
390        let nearest_beat = self.snap_to_nearest_beat();
391        let mut new_beats = (nearest_beat.beats % beats) * beats;
392        if nearest_beat.beats - new_beats >= beats / 2 {
393            new_beats += beats / 2;
394        }
395
396        MusicalTime {
397            beats: new_beats,
398            super_beats: 0,
399        }
400    }
401
402    pub fn snap_to_nearest_fractional_beat<const DIVISOR: u32>(&self) -> MusicalTime {
403        let mut beats = self.beats;
404        let mut super_beats =
405            (self.super_beats % (SUPER_UNITS / DIVISOR)) * (SUPER_UNITS / DIVISOR);
406        if self.super_beats - super_beats >= (SUPER_UNITS / DIVISOR) / 2 {
407            super_beats += SUPER_UNITS / DIVISOR;
408        }
409        if super_beats >= SUPER_UNITS {
410            beats += 1;
411            super_beats = 0;
412        }
413
414        MusicalTime { beats, super_beats }
415    }
416
417    pub fn snap_to_nearest_half_beat(&self) -> MusicalTime {
418        self.snap_to_nearest_fractional_beat::<2>()
419    }
420
421    pub fn snap_to_nearest_quarter_beat(&self) -> MusicalTime {
422        self.snap_to_nearest_fractional_beat::<4>()
423    }
424
425    pub fn snap_to_nearest_eigth_beat(&self) -> MusicalTime {
426        self.snap_to_nearest_fractional_beat::<8>()
427    }
428
429    pub fn snap_to_nearest_sixteenth_beat(&self) -> MusicalTime {
430        self.snap_to_nearest_fractional_beat::<16>()
431    }
432
433    pub fn snap_to_nearest_32nd_beat(&self) -> MusicalTime {
434        self.snap_to_nearest_fractional_beat::<32>()
435    }
436
437    pub fn snap_to_nearest_64th_beat(&self) -> MusicalTime {
438        self.snap_to_nearest_fractional_beat::<64>()
439    }
440
441    pub fn snap_to_nearest_128th_beat(&self) -> MusicalTime {
442        self.snap_to_nearest_fractional_beat::<128>()
443    }
444
445    pub fn snap_to_nearest_third_beat(&self) -> MusicalTime {
446        self.snap_to_nearest_fractional_beat::<3>()
447    }
448
449    pub fn snap_to_nearest_fifth_beat(&self) -> MusicalTime {
450        self.snap_to_nearest_fractional_beat::<5>()
451    }
452
453    pub fn snap_to_nearest_sixth_beat(&self) -> MusicalTime {
454        self.snap_to_nearest_fractional_beat::<6>()
455    }
456
457    pub fn snap_to_nearest_seventh_beat(&self) -> MusicalTime {
458        self.snap_to_nearest_fractional_beat::<7>()
459    }
460
461    pub fn snap_to_nearest_ninth_beat(&self) -> MusicalTime {
462        self.snap_to_nearest_fractional_beat::<9>()
463    }
464
465    pub fn snap_to_nearest_tenth_beat(&self) -> MusicalTime {
466        self.snap_to_nearest_fractional_beat::<10>()
467    }
468
469    pub fn snap_to_nearest_twelth_beat(&self) -> MusicalTime {
470        self.snap_to_nearest_fractional_beat::<12>()
471    }
472
473    pub fn snap_to_nearest_24th_beat(&self) -> MusicalTime {
474        self.snap_to_nearest_fractional_beat::<24>()
475    }
476
477    /// The number of fractional-beats *after* `self.beats()` (floored to
478    /// the nearest fractional-beat).
479    ///
480    /// This will always be in the range `[0, DIVISOR - 1]`.
481    pub fn num_fractional_beats<const DIVISOR: u32>(&self) -> u32 {
482        self.super_beats % (SUPER_UNITS / DIVISOR)
483    }
484
485    /// The number of half-beats *after* `self.beats()` (floored to
486    /// the nearest half-beat).
487    ///
488    /// This will always be in the range `[0, 1]`.
489    pub fn num_half_beats(&self) -> u32 {
490        self.num_fractional_beats::<2>()
491    }
492
493    /// The number of quarter-beats *after* `self.beats()` (floored to
494    /// the nearest quarter-beat).
495    ///
496    /// This will always be in the range `[0, 3]`.
497    pub fn num_quarter_beats(&self) -> u32 {
498        self.num_fractional_beats::<4>()
499    }
500
501    /// The number of eigth-beats *after* `self.beats()` (floored to
502    /// the nearest eigth-beat).
503    ///
504    /// This will always be in the range `[0, 7]`.
505    pub fn num_eigth_beats(&self) -> u32 {
506        self.num_fractional_beats::<8>()
507    }
508
509    /// The number of sixteenth-beats *after* `self.beats()` (floored to
510    /// the nearest sixteenth-beat).
511    ///
512    /// This will always be in the range `[0, 15]`.
513    pub fn num_sixteenth_beats(&self) -> u32 {
514        self.num_fractional_beats::<16>()
515    }
516
517    /// The number of 32nd-beats *after* `self.beats()` (floored to
518    /// the nearest 32nd-beat).
519    ///
520    /// This will always be in the range `[0, 31]`.
521    pub fn num_32nd_beats(&self) -> u32 {
522        self.num_fractional_beats::<32>()
523    }
524
525    /// The number of 128th-beats *after* `self.beats()` (floored to
526    /// the nearest 64th-beat).
527    ///
528    /// This will always be in the range `[0, 63]`.
529    pub fn num_64th_beats(&self) -> u32 {
530        self.num_fractional_beats::<64>()
531    }
532
533    /// The number of 64th-beats *after* `self.beats()` (floored to
534    /// the nearest 128th-beat).
535    ///
536    /// This will always be in the range `[0, 127]`.
537    pub fn num_128th_beats(&self) -> u32 {
538        self.num_fractional_beats::<128>()
539    }
540
541    /// The number of third-beats *after* `self.beats()` (floored to
542    /// the nearest third-beat).
543    ///
544    /// This will always be in the range `[0, 2]`.
545    pub fn num_third_beats(&self) -> u32 {
546        self.num_fractional_beats::<3>()
547    }
548
549    /// The number of fifth-beats *after* `self.beats()` (floored to
550    /// the nearest fifth-beat).
551    ///
552    /// This will always be in the range `[0, 4]`.
553    pub fn num_fifth_beats(&self) -> u32 {
554        self.num_fractional_beats::<5>()
555    }
556
557    /// The number of sixth-beats *after* `self.beats()` (floored to
558    /// the nearest sixth-beat).
559    ///
560    /// This will always be in the range `[0, 5]`.
561    pub fn num_sixth_beats(&self) -> u32 {
562        self.num_fractional_beats::<6>()
563    }
564
565    /// The number of seventh-beats *after* `self.beats()` (floored to
566    /// the nearest seventh-beat).
567    ///
568    /// This will always be in the range `[0, 6]`.
569    pub fn num_seventh_beats(&self) -> u32 {
570        self.num_fractional_beats::<7>()
571    }
572
573    /// The number of ninth-beats *after* `self.beats()` (floored to
574    /// the nearest ninth-beat).
575    ///
576    /// This will always be in the range `[0, 8]`.
577    pub fn num_ninth_beats(&self) -> u32 {
578        self.num_fractional_beats::<9>()
579    }
580
581    /// The number of tenth-beats *after* `self.beats()` (floored to
582    /// the nearest tenth-beat).
583    ///
584    /// This will always be in the range `[0, 9]`.
585    pub fn num_tenth_beats(&self) -> u32 {
586        self.num_fractional_beats::<10>()
587    }
588
589    /// The number of twelth-beats *after* `self.beats()` (floored to
590    /// the nearest twelth-beat).
591    ///
592    /// This will always be in the range `[0, 11]`.
593    pub fn num_twelth_beats(&self) -> u32 {
594        self.num_fractional_beats::<12>()
595    }
596
597    /// The number of 24th-beats *after* `self.beats()` (floored to
598    /// the nearest 24th-beat).
599    ///
600    /// This will always be in the range `[0, 23]`.
601    pub fn num_24th_beats(&self) -> u32 {
602        self.num_fractional_beats::<24>()
603    }
604
605    /// Convert to the corresponding time in [`Seconds`].
606    ///
607    /// Note that this conversion is *NOT* lossless.
608    ///
609    /// [`Seconds`]: struct.Seconds.html
610    pub fn to_seconds(&self, bpm: f64) -> Seconds {
611        Seconds(self.as_beats_f64() * 60.0 / bpm)
612    }
613
614    /// Convert to the corresponding discrete [`Frames`]. This will be rounded to the nearest sample.
615    ///
616    /// Note that this conversion is *NOT* lossless.
617    ///
618    /// Note that this must be re-calculated after recieving a new [`SampleRate`].
619    ///
620    /// [`Frames`]: struct.Frames.html
621    pub fn to_nearest_frame_round(&self, bpm: f64, sample_rate: SampleRate) -> Frames {
622        self.to_seconds(bpm).to_nearest_frame_round(sample_rate)
623    }
624
625    /// Convert to the corresponding discrete [`Frames`]. This will be floored to the nearest sample.
626    ///
627    /// Note that this conversion is *NOT* lossless.
628    ///
629    /// Note that this must be re-calculated after recieving a new [`SampleRate`].
630    ///
631    /// [`Frames`]: struct.Frames.html
632    pub fn to_nearest_frame_floor(&self, bpm: f64, sample_rate: SampleRate) -> Frames {
633        self.to_seconds(bpm).to_nearest_frame_floor(sample_rate)
634    }
635
636    /// Convert to the corresponding discrete [`Frames`]. This will be ceil-ed to the nearest sample.
637    ///
638    /// Note that this conversion is *NOT* lossless.
639    ///
640    /// Note that this must be re-calculated after recieving a new [`SampleRate`].
641    ///
642    /// [`Frames`]: struct.Frames.html
643    pub fn to_nearest_frame_ceil(&self, bpm: f64, sample_rate: SampleRate) -> Frames {
644        self.to_seconds(bpm).to_nearest_frame_ceil(sample_rate)
645    }
646
647    /// Convert to the corresponding discrete [`Frames`] floored to the nearest sample,
648    /// while also returning the fractional sub-sample part.
649    ///
650    /// Note that this conversion is *NOT* lossless.
651    ///
652    /// Note that this must be re-calculated after recieving a new [`SampleRate`].
653    ///
654    /// [`Frames`]: struct.Frames.html
655    pub fn to_sub_frames(&self, bpm: f64, sample_rate: SampleRate) -> (Frames, f64) {
656        self.to_seconds(bpm).to_sub_frames(sample_rate)
657    }
658
659    /// Convert to the corresponding discrete [`SuperFrames`]. This will be rounded to the nearest super-frame.
660    ///
661    /// Note that this conversion is *NOT* lossless.
662    ///
663    /// [`SuperFrames`]: struct.SuperFrames.html
664    pub fn to_nearest_super_frame_round(&self, bpm: f64) -> SuperFrames {
665        self.to_seconds(bpm).to_nearest_super_frame_round()
666    }
667
668    /// Convert to the corresponding discrete [`SuperFrames`]. This will be floored to the nearest super-frame.
669    ///
670    /// Note that this conversion is *NOT* lossless.
671    ///
672    /// [`SuperFrames`]: struct.SuperFrames.html
673    pub fn to_nearest_super_frame_floor(&self, bpm: f64) -> SuperFrames {
674        self.to_seconds(bpm).to_nearest_super_frame_floor()
675    }
676
677    /// Convert to the corresponding discrete [`SuperFrames`]. This will be ceil-ed to the nearest super-frame.
678    ///
679    /// Note that this conversion is *NOT* lossless.
680    ///
681    /// [`SuperFrames`]: struct.SuperFrames.html
682    pub fn to_nearest_super_frame_ceil(&self, bpm: f64) -> SuperFrames {
683        self.to_seconds(bpm).to_nearest_super_frame_ceil()
684    }
685
686    /// Convert to the corresponding discrete [`SuperFrames`] floored to the nearest super-frame,
687    /// while also returning the fractional sub-super-frame part.
688    ///
689    /// Note that this conversion is *NOT* lossless.
690    ///
691    /// [`SuperFrames`]: struct.SuperFrames.html
692    pub fn to_sub_super_frames(&self, bpm: f64) -> (SuperFrames, f64) {
693        self.to_seconds(bpm).to_sub_super_frames()
694    }
695
696    /// Try subtracting `rhs` from self. This will return `None` if the resulting value
697    /// is negative due to `rhs` being larger than self (overflow).
698    pub fn checked_sub(self, rhs: MusicalTime) -> Option<MusicalTime> {
699        if self >= rhs {
700            let mut beats = self.beats - rhs.beats;
701            let super_beats = if self.super_beats < rhs.super_beats {
702                beats -= 1;
703                SUPER_UNITS - (rhs.super_beats - self.super_beats)
704            } else {
705                self.super_beats - rhs.super_beats
706            };
707
708            Some(Self { beats, super_beats })
709        } else {
710            None
711        }
712    }
713}
714
715impl Default for MusicalTime {
716    fn default() -> Self {
717        MusicalTime {
718            beats: 0,
719            super_beats: 0,
720        }
721    }
722}
723
724impl PartialOrd for MusicalTime {
725    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
726        match self.beats.partial_cmp(&other.beats) {
727            Some(std::cmp::Ordering::Equal) => self.super_beats.partial_cmp(&other.super_beats),
728            res => res,
729        }
730    }
731}
732
733impl Add<MusicalTime> for MusicalTime {
734    type Output = Self;
735    fn add(self, rhs: Self) -> Self::Output {
736        let mut beats = self.beats + rhs.beats;
737        let mut super_beats = self.super_beats + rhs.super_beats;
738        if super_beats >= SUPER_UNITS {
739            super_beats -= SUPER_UNITS;
740            beats += 1;
741        }
742
743        Self { beats, super_beats }
744    }
745}
746impl Mul<u32> for MusicalTime {
747    type Output = Self;
748    fn mul(self, rhs: u32) -> Self::Output {
749        let mut beats = self.beats * rhs;
750        let mut super_beats_u64 = u64::from(self.super_beats) * u64::from(rhs);
751        if super_beats_u64 >= u64::from(SUPER_UNITS) {
752            let additional_beats = super_beats_u64 % u64::from(SUPER_UNITS);
753            beats += additional_beats as u32;
754            super_beats_u64 -= additional_beats * u64::from(SUPER_UNITS);
755        }
756
757        Self {
758            beats,
759            super_beats: super_beats_u64 as u32,
760        }
761    }
762}
763
764impl AddAssign<MusicalTime> for MusicalTime {
765    fn add_assign(&mut self, other: Self) {
766        *self = *self + other
767    }
768}
769impl MulAssign<u32> for MusicalTime {
770    fn mul_assign(&mut self, other: u32) {
771        *self = *self * other
772    }
773}
774
775/// Unit of time in "Seconds"
776#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
777pub struct Seconds(pub f64);
778
779impl Seconds {
780    pub fn new(seconds: f64) -> Self {
781        Seconds(seconds)
782    }
783
784    pub fn as_f32(&self) -> f32 {
785        self.0 as f32
786    }
787
788    /// Creates a new time in `Seconds` from [`Frames`] and a [`SampleRate`].
789    ///
790    /// Note that this conversion is *NOT* lossless.
791    ///
792    /// [`Frames`]: struct.Frames.html
793    /// [`SampleRate`]: struct.SampleRate.html
794    pub fn from_frames(sample_time: Frames, sample_rate: SampleRate) -> Self {
795        sample_time.to_seconds(sample_rate)
796    }
797
798    /// Creates a new time in `Seconds` from [`SuperFrames`].
799    ///
800    /// Note that this conversion is *NOT* lossless.
801    ///
802    /// [`SuperFrames`]: struct.SuperFrames.html
803    pub fn from_super_frames(super_frame_time: SuperFrames) -> Self {
804        super_frame_time.to_seconds()
805    }
806
807    /// Convert to discrete [`Frames`] with the given [`SampleRate`]. This will
808    /// be rounded to the nearest sample.
809    ///
810    /// Note that this conversion is *NOT* lossless.
811    ///
812    /// If the seconds value is negative, then `Frames(0)` will be returned instead.
813    ///
814    /// [`Frames`]: struct.Frames.html
815    /// [`SampleRate`]: struct.SampleRate.html
816    pub fn to_nearest_frame_round(&self, sample_rate: SampleRate) -> Frames {
817        if self.0 > 0.0 {
818            Frames((self.0 * sample_rate).round() as u64)
819        } else {
820            Frames(0)
821        }
822    }
823
824    /// Convert to discrete [`Frames`] with the given [`SampleRate`]. This will
825    /// be floored to the nearest sample.
826    ///
827    /// Note that this conversion is *NOT* lossless.
828    ///
829    /// If the seconds value is negative, then `Frames(0)` will be returned instead.
830    ///
831    /// [`Frames`]: struct.Frames.html
832    /// [`SampleRate`]: struct.SampleRate.html
833    pub fn to_nearest_frame_floor(&self, sample_rate: SampleRate) -> Frames {
834        if self.0 > 0.0 {
835            Frames((self.0 * sample_rate).floor() as u64)
836        } else {
837            Frames(0)
838        }
839    }
840
841    /// Convert to discrete [`Frames`] with the given [`SampleRate`]. This will
842    /// be ceil-ed to the nearest sample.
843    ///
844    /// Note that this conversion is *NOT* lossless.
845    ///
846    /// If the seconds value is negative, then `Frames(0)` will be returned instead.
847    ///
848    /// [`Frames`]: struct.Frames.html
849    /// [`SampleRate`]: struct.SampleRate.html
850    pub fn to_nearest_frame_ceil(&self, sample_rate: SampleRate) -> Frames {
851        if self.0 > 0.0 {
852            Frames((self.0 * sample_rate).ceil() as u64)
853        } else {
854            Frames(0)
855        }
856    }
857
858    /// Convert to discrete [`Frames`] given the [`SampleRate`] floored to the nearest
859    /// sample, while also return the fractional sub-sample part.
860    ///
861    /// Note that this conversion is *NOT* lossless.
862    ///
863    /// If the seconds value is negative, then `(Frames(0), 0.0)` will be returned instead.
864    ///
865    /// [`Frames`]: struct.Frames.html
866    /// [`SampleRate`]: struct.SampleRate.html
867    pub fn to_sub_frames(&self, sample_rate: SampleRate) -> (Frames, f64) {
868        if self.0 > 0.0 {
869            let frames_f64 = self.0 * sample_rate;
870            (Frames(frames_f64.floor() as u64), frames_f64.fract())
871        } else {
872            (Frames(0), 0.0)
873        }
874    }
875
876    /// Convert to discrete [`SuperFrames`]. This will
877    /// be rounded to the nearest super-frame.
878    ///
879    /// Note that this conversion is *NOT* lossless.
880    ///
881    /// If the seconds value is negative, then the `SuperFrames`'s value will be 0.
882    ///
883    /// [`SuperFrames`]: struct.Frames.html
884    pub fn to_nearest_super_frame_round(&self) -> SuperFrames {
885        if self.0 > 0.0 {
886            SuperFrames((self.0 * f64::from(SUPER_UNITS)).round() as u64)
887        } else {
888            SuperFrames(0)
889        }
890    }
891
892    /// Convert to discrete [`SuperFrames`]. This will
893    /// be floored to the nearest super-frame.
894    ///
895    /// Note that this conversion is *NOT* lossless.
896    ///
897    /// If the seconds value is negative, then the `SuperFrames`'s values will be 0.
898    ///
899    /// [`SuperFrames`]: struct.Frames.html
900    pub fn to_nearest_super_frame_floor(&self) -> SuperFrames {
901        if self.0 > 0.0 {
902            SuperFrames((self.0 * f64::from(SUPER_UNITS)).floor() as u64)
903        } else {
904            SuperFrames(0)
905        }
906    }
907
908    /// Convert to discrete [`SuperFrames`]. This will
909    /// be ceil-ed to the nearest super-frame.
910    ///
911    /// Note that this conversion is *NOT* lossless.
912    ///
913    /// If the seconds value is negative, then the `SuperFrames`'s values will be 0.
914    ///
915    /// [`SuperFrames`]: struct.Frames.html
916    pub fn to_nearest_super_frame_ceil(&self) -> SuperFrames {
917        if self.0 > 0.0 {
918            SuperFrames((self.0 * f64::from(SUPER_UNITS)).ceil() as u64)
919        } else {
920            SuperFrames(0)
921        }
922    }
923
924    /// Convert to discrete [`Frames`] floored to the nearest
925    /// super-frame, while also return the fractional sub-super-frame part.
926    ///
927    /// Note that this conversion is *NOT* lossless.
928    ///
929    /// If the seconds value is negative, then the `SuperFrames`'s values and the
930    /// fractional value will both be 0.
931    ///
932    /// [`SuperFrames`]: struct.Frames.html
933    pub fn to_sub_super_frames(&self) -> (SuperFrames, f64) {
934        if self.0 > 0.0 {
935            let frames_f64 = self.0 * f64::from(SUPER_UNITS);
936            (SuperFrames(frames_f64.floor() as u64), frames_f64.fract())
937        } else {
938            (SuperFrames(0), 0.0)
939        }
940    }
941
942    /// Convert to the corresponding [`MusicalTime`].
943    ///
944    /// Note that this conversion is *NOT* lossless.
945    ///
946    /// [`MusicalTime`]: ../time/struct.MusicalTime.html
947    pub fn to_musical(&self, bpm: f64) -> MusicalTime {
948        MusicalTime::from_beats_f64(self.0 * (bpm / 60.0))
949    }
950}
951
952impl Default for Seconds {
953    fn default() -> Self {
954        Seconds(0.0)
955    }
956}
957
958impl From<i8> for Seconds {
959    fn from(s: i8) -> Self {
960        Seconds(f64::from(s))
961    }
962}
963impl From<u8> for Seconds {
964    fn from(s: u8) -> Self {
965        Seconds(f64::from(s))
966    }
967}
968impl From<i16> for Seconds {
969    fn from(s: i16) -> Self {
970        Seconds(f64::from(s))
971    }
972}
973impl From<u16> for Seconds {
974    fn from(s: u16) -> Self {
975        Seconds(f64::from(s))
976    }
977}
978impl From<i32> for Seconds {
979    fn from(s: i32) -> Self {
980        Seconds(f64::from(s))
981    }
982}
983impl From<u32> for Seconds {
984    fn from(s: u32) -> Self {
985        Seconds(f64::from(s))
986    }
987}
988impl From<f32> for Seconds {
989    fn from(s: f32) -> Self {
990        Seconds(f64::from(s))
991    }
992}
993
994impl Add<Seconds> for Seconds {
995    type Output = Self;
996    fn add(self, rhs: Self) -> Self::Output {
997        Self(self.0 + rhs.0)
998    }
999}
1000impl Sub<Seconds> for Seconds {
1001    type Output = Self;
1002    fn sub(self, rhs: Self) -> Self::Output {
1003        Self(self.0 - rhs.0)
1004    }
1005}
1006impl Mul<Seconds> for Seconds {
1007    type Output = Self;
1008    fn mul(self, rhs: Self) -> Self::Output {
1009        Self(self.0 * rhs.0)
1010    }
1011}
1012impl Div<Seconds> for Seconds {
1013    type Output = Self;
1014    fn div(self, rhs: Self) -> Self::Output {
1015        Self(self.0 / rhs.0)
1016    }
1017}
1018
1019impl AddAssign<Seconds> for Seconds {
1020    fn add_assign(&mut self, other: Self) {
1021        self.0 += other.0;
1022    }
1023}
1024impl SubAssign<Seconds> for Seconds {
1025    fn sub_assign(&mut self, other: Self) {
1026        self.0 -= other.0;
1027    }
1028}
1029impl MulAssign<Seconds> for Seconds {
1030    fn mul_assign(&mut self, other: Self) {
1031        self.0 *= other.0;
1032    }
1033}
1034impl DivAssign<Seconds> for Seconds {
1035    fn div_assign(&mut self, other: Self) {
1036        self.0 /= other.0;
1037    }
1038}
1039
1040/// Unit of time length (of a single de-interleaved channel) in samples.
1041#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Hash)]
1042pub struct Frames(pub u64);
1043
1044impl Frames {
1045    pub fn new(frames: u64) -> Self {
1046        Self(frames)
1047    }
1048
1049    /// Convert to the corresponding time in [`Seconds`] with the given [`SampleRate`].
1050    ///
1051    /// Note that this conversion is *NOT* lossless.
1052    ///
1053    /// [`Seconds`]: struct.Seconds.html
1054    /// [`SampleRate`]: struct.SampleRate.html
1055    pub fn to_seconds(&self, sample_rate: SampleRate) -> Seconds {
1056        Seconds(self.0 as f64 / sample_rate)
1057    }
1058
1059    /// Convert to the corresponding [`MusicalTime`].
1060    ///
1061    /// Note that this conversion is *NOT* lossless.
1062    ///
1063    /// Note that this must be re-calculated after recieving a new [`SampleRate`].
1064    ///
1065    /// [`MusicalTime`]: struct.MusicalTime.html
1066    pub fn to_musical(&self, bpm: f64, sample_rate: SampleRate) -> MusicalTime {
1067        self.to_seconds(sample_rate).to_musical(bpm)
1068    }
1069
1070    /// Convert to the corresponding time length in [`SuperFrames`] from the given [`SampleRate`].
1071    ///
1072    /// This conversion **IS** lossless if the sample rate happens to be equal to one of the common
1073    /// sample rates: `22050, 24000, 44100, 48000, 88200, 96000, 176400, or 192000`. This
1074    /// conversion is *NOT* lossless otherwise.
1075    ///
1076    /// [`SuperFrames`]: struct.SuperFrames.html
1077    /// [`SampleRate`]: struct.SampleRate.html
1078    pub fn to_super_frames(&self, sample_rate: SampleRate) -> SuperFrames {
1079        SuperFrames::from_frames(*self, sample_rate)
1080    }
1081}
1082
1083impl Default for Frames {
1084    fn default() -> Self {
1085        Frames(0)
1086    }
1087}
1088
1089impl From<u8> for Frames {
1090    fn from(s: u8) -> Self {
1091        Frames(u64::from(s))
1092    }
1093}
1094impl From<u16> for Frames {
1095    fn from(s: u16) -> Self {
1096        Frames(u64::from(s))
1097    }
1098}
1099impl From<u32> for Frames {
1100    fn from(s: u32) -> Self {
1101        Frames(u64::from(s))
1102    }
1103}
1104impl From<u64> for Frames {
1105    fn from(s: u64) -> Self {
1106        Frames(s)
1107    }
1108}
1109impl From<usize> for Frames {
1110    fn from(s: usize) -> Self {
1111        Frames(s as u64)
1112    }
1113}
1114
1115impl Add<Frames> for Frames {
1116    type Output = Self;
1117    fn add(self, rhs: Self) -> Self::Output {
1118        Self(self.0 + rhs.0)
1119    }
1120}
1121impl Sub<Frames> for Frames {
1122    type Output = Self;
1123    fn sub(self, rhs: Self) -> Self::Output {
1124        Self(self.0 - rhs.0)
1125    }
1126}
1127impl Mul<u64> for Frames {
1128    type Output = Self;
1129    fn mul(self, rhs: u64) -> Self::Output {
1130        Self(self.0 * rhs)
1131    }
1132}
1133
1134impl AddAssign<Frames> for Frames {
1135    fn add_assign(&mut self, other: Self) {
1136        self.0 += other.0;
1137    }
1138}
1139impl SubAssign<Frames> for Frames {
1140    fn sub_assign(&mut self, other: Self) {
1141        self.0 -= other.0;
1142    }
1143}
1144impl MulAssign<u64> for Frames {
1145    fn mul_assign(&mut self, other: u64) {
1146        *self = *self * other
1147    }
1148}
1149
1150/// Unit of time length (of a single de-interleaved channel) in super-frames.
1151///
1152/// A "super-frame" is a unit of time that is exactly 1 / 508,032,000 of a second.
1153/// This number happens to be nicely divisible by all common sampling rates, allowing
1154/// changes to sample rate in a project to be a lossless process.
1155#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Hash)]
1156pub struct SuperFrames(pub u64);
1157
1158impl SuperFrames {
1159    /// * `super_frames` - The number of super-frames
1160    ///
1161    /// A "super-frame" is a unit of time equal to 1 / 508,032,000 of a second. This number was chosen
1162    /// because it is nicely divisible by a whole slew of factors including `2, 3, 4, 5, 6, 7, 8, 9,
1163    /// 10, 12, 14, 15, 16, 18, 20, 24, 32, 64, 128, 256, 512, and 1920`, as well as common sampling
1164    /// rates such as `22050, 24000, 44100, 48000, 88200, 96000, 176400, and 192000`. This ensures that
1165    /// any recording of frame data in this format will always be at-least sample-accurate.
1166    pub fn new(super_frames: u64) -> Self {
1167        Self(super_frames)
1168    }
1169
1170    /// Get the time in [`SuperFrames`] from the time in [`Seconds`]
1171    ///
1172    /// Note that this conversion is *NOT* lossless.
1173    ///
1174    /// If the seconds value is negative, then the `SuperFrames`'s values will be 0.
1175    ///
1176    /// [`SuperFrames`]: struct.SuperFrames.html
1177    /// [`Seconds`]: struct.Seconds.html
1178    pub fn from_seconds(seconds: Seconds) -> Self {
1179        seconds.to_nearest_super_frame_round()
1180    }
1181
1182    /// Get the time in [`SuperFrames`] from the time in [`Frames`].
1183    ///
1184    /// This conversion **IS** lossless if the sample rate happens to be equal to one of the common
1185    /// sample rates: `22050, 24000, 44100, 48000, 88200, 96000, 176400, or 192000`. This
1186    /// conversion is *NOT* lossless otherwise.
1187    ///
1188    /// [`SuperFrames`]: struct.SuperFrames.html
1189    /// [`Frames`]: struct.Frames.html
1190    pub fn from_frames(frames: Frames, sample_rate: SampleRate) -> Self {
1191        match sample_rate.0 as usize {
1192            44100 => Self(frames.0 * (u64::from(SUPER_UNITS) / 44100)),
1193            48000 => Self(frames.0 * (u64::from(SUPER_UNITS) / 48000)),
1194            88200 => Self(frames.0 * (u64::from(SUPER_UNITS) / 88200)),
1195            96000 => Self(frames.0 * (u64::from(SUPER_UNITS) / 96000)),
1196            176400 => Self(frames.0 * (u64::from(SUPER_UNITS) / 176400)),
1197            192000 => Self(frames.0 * (u64::from(SUPER_UNITS) / 192000)),
1198            22050 => Self(frames.0 * (u64::from(SUPER_UNITS) / 22050)),
1199            24000 => Self(frames.0 * (u64::from(SUPER_UNITS) / 24000)),
1200            _ => Self((frames.0 as f64 * (f64::from(SUPER_UNITS) / sample_rate.0)).round() as u64),
1201        }
1202    }
1203
1204    /// Convert to the corresponding time in [`Seconds`].
1205    ///
1206    /// Note that this conversion is *NOT* lossless.
1207    ///
1208    /// [`Seconds`]: struct.Seconds.html
1209    pub fn to_seconds(&self) -> Seconds {
1210        Seconds(self.0 as f64 / f64::from(SUPER_UNITS))
1211    }
1212
1213    /// Convert to the corresponding [`MusicalTime`].
1214    ///
1215    /// Note that this conversion is *NOT* lossless.
1216    ///
1217    /// [`MusicalTime`]: struct.MusicalTime.html
1218    pub fn to_musical(&self, bpm: f64) -> MusicalTime {
1219        self.to_seconds().to_musical(bpm)
1220    }
1221
1222    /// Convert to the corresponding time length in [`Frames`] from the given [`SampleRate`],
1223    /// rounded to the nearest frame.
1224    ///
1225    /// Note that this conversion is *NOT* lossless.
1226    ///
1227    /// [`Frames`]: struct.Frames.html
1228    /// [`SampleRate`]: struct.SampleRate.html
1229    pub fn to_nearest_frame_round(&self, sample_rate: SampleRate) -> Frames {
1230        self.to_seconds().to_nearest_frame_round(sample_rate)
1231    }
1232
1233    /// Convert to the corresponding time length in [`Frames`] from the given [`SampleRate`],
1234    /// floored to the nearest frame.
1235    ///
1236    /// Note that this conversion is *NOT* lossless.
1237    ///
1238    /// [`Frames`]: struct.Frames.html
1239    /// [`SampleRate`]: struct.SampleRate.html
1240    pub fn to_nearest_frame_floor(&self, sample_rate: SampleRate) -> Frames {
1241        self.to_seconds().to_nearest_frame_floor(sample_rate)
1242    }
1243
1244    /// Convert to the corresponding time length in [`Frames`] from the given [`SampleRate`],
1245    /// ceil-ed to the nearest frame.
1246    ///
1247    /// Note that this conversion is *NOT* lossless.
1248    ///
1249    /// [`Frames`]: struct.Frames.html
1250    /// [`SampleRate`]: struct.SampleRate.html
1251    pub fn to_nearest_frame_ceil(&self, sample_rate: SampleRate) -> Frames {
1252        self.to_seconds().to_nearest_frame_ceil(sample_rate)
1253    }
1254}
1255
1256impl Default for SuperFrames {
1257    fn default() -> Self {
1258        SuperFrames(0)
1259    }
1260}
1261
1262impl Add<SuperFrames> for SuperFrames {
1263    type Output = Self;
1264    fn add(self, rhs: Self) -> Self::Output {
1265        Self(self.0 + rhs.0)
1266    }
1267}
1268impl Sub<SuperFrames> for SuperFrames {
1269    type Output = Self;
1270    fn sub(self, rhs: Self) -> Self::Output {
1271        Self(self.0 - rhs.0)
1272    }
1273}
1274impl Mul<u64> for SuperFrames {
1275    type Output = Self;
1276    fn mul(self, rhs: u64) -> Self::Output {
1277        Self(self.0 * rhs)
1278    }
1279}
1280
1281impl AddAssign<SuperFrames> for SuperFrames {
1282    fn add_assign(&mut self, other: Self) {
1283        *self = *self + other
1284    }
1285}
1286impl SubAssign<SuperFrames> for SuperFrames {
1287    fn sub_assign(&mut self, other: Self) {
1288        *self = *self - other
1289    }
1290}
1291impl MulAssign<u64> for SuperFrames {
1292    fn mul_assign(&mut self, other: u64) {
1293        *self = *self * other
1294    }
1295}