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}