tek/src/time.rs
2024-07-04 01:36:31 +03:00

95 lines
2.3 KiB
Rust

/// Number of data frames in a second.
#[derive(Debug)]
pub struct Hz(pub u32);
/// One data frame.
#[derive(Debug)]
pub struct Frame(pub u32);
/// One microsecond.
#[derive(Debug)]
pub struct Usec(pub u64);
/// Beats per minute as `120000` = 120.000BPM
#[derive(Debug)]
pub struct Tempo(pub u64);
/// Time signature: N/Mths per bar.
#[derive(Debug)]
pub struct Signature(pub u32, pub u32);
/// NoteDuration in musical terms. Has definite usec value
/// for given bpm and sample rate.
pub enum NoteDuration {
Nth(u16, u16),
Dotted(Box<Self>),
Tuplet(u16, Box<Self>),
}
impl Frame {
#[inline]
pub fn to_usec (&self, rate: &Hz) -> Usec {
Usec((self.0 as u64 * 1000000) / rate.0 as u64)
}
}
impl Usec {
#[inline]
pub fn to_frame (&self, rate: &Hz) -> Frame {
Frame(((self.0 * rate.0 as u64) / 1000) as u32)
}
}
impl Tempo {
#[inline]
pub fn usec_per_bar (&self, beats: u64) -> Usec {
Usec(beats * self.usec_per_beat().0)
}
#[inline]
pub fn usec_per_beat (&self) -> Usec {
Usec(60_000_000_000 / self.0 as u64)
}
#[inline]
pub fn usec_per_step (&self, divisor: u64) -> Usec {
Usec(self.usec_per_beat().0 / divisor as u64)
}
#[inline]
pub fn quantize (&self, step: &NoteDuration, time: Usec) -> Usec {
let step = step.to_usec(self);
let t = time.0 / step.0;
Usec(step.0 * t)
}
#[inline]
pub fn quantize_into <T, U> (&self, step: &NoteDuration, events: U)
-> Vec<(Usec, T)>
where U: std::iter::Iterator<Item=(Usec, T)> + Sized
{
events
.map(|(time, event)|(self.quantize(step, time), event))
.collect()
}
}
impl NoteDuration {
fn to_usec (&self, bpm: &Tempo) -> Usec {
Usec(match self {
Self::Nth(time, flies) =>
bpm.usec_per_beat().0 * *time as u64 / *flies as u64,
Self::Dotted(duration) =>
duration.to_usec(bpm).0 * 3 / 2,
Self::Tuplet(n, duration) =>
duration.to_usec(bpm).0 * 2 / *n as u64,
})
}
fn to_frame (&self, bpm: &Tempo, rate: &Hz) -> Frame {
self.to_usec(bpm).to_frame(rate)
}
}
struct Loop<T> {
repeat: bool,
pre_start: T,
start: T,
end: T,
post_end: T,
}