wip: more time traits

This commit is contained in:
🪞👃🪞 2024-10-26 13:56:03 +03:00
parent 5a18a2023d
commit e6a37cfc36
2 changed files with 36 additions and 47 deletions

View file

@ -16,7 +16,7 @@ pub(crate) use std::thread::{spawn, JoinHandle};
pub(crate) use std::time::Duration; pub(crate) use std::time::Duration;
pub(crate) use atomic_float::*; pub(crate) use atomic_float::*;
use better_panic::{Settings, Verbosity}; use better_panic::{Settings, Verbosity};
use std::ops::{Add, Sub, Mul, Div}; use std::ops::{Add, Sub, Mul, Div, Rem};
use std::cmp::{Ord, Eq, PartialEq}; use std::cmp::{Ord, Eq, PartialEq};
use std::fmt::{Debug, Display}; use std::fmt::{Debug, Display};

View file

@ -1,9 +1,10 @@
use crate::*; use crate::*;
use std::iter::Iterator;
pub trait TimeUnit: Mul<Self, Output=Self> + Div<Self, Output=Self> + From<f64> + Sized {} pub trait TimeUnit: Mul<Self, Output=Self> + Div<Self, Output=Self>
+ Rem<Self, Output=Self> + From<f64> + Copy {}
impl<T> TimeUnit for T impl<T> TimeUnit for T where T: Mul<Self, Output=Self> + Div<Self, Output=Self>
where T: Mul<Self, Output=Self> + Div<Self, Output=Self> + From<f64> + Sized {} + Rem<Self, Output=Self> + From<f64> + Copy {}
/// Trait for struct that defines a sample rate in hertz (samples per second) /// Trait for struct that defines a sample rate in hertz (samples per second)
pub trait TimeSR<T: TimeUnit> { pub trait TimeSR<T: TimeUnit> {
@ -27,6 +28,30 @@ pub trait TimeBPM<T: TimeUnit> {
#[inline] fn usec_per_beat (&self) -> T { T::from(60_000_000f64) / self.bpm() } #[inline] fn usec_per_beat (&self) -> T { T::from(60_000_000f64) / self.bpm() }
/// Return the number of beats in a second /// Return the number of beats in a second
#[inline] fn beat_per_second (&self) -> T { self.bpm() / T::from(60_000_000f64) } #[inline] fn beat_per_second (&self) -> T { self.bpm() / T::from(60_000_000f64) }
/// Return the duration of a note in microseconds
#[inline] fn note_to_usec (&self, (num, den): (T, T)) -> T {
T::from(4.0) * self.usec_per_beat() * num / den
}
/// Return the quantized position of a moment in time given a step
#[inline] fn quantize (&self, step: (T, T), time: T) -> (T, T) {
let step = self.note_to_usec(step);
(time / step, time % step)
}
/// Quantize a collection of events
#[inline] fn quantize_into <E: Iterator<Item=(T, T)> + Sized, U> (
&self, step: (T, T), events: E
) -> Vec<(T, U)> {
let step = (step.0.into(), step.1.into());
events
.map(|(time, event)|(self.quantize(step, time).0, event))
.collect()
}
#[inline] fn note_to_frame (&self, note: (T, T)) -> T where Self: TimeSR<T> {
self.usec_to_frame(self.note_to_usec(note))
}
#[inline] fn usec_to_frame (&self, usec: T) -> T where Self: TimeSR<T> {
usec * self.sr() / T::from(1000f64)
}
} }
/// Trait for struct that defines a MIDI resolution in pulses per quaver (beat) /// Trait for struct that defines a MIDI resolution in pulses per quaver (beat)
@ -72,6 +97,12 @@ pub struct Timebase {
/// Ticks per beat /// Ticks per beat
pub ppq: AtomicF64, pub ppq: AtomicF64,
} }
impl Default for Timebase { fn default () -> Self { Self::new(48000f64, 150f64, 96f64) } }
impl Timebase {
pub fn new (s: impl Into<AtomicF64>, b: impl Into<AtomicF64>, p: impl Into<AtomicF64>) -> Self {
Self { sr: s.into(), bpm: b.into(), ppq: p.into() }
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct TransportTime { pub struct TransportTime {
@ -133,48 +164,6 @@ pub trait TimePoint<T>: TimeFrame<T> + TimePulse<T> + TimeUsec<T> {}
pub trait TimeSync<T> { fn sync (&self) -> T; fn set_sync (&self, sync: T) -> T; } pub trait TimeSync<T> { fn sync (&self) -> T; fn set_sync (&self, sync: T) -> T; }
pub trait TimeQuant<T> { fn quant (&self) -> T; fn set_quant (&self, quant: T); } pub trait TimeQuant<T> { fn quant (&self) -> T; fn set_quant (&self, quant: T); }
impl Default for Timebase {
fn default () -> Self { Self::new(48000f64, 150f64, 96f64) }
}
impl Timebase {
pub fn new (
sr: impl Into<AtomicF64>, bpm: impl Into<AtomicF64>, ppq: impl Into<AtomicF64>
) -> Self {
Self { sr: sr.into(), bpm: bpm.into(), ppq: ppq.into() }
}
#[inline] pub fn note_to_usec (&self, (num, den): (f64, f64)) -> f64 {
4.0 * self.usec_per_beat() * num / den
}
#[inline] pub fn note_to_frame (&self, note: (f64, f64)) -> f64 {
self.usec_to_frame(self.note_to_usec(note))
}
#[inline] fn usec_to_frame (&self, usec: f64) -> f64 {
usec * self.sr() / 1000.0
}
#[inline] pub fn quantize (
&self, step: (f64, f64), time: f64
) -> (f64, f64) {
let step = self.note_to_usec(step);
(time / step, time % step)
}
#[inline] pub fn quantize_into <E, T> (
&self, step: (f64, f64), events: E
) -> Vec<(f64, T)>
where E: std::iter::Iterator<Item=(f64, T)> + Sized
{
let step = (step.0.into(), step.1.into());
events
.map(|(time, event)|(self.quantize(step, time).0, event))
.collect()
}
}
/// (pulses, name) /// (pulses, name)
pub const NOTE_DURATIONS: [(usize, &str);26] = [ pub const NOTE_DURATIONS: [(usize, &str);26] = [
(1, "1/384"), (1, "1/384"),