fluffl/audio/
interval.rs

1use crate::{collections::segment_tree::index_types::GlobalIndex, math::FP64};
2use std::{fmt::Debug, ops::Deref};
3
4/// Represents an interval
5#[derive(Copy, Clone, PartialEq, Eq, Default)]
6pub struct Interval {
7    pub lo: FP64,
8    pub hi: FP64,
9}
10
11impl Debug for Interval {
12    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
13        write!(f, "({},{})", self.lo, self.hi)
14    }
15}
16
17impl Interval {
18    /// creates and interval: \[`t0`,`t0`+`dt`\]
19    pub fn from_point_and_length(t0: FP64, dt: FP64) -> Self {
20        Self {
21            lo: t0,
22            hi: t0 + dt,
23        }
24    }
25    /// creates an interval: \[0,`dt`\]
26    pub fn from_length(dt: FP64) -> Self {
27        Self {
28            lo: FP64::zero(),
29            hi: dt,
30        }
31    }
32
33    /// returns an interval that is within `bounds` parts of interval outside of `bounds` gets clipped away
34    pub fn clip_interval(mut self, bounds: Self) -> Self {
35        if self.hi > bounds.hi {
36            self.hi = bounds.hi;
37        }
38        if self.lo < bounds.lo {
39            self.lo = bounds.lo;
40        }
41        self
42    }
43
44    pub fn inverted(&self) -> bool {
45        self.lo > self.hi
46    }
47
48    pub fn is_seperating(&self, other_interval: &Self) -> bool {
49        let &Self { lo: lo_a, hi: hi_a } = self;
50
51        let &Self { lo: lo_b, hi: hi_b } = other_interval;
52
53        lo_b > hi_a || lo_a > hi_b
54    }
55
56    pub fn distance(&self) -> FP64 {
57        self.hi - self.lo
58    }
59
60    /// divide the interval into equal chunks of count `num_chunks`. returns the `chunk_idx`-th chunk
61    pub fn chunk(&self, num_chunks: u64, chunk_idx: usize) -> Self {
62        let num_chunks = FP64::from(num_chunks);
63        let chunk_idx = FP64::from(chunk_idx as u32);
64        let length = self.distance();
65        let chunk_length = length / num_chunks;
66        let lo = self.lo + chunk_length * chunk_idx;
67        Self {
68            lo,
69            hi: lo + chunk_length,
70        }
71    }
72
73    pub fn is_overlapping(&self, other_interval: &Self) -> bool {
74        !self.is_seperating(other_interval)
75    }
76
77    pub fn is_within(&self, t: FP64) -> bool {
78        let &Self { lo, hi } = self;
79        t >= lo && t <= hi
80    }
81
82    #[allow(dead_code)]
83    pub fn midpoint(&self) -> FP64 {
84        self.lo + (self.hi - self.lo) / FP64::from(2)
85    }
86
87    pub fn to_tuple(&self) -> (u128, u128) {
88        (self.lo.as_i64() as u128, self.hi.as_i64() as u128)
89    }
90    pub fn to_tuple_f32(&self) -> (f32, f32) {
91        (self.lo.as_f64() as f32, self.hi.as_f64() as f32)
92    }
93}
94
95impl<T> std::ops::Add<T> for Interval
96where
97    T: Into<u64> + Copy,
98{
99    type Output = Self;
100    fn add(self, rhs: T) -> Self::Output {
101        let rhs = FP64::from(T::into(rhs));
102        Self {
103            lo: self.lo + rhs,
104            hi: self.hi + rhs,
105        }
106    }
107}
108
109impl std::ops::Add<FP64> for Interval {
110    type Output = Self;
111    fn add(self, rhs: FP64) -> Self::Output {
112        Self {
113            lo: self.lo + rhs,
114            hi: self.hi + rhs,
115        }
116    }
117}
118
119impl From<(u64, u64)> for Interval {
120    fn from((lo, hi): (u64, u64)) -> Self {
121        Self {
122            lo: FP64::from(lo),
123            hi: FP64::from(hi),
124        }
125    }
126}
127impl From<(i64, i64)> for Interval {
128    fn from((lo, hi): (i64, i64)) -> Self {
129        Self {
130            lo: FP64::from(lo),
131            hi: FP64::from(hi),
132        }
133    }
134}
135impl From<(i32, i32)> for Interval {
136    fn from((lo, hi): (i32, i32)) -> Self {
137        Self {
138            lo: FP64::from(lo),
139            hi: FP64::from(hi),
140        }
141    }
142}
143impl From<(FP64, FP64)> for Interval {
144    fn from((lo, hi): (FP64, FP64)) -> Self {
145        Self { lo, hi }
146    }
147}
148
149#[derive(Copy, Clone, Debug)]
150pub struct GlobalInterval<V> {
151    pub interval: Interval,
152    pub data: V,
153}
154
155impl<V> Deref for GlobalInterval<V> {
156    type Target = Interval;
157    fn deref(&self) -> &Self::Target {
158        &self.interval
159    }
160}
161
162#[derive(Clone, Copy, Debug, Default)]
163pub struct TreeInterval {
164    pub clipped_interval: Interval,
165    pub global_idx: GlobalIndex,
166}
167
168impl Deref for TreeInterval {
169    type Target = Interval;
170    fn deref(&self) -> &Self::Target {
171        &self.clipped_interval
172    }
173}