git ssb

0+

dinoworm ๐Ÿ› / metronome



Tree: 9cf1052d129942a85af116c81a7f960330143ad6

Files: 9cf1052d129942a85af116c81a7f960330143ad6 / src / clock.rs

3891 bytesRaw
1// inspired by https://github.com/mmckegg/rust-loop-drop/blob/master/src/midi_time.rs
2// http://www.deluge.co/?q=midi-tempo-bpm
3
4use std::time::{Duration, Instant};
5use std::thread::{sleep};
6
7pub type Time = Instant;
8
9pub type Nanos = u64;
10pub type Ticks = u64;
11pub type Beats = u64;
12pub type Bars = u64;
13
14static SECONDS_PER_MINUTE: u64 = 60;
15static NANOS_PER_SECOND: u64 = 1_000_000_000;
16static BEATS_PER_MINUTE: u64 = 60;
17static DEFAULT_TICKS_PER_BEAT: u64 = 16;
18static DEFAULT_BEATS_PER_BAR: u64 = 4;
19
20#[derive(Clone, Copy, Debug, Hash)]
21pub struct ClockSignature {
22 nanos_per_beat: u64, // tempo
23 ticks_per_beat: u64, // meter
24 beats_per_bar: u64 // meter
25}
26
27impl ClockSignature {
28 pub fn new (beats_per_minute: f64) -> Self {
29 let minutes_per_beat = 1_f64 / beats_per_minute;
30 let seconds_per_beat = minutes_per_beat * SECONDS_PER_MINUTE as f64;
31 let nanos_per_beat = seconds_per_beat * NANOS_PER_SECOND as f64;
32
33 Self {
34 nanos_per_beat: nanos_per_beat as u64,
35 ticks_per_beat: DEFAULT_TICKS_PER_BEAT,
36 beats_per_bar: DEFAULT_BEATS_PER_BAR
37 }
38 }
39
40 pub fn nanos_per_tick (&self) -> u64 {
41 (self.nanos_per_beat / self.ticks_per_beat) as u64
42 }
43
44 pub fn nanos_per_beat (&self) -> u64 {
45 self.nanos_per_beat
46 }
47
48 pub fn nanos_per_bar (&self) -> u64 {
49 self.nanos_per_beat() * self.beats_per_bar
50 }
51
52 pub fn nanos_to_ticks (&self, nanos: Nanos) -> u64 {
53 (nanos / self.nanos_per_tick()) as u64
54 }
55
56 pub fn nanos_to_beats (&self, nanos: Nanos) -> u64 {
57 (nanos / self.nanos_per_beat()) as u64
58 }
59
60 pub fn nanos_to_bars (&self, nanos: Nanos) -> u64 {
61 (nanos / self.nanos_per_bar()) as u64
62 }
63}
64
65#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
66pub struct ClockTime {
67 nanos: Nanos,
68 ticks: Ticks,
69 beats: Beats,
70 bars: Bars
71}
72
73impl ClockTime {
74 pub fn new (nanos: Nanos, signature: ClockSignature) -> Self {
75 Self {
76 nanos,
77 ticks: signature.nanos_to_ticks(nanos),
78 beats: signature.nanos_to_beats(nanos),
79 bars: signature.nanos_to_bars(nanos)
80 }
81 }
82}
83
84#[derive(Clone, Copy, Debug, Hash)]
85pub struct Clock {
86 start_instant: Instant,
87 tick_instant: Instant,
88 signature: ClockSignature
89}
90
91pub struct ClockMessage {
92}
93
94impl Clock {
95 pub fn new (signature: ClockSignature) -> Self {
96 let start_instant = Instant::now();
97
98 Self {
99 start_instant,
100 tick_instant: start_instant,
101 signature
102 }
103 }
104
105 pub fn time (&self) -> ClockTime {
106 ClockTime::new(self.nanos_since_start(), self.signature)
107 }
108
109 pub fn diff (&self) -> ClockTime {
110 ClockTime::new(self.nanos_since_tick(), self.signature)
111 }
112
113 pub fn nanos_since_start (&self) -> Nanos {
114 duration_to_nanos(self.start_instant.elapsed())
115 }
116
117 pub fn nanos_since_tick (&self) -> Nanos {
118 duration_to_nanos(self.tick_instant.elapsed())
119 }
120
121 // https://github.com/BookOwl/fps_clock/blob/master/src/lib.rs
122 pub fn tick (&mut self) -> ClockTime {
123 let diff = self.diff();
124
125 if diff.nanos > 0 {
126 sleep(Duration::new(0, diff.nanos as u32))
127 };
128
129
130 self.tick_instant = Instant::now();
131
132 diff
133 }
134}
135
136fn duration_to_nanos (duration: Duration) -> Nanos {
137 duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as Nanos
138}
139
140/*
141pub fn nanos_from_ticks (ticks: Ticks, signature: ClockSignature) -> Nanos {
142 ticks * signature.nanos_per_beat
143}
144
145pub fn ticks_from_beats (beats: Beats, signature: ClockSignature) -> Ticks {
146 beats * signature.ticks_per_beat
147}
148
149pub fn ticks_from_measure (measures: Measures, signature: ClockSignature) -> Ticks {
150 measures * signature.beats_per_measure * signature.ticks_per_beat
151}
152*/
153

Built with git-ssb-web