diff --git a/crates/tek_core/src/time.rs b/crates/tek_core/src/time.rs index ea567dd5..ae1c98f1 100644 --- a/crates/tek_core/src/time.rs +++ b/crates/tek_core/src/time.rs @@ -27,10 +27,18 @@ pub trait SampleRate { #[inline] fn usec_per_sample (&self) -> U where U: TimeFloat { U::from(1_000_000f64 / self.sr().into()) } + /// Return the duration of a sample in microseconds (floating) + #[inline] fn sample_per_usec (&self) -> U where U: TimeFloat { + U::from(self.sr().into() / 1_000_000f64) + } /// Convert a number of samples to microseconds (floating) #[inline] fn samples_to_usec (&self, samples: U) -> U where U: TimeFloat { samples * self.usec_per_sample() } + /// Convert a number of microseconds to samples (floating) + #[inline] fn usecs_to_sample (&self, usecs: U) -> U where U: TimeFloat, Self: SampleRate { + usecs * self.sample_per_usec() + } } /// Trait for struct that defines a tempo in beats per minute @@ -79,11 +87,11 @@ pub trait PulsesPerQuaver { fn ppq (&self) -> U; /// Set the PPQ fn set_ppq (&self, ppq: U); - /// Return number of pulses to which a number of microseconds corresponds (BPM-dependent) - #[inline] fn usecs_to_pulse (&self, usec: U) -> U + /// Return duration of a pulse in microseconds (BPM-dependent) + #[inline] fn pulse_per_usec (&self) -> U where U: TimeFloat, Self: BeatsPerMinute { - usec / self.usec_per_pulse() + self.ppq() / self.usec_per_beat() } /// Return duration of a pulse in microseconds (BPM-dependent) #[inline] fn usec_per_pulse (&self) -> U @@ -91,6 +99,18 @@ pub trait PulsesPerQuaver { { self.usec_per_beat() / self.ppq() } + /// Return number of pulses to which a number of microseconds corresponds (BPM-dependent) + #[inline] fn usecs_to_pulse (&self, usec: U) -> U + where U: TimeFloat, Self: BeatsPerMinute + { + usec / self.pulse_per_usec() + } + /// Convert a number of pulses to a sample number (SR- and BPM-dependent) + #[inline] fn pulses_to_usec (&self, pulse: U) -> U + where U: TimeFloat, Self: SampleRate + BeatsPerMinute + { + pulse / self.usec_per_pulse() + } /// Return number of pulses in a second (BPM-dependent) #[inline] fn pulses_per_second (&self) -> U where U: TimeFloat, Self: BeatsPerMinute @@ -236,6 +256,29 @@ impl PulsePosition for Instant { #[inline] fn pulse (&self) -> usize { self.pulse.load(Ordering::Relaxed) as usize } #[inline] fn set_pulse (&self, usec: usize) { self.pulse.store(usec as f64, Ordering::Relaxed); } } +impl Instant { + pub fn from_usec (timebase: &Timebase, usec: usize) -> Self { + Self { + usec: usec.into(), + sample: (timebase.usecs_to_sample(usec as f64) as usize).into(), + pulse: timebase.usecs_to_pulse(usec as f64).into() + } + } + pub fn from_sample (timebase: &Timebase, sample: usize) -> Self { + Self { + sample: sample.into(), + usec: (timebase.samples_to_usec(sample as f64) as usize).into(), + pulse: timebase.samples_to_pulse(sample as f64).into() + } + } + pub fn from_pulse (timebase: &Timebase, pulse: f64) -> Self { + Self { + pulse: pulse.into(), + sample: (timebase.pulses_to_sample(pulse) as usize).into(), + usec: (timebase.pulses_to_usec(pulse) as usize).into() + } + } +} /// (pulses, name) pub const NOTE_DURATIONS: [(usize, &str);26] = [