euphony_core/time/
time_signature.rs1use crate::{
2 ratio::Ratio,
3 time::{beat::Beat, measure::Measure},
4};
5use core::convert::TryInto;
6
7#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
8pub struct TimeSignature(pub u64, pub u64);
9
10impl Default for TimeSignature {
11 fn default() -> Self {
12 Self(4, 4)
13 }
14}
15
16impl TimeSignature {
17 pub fn new<T: Into<Self>>(value: T) -> Self {
18 value.into()
19 }
20
21 pub fn beat(&self) -> Beat {
22 Beat(1, self.1)
23 }
24
25 pub fn count(&self) -> u64 {
26 self.0
27 }
28
29 pub fn total_beats(&self) -> Beat {
30 Beat(self.0, self.1)
31 }
32
33 fn as_ratio(self) -> Ratio<u64> {
34 Ratio(self.0, self.1)
35 }
36}
37
38impl core::ops::Mul<Measure> for TimeSignature {
39 type Output = Beat;
40
41 fn mul(self, measure: Measure) -> Self::Output {
42 let count = self.as_ratio() * measure.as_ratio();
43 (count / self.beat().as_ratio()).into()
44 }
45}
46
47#[test]
48fn mul_measure_test() {
49 assert_eq!(TimeSignature(4, 4) * Measure(1, 4), Beat(1, 1));
50 assert_eq!(TimeSignature(4, 4) * Measure(2, 4), Beat(2, 1));
51 assert_eq!(TimeSignature(7, 8) * Measure(2, 1), Beat(14, 1));
52 assert_eq!(TimeSignature(6, 8) * Measure(1, 3), Beat(2, 1));
53 assert_eq!(TimeSignature(6, 8) * Measure(2, 3), Beat(4, 1));
54}
55
56macro_rules! convert {
57 ($ty:ty) => {
58 impl From<($ty, $ty)> for TimeSignature {
59 fn from((n, d): ($ty, $ty)) -> Self {
60 Self(n.try_into().unwrap(), d.try_into().unwrap())
61 }
62 }
63 };
64}
65
66convert!(i8);
67convert!(u8);
68convert!(i16);
69convert!(u16);
70convert!(i32);
71convert!(u32);
72convert!(i64);
73convert!(u64);
74convert!(isize);
75convert!(usize);