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 | |
4 | use std::time::{Duration, Instant}; |
5 | use std::thread::{sleep}; |
6 | |
7 | pub type Time = Instant; |
8 | |
9 | pub type Nanos = u64; |
10 | pub type Ticks = u64; |
11 | pub type Beats = u64; |
12 | pub type Bars = u64; |
13 | |
14 | static SECONDS_PER_MINUTE: u64 = 60; |
15 | static NANOS_PER_SECOND: u64 = 1_000_000_000; |
16 | static BEATS_PER_MINUTE: u64 = 60; |
17 | static DEFAULT_TICKS_PER_BEAT: u64 = 16; |
18 | static DEFAULT_BEATS_PER_BAR: u64 = 4; |
19 | |
20 | |
21 | pub struct ClockSignature { |
22 | nanos_per_beat: u64, // tempo |
23 | ticks_per_beat: u64, // meter |
24 | beats_per_bar: u64 // meter |
25 | } |
26 | |
27 | impl 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 | |
66 | pub struct ClockTime { |
67 | nanos: Nanos, |
68 | ticks: Ticks, |
69 | beats: Beats, |
70 | bars: Bars |
71 | } |
72 | |
73 | impl 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 | |
85 | pub struct Clock { |
86 | start_instant: Instant, |
87 | tick_instant: Instant, |
88 | signature: ClockSignature |
89 | } |
90 | |
91 | pub struct ClockMessage { |
92 | } |
93 | |
94 | impl 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 | |
136 | fn duration_to_nanos (duration: Duration) -> Nanos { |
137 | duration.as_secs() * 1_000_000_000 + duration.subsec_nanos() as Nanos |
138 | } |
139 | |
140 | /* |
141 | pub fn nanos_from_ticks (ticks: Ticks, signature: ClockSignature) -> Nanos { |
142 | ticks * signature.nanos_per_beat |
143 | } |
144 | |
145 | pub fn ticks_from_beats (beats: Beats, signature: ClockSignature) -> Ticks { |
146 | beats * signature.ticks_per_beat |
147 | } |
148 | |
149 | pub 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