mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 20:56:43 +01:00
wip: simplifying timebase
This commit is contained in:
parent
238d307817
commit
b3e6206b08
5 changed files with 50 additions and 89 deletions
102
src/core/time.rs
102
src/core/time.rs
|
|
@ -3,11 +3,11 @@ use atomic_float::AtomicF64;
|
|||
#[derive(Debug)]
|
||||
pub struct Timebase {
|
||||
/// Frames per second
|
||||
pub rate: AtomicF64,
|
||||
rate: AtomicF64,
|
||||
/// Beats per minute
|
||||
pub bpm: AtomicF64,
|
||||
bpm: AtomicF64,
|
||||
/// Ticks per beat
|
||||
pub ppq: AtomicF64,
|
||||
ppq: AtomicF64,
|
||||
}
|
||||
impl Default for Timebase {
|
||||
fn default () -> Self {
|
||||
|
|
@ -27,61 +27,48 @@ impl Timebase {
|
|||
#[inline] fn rate (&self) -> f64 {
|
||||
self.rate.load(Ordering::Relaxed)
|
||||
}
|
||||
/// Usec per frame
|
||||
#[inline] fn frame_usec (&self) -> f64 {
|
||||
#[inline] fn usec_per_frame (&self) -> f64 {
|
||||
1_000_000 as f64 / self.rate() as f64
|
||||
}
|
||||
/// Frames to usecs
|
||||
#[inline] pub fn frames_usecs (&self, frame: f64) -> f64 {
|
||||
frame * self.frame_usec()
|
||||
}
|
||||
/// Frames to usecs
|
||||
#[inline] pub fn usecs_frames (&self, usec: f64) -> f64 {
|
||||
usec / self.frame_usec()
|
||||
#[inline] pub fn frame_to_usec (&self, frame: f64) -> f64 {
|
||||
frame * self.usec_per_frame()
|
||||
}
|
||||
|
||||
/// Beats per minute
|
||||
#[inline] pub fn bpm (&self) -> f64 {
|
||||
self.bpm.load(Ordering::Relaxed)
|
||||
}
|
||||
/// Usec per beat
|
||||
#[inline] fn beat_usec (&self) -> f64 {
|
||||
#[inline] fn usec_per_beat (&self) -> f64 {
|
||||
60_000_000f64 / self.bpm() as f64
|
||||
}
|
||||
#[inline] fn beat_per_second (&self) -> f64 {
|
||||
self.bpm() as f64 / 60000000.0
|
||||
}
|
||||
|
||||
/// Pulses per beat
|
||||
#[inline] pub fn ppq (&self) -> f64 {
|
||||
self.ppq.load(Ordering::Relaxed)
|
||||
}
|
||||
/// Usec per pulse
|
||||
#[inline] fn pulse_usec (&self) -> f64 {
|
||||
self.beat_usec() / self.ppq() as f64
|
||||
#[inline] fn usec_per_pulse (&self) -> f64 {
|
||||
self.usec_per_beat() / self.ppq() as f64
|
||||
}
|
||||
/// Usecs to pulses
|
||||
#[inline] pub fn pulses_usecs (&self, pulses: f64) -> f64 {
|
||||
self.pulse_usec() * pulses
|
||||
#[inline] pub fn pulse_per_frame (&self) -> f64 {
|
||||
self.usec_per_pulse() / self.usec_per_frame() as f64
|
||||
}
|
||||
/// Pulses per frame
|
||||
#[inline] pub fn pulse_frame (&self) -> f64 {
|
||||
self.pulse_usec() / self.frame_usec() as f64
|
||||
#[inline] pub fn frame_to_pulse (&self, pulses: f64) -> f64 {
|
||||
self.pulse_per_frame() * pulses
|
||||
}
|
||||
/// Frames per pulse
|
||||
#[inline] pub fn frame_pulse (&self) -> f64 {
|
||||
self.frame_usec() as f64 / self.pulse_usec()
|
||||
}
|
||||
/// Frames to pulses
|
||||
#[inline] pub fn pulses_frames (&self, pulses: f64) -> f64 {
|
||||
self.pulse_frame() * pulses
|
||||
}
|
||||
/// Pulses to frames
|
||||
#[inline] pub fn frames_pulses (&self, frames: f64) -> f64 {
|
||||
frames / self.pulse_frame()
|
||||
}
|
||||
#[inline] pub fn usec_per_step (&self, divisor: f64) -> f64 {
|
||||
self.beat_usec() / divisor
|
||||
#[inline] pub fn pulse_to_frame (&self, frames: f64) -> f64 {
|
||||
frames / self.pulse_per_frame()
|
||||
}
|
||||
#[inline] pub fn note_to_usec (&self, (num, den): (f64, f64)) -> f64 {
|
||||
4.0 * self.beat_usec() * num / den
|
||||
4.0 * self.usec_per_beat() * num / den
|
||||
}
|
||||
#[inline] fn pulses_per_second (&self) -> f64 {
|
||||
self.beat_per_second() * self.ppq() as f64
|
||||
}
|
||||
#[inline] pub fn frames_per_pulse (&self) -> f64 {
|
||||
self.rate() as f64 / self.pulses_per_second()
|
||||
}
|
||||
|
||||
#[inline] fn usec_to_frame (&self, usec: f64) -> f64 {
|
||||
|
|
@ -109,43 +96,4 @@ impl Timebase {
|
|||
.collect()
|
||||
}
|
||||
|
||||
#[inline] fn beats_per_second (&self) -> f64 {
|
||||
self.bpm() as f64 / 60000000.0
|
||||
}
|
||||
#[inline] fn ticks_per_second (&self) -> f64 {
|
||||
self.beats_per_second() * self.ppq() as f64
|
||||
}
|
||||
#[inline] pub fn frames_per_tick (&self) -> f64 {
|
||||
self.rate() as f64 / self.ticks_per_second()
|
||||
}
|
||||
}
|
||||
#[cfg(test)] mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_timebase () -> Usually<()> {
|
||||
let timebase = Timebase::new(48000.0, 240.0, 24.0);
|
||||
println!("F/S = {:.03}", s.rate());
|
||||
println!("B/S = {:.03}", s.beats_per_secon());
|
||||
println!("F/B = {:.03}", s.frames_per_beat());
|
||||
println!("T/B = {:.03}", s.ticks_per_beat());
|
||||
println!("F/T = {:.03}", s.frames_per_tick());
|
||||
println!("F/L = {:.03}", s.frames_per_loop());
|
||||
println!("T/L = {:.03}", s.ticks_per_loop());
|
||||
let fpt = s.fpt();
|
||||
let frames_per_chunk = 240;
|
||||
let chunk = |chunk: usize| s.frames_to_ticks(
|
||||
chunk * frames_per_chunk,
|
||||
(chunk + 1) * frames_per_chunk
|
||||
);
|
||||
//for i in 0..2000 {
|
||||
//println!("{i} {:?}", chunk(i));
|
||||
//}
|
||||
assert_eq!(chunk(0), vec![(0, 0), (125, 1)]);
|
||||
assert_eq!(chunk(1), vec![(10, 2), (135, 3)]);
|
||||
assert_eq!(chunk(12), vec![(120, 24)]);
|
||||
assert_eq!(chunk(412), vec![(120, 24)]);
|
||||
assert_eq!(chunk(413), vec![(5, 25), (130, 26)]);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue