mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
95 lines
2.3 KiB
Rust
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,
|
|
}
|