1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use super::{
Measure,
TimeSig,
};
use super::division::{
NumDiv,
Division,
DivType,
};
pub type Bpm = f64;
pub type Ppqn = u32;
pub type Ms = f64;
pub type SampleHz = f64;
pub type Samples = i64;
pub type Ticks = i64;
pub const MINUTE_IN_MS: Ms = 60_000.0;
pub const SECOND_IN_MS: Ms = 1_000.0;
#[inline]
pub fn bar_in_ms(bpm: Bpm, ts: TimeSig) -> Ms {
beat_in_ms(bpm) * ts.beats_in_a_bar()
}
#[inline]
pub fn beat_in_ms(bpm: Bpm) -> Ms {
MINUTE_IN_MS / bpm
}
#[inline]
pub fn ms_from_measure(num: NumDiv, div: Division, div_type: DivType, bpm: Bpm, ts: TimeSig) -> Ms {
Measure(num, div, div_type).beats(ts) * beat_in_ms(bpm)
}
#[inline]
pub fn ms_from_samples(samples: Samples, sample_hz: SampleHz) -> Ms {
samples as Ms * SECOND_IN_MS / sample_hz
}
#[inline]
pub fn ms_from_ticks(ticks: Ticks, bpm: Bpm, ppqn: Ppqn) -> Ms {
tick_in_ms(bpm, ppqn) * ticks as Ms
}
#[inline]
pub fn samples_from_measure(num: NumDiv, div: Division, div_type: DivType,
bpm: Bpm, ts: TimeSig, sample_hz: SampleHz) -> Samples {
samples_from_ms(ms_from_measure(num, div, div_type, bpm, ts), sample_hz)
}
#[inline]
pub fn samples_from_ms(ms: Ms, sample_hz: SampleHz) -> Samples {
(ms * sample_hz as Ms / SECOND_IN_MS) as Samples
}
#[inline]
pub fn samples_from_ticks(ticks: Ticks, bpm: Bpm, ppqn: Ppqn, sample_hz: SampleHz) -> Samples {
samples_from_ms(ms_from_ticks(ticks, bpm, ppqn), sample_hz)
}
#[inline]
pub fn tick_in_ms(bpm: Bpm, ppqn: Ppqn) -> Ms {
beat_in_ms(bpm) / ppqn as Ms
}
#[inline]
pub fn ticks_from_measure(num: NumDiv, div: Division, div_type: DivType,
ts: TimeSig, ppqn: Ppqn) -> Ticks {
let num_quarters = match div_type {
DivType::TwoThirds => div.beats(ts) * num as f64 * 2.0 / 3.0,
DivType::Whole => div.beats(ts) * num as f64
};
(num_quarters * ppqn as f64).round() as Ticks
}
#[inline]
pub fn ticks_from_ms(ms: Ms, bpm: Bpm, ppqn: Ppqn) -> Ticks {
(ms / tick_in_ms(bpm, ppqn)).round() as Ticks
}
#[inline]
pub fn ticks_from_samples(samples: Samples, bpm: Bpm, ppqn: Ppqn, sample_hz: SampleHz) -> Ticks {
ticks_from_ms(ms_from_samples(samples, sample_hz), bpm, ppqn)
}