Skip to main content

rosu_pp/model/control_point/
timing.rs

1/// Timing-related info about this control point.
2#[derive(Copy, Clone, Debug, PartialEq)]
3pub struct TimingPoint {
4    pub time: f64,
5    pub beat_len: f64,
6}
7
8impl TimingPoint {
9    pub const DEFAULT_BEAT_LEN: f64 =
10        rosu_map::section::timing_points::TimingPoint::DEFAULT_BEAT_LEN;
11
12    pub const DEFAULT_BPM: f64 = 60_000.0 / Self::DEFAULT_BEAT_LEN;
13
14    pub const fn new(time: f64, beat_len: f64) -> Self {
15        Self {
16            time,
17            beat_len: beat_len.clamp(6.0, 60_000.0),
18        }
19    }
20
21    pub const fn bpm(&self) -> f64 {
22        60_000.0 / self.beat_len
23    }
24}
25
26impl Default for TimingPoint {
27    fn default() -> Self {
28        Self {
29            time: 0.0,
30            beat_len: Self::DEFAULT_BEAT_LEN,
31        }
32    }
33}
34
35pub fn timing_point_at(points: &[TimingPoint], time: f64) -> Option<&TimingPoint> {
36    let i = points
37        .binary_search_by(|probe| probe.time.total_cmp(&time))
38        .unwrap_or_else(|i| i.saturating_sub(1));
39
40    points.get(i)
41}