diff --git a/crates/tek_core/src/time.rs b/crates/tek_core/src/time.rs index 69ac840e..16e3f72b 100644 --- a/crates/tek_core/src/time.rs +++ b/crates/tek_core/src/time.rs @@ -9,7 +9,7 @@ impl TimeUnit for T where T: PartialEq + Copy + Add + Mul + Div + Rem {} -/// Integer time unit, such as frames, pulses, or microseconds +/// Integer time unit, such as samples, pulses, or microseconds pub trait TimeInteger: TimeUnit + From + Into + Copy {} impl TimeInteger for T where T: TimeUnit + From + Into + Copy {} @@ -51,12 +51,12 @@ pub trait BeatsPerMinute { #[inline] fn note_to_usec (&self, (num, den): (U, U)) -> U { U::from(4.0) * self.usec_per_beat() * num / den } - /// Return the number of frames corresponding to a note of the given duration - #[inline] fn note_to_frame (&self, note: (U, U)) -> U where Self: SampleRate { - self.usec_to_frame(self.note_to_usec(note)) + /// Return the number of samples corresponding to a note of the given duration + #[inline] fn note_to_samples (&self, note: (U, U)) -> U where Self: SampleRate { + self.usec_to_sample(self.note_to_usec(note)) } - /// Return the number of frames corresponding to the given number of microseconds - #[inline] fn usec_to_frame (&self, usec: U) -> U where Self: SampleRate { + /// Return the number of samples corresponding to the given number of microseconds + #[inline] fn usec_to_sample (&self, usec: U) -> U where Self: SampleRate { usec * self.sr() / U::from(1000f64) } /// Return the quantized position of a moment in time given a step @@ -118,8 +118,8 @@ pub trait PulsesPerQuaver { } pub trait FramePosition { - fn frame (&self) -> U; - fn set_frame (&self, frame: U); + fn sample (&self) -> U; + fn set_sample (&self, sample: U); } pub trait PulsePosition { @@ -135,13 +135,13 @@ pub trait UsecPosition { pub trait LaunchSync { fn sync (&self) -> U; fn set_sync (&self, sync: U); - #[inline] fn next_launch_frame (&self) -> U where U: TimeInteger, Self: FramePosition { + #[inline] fn next_launch_sample (&self) -> U where U: TimeInteger, Self: FramePosition { let sync = self.sync(); - let frame = self.frame(); - if frame % sync == U::from(0) { - frame + let sample = self.sample(); + if sample % sync == U::from(0) { + sample } else { - (frame / sync) * sync + U::from(1) + (sample / sync) * sync + U::from(1) } } } @@ -231,12 +231,12 @@ pub fn pulses_to_name (pulses: usize) -> &'static str { "" } -/// Defines frames per tick. +/// Defines samples per tick. pub struct Ticks(pub f64); impl Ticks { /// Iterate over ticks between start and end. - pub fn between_frames (&self, start: usize, end: usize) -> TicksIterator { + pub fn between_samples (&self, start: usize, end: usize) -> TicksIterator { TicksIterator(self.0, start, start, end) } } @@ -252,16 +252,16 @@ impl Iterator for TicksIterator { return None } let fpt = self.0; - let frame = self.1 as f64; + let sample = self.1 as f64; let start = self.2; let end = self.3; self.1 = self.1 + 1; - //println!("{fpt} {frame} {start} {end}"); - let jitter = frame.rem_euclid(fpt); // ramps - let next_jitter = (frame + 1.0).rem_euclid(fpt); + //println!("{fpt} {sample} {start} {end}"); + let jitter = sample.rem_euclid(fpt); // ramps + let next_jitter = (sample + 1.0).rem_euclid(fpt); if jitter > next_jitter { // at crossing: - let time = (frame as usize) % (end as usize-start as usize); - let tick = (frame / fpt) as usize; + let time = (sample as usize) % (end as usize-start as usize); + let tick = (sample / fpt) as usize; return Some((time, tick)) } } @@ -273,8 +273,8 @@ mod test { use super::*; #[test] - fn test_frames_to_ticks () { - let ticks = Ticks(12.3).between_frames(0, 100).collect::>(); + fn test_samples_to_ticks () { + let ticks = Ticks(12.3).between_samples(0, 100).collect::>(); println!("{ticks:?}"); } diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index 19e0450d..187077e5 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -237,12 +237,12 @@ impl Arrangement { match self.selected { ArrangementFocus::Scene(s) => { for (t, track) in self.tracks.iter_mut().enumerate() { - let start = self.clock.next_launch_frame(); + let start = self.clock.next_launch_sample(); track.player.enqueue_next(start, self.scenes[s].clips[t].as_ref()); } }, ArrangementFocus::Clip(t, s) => { - let start = self.clock.next_launch_frame(); + let start = self.clock.next_launch_sample(); self.tracks[t].player.enqueue_next(start, self.scenes[s].clips[t].as_ref()); }, _ => {} diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index 74ab2d9b..6070d95a 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -174,7 +174,9 @@ impl<'a> Content for VerticalArranger<'a, Tui> { .map(|t|format!("▎{t:>}")) .unwrap_or(String::from("▎")); let time2 = track.player.next_phrase.as_ref() - .map(|(t, _)|format!("▎{:>}", t.load(Ordering::Relaxed))) + .map(|(t, _)|format!("▎{:>}", + track.player.clock.samples_to_pulse(t.load(Ordering::Relaxed) as f64) + )) .unwrap_or(String::from("▎")); col!(name, time1, time2) .min_xy(w as u16, title_h) diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_sequencer/src/sequencer.rs index 3490475a..80dbcb18 100644 --- a/crates/tek_sequencer/src/sequencer.rs +++ b/crates/tek_sequencer/src/sequencer.rs @@ -352,7 +352,7 @@ impl PhrasePlayer { pub fn frames_since_start (&self) -> Option { self.phrase.as_ref() .map(|(started,_)|started.load(Ordering::Relaxed)) - .map(|started|started - self.clock.frame()) + .map(|started|started - self.clock.sample()) } } /// Displays and edits phrase length diff --git a/crates/tek_sequencer/src/sequencer_snd.rs b/crates/tek_sequencer/src/sequencer_snd.rs index eb29cb3f..3253acd7 100644 --- a/crates/tek_sequencer/src/sequencer_snd.rs +++ b/crates/tek_sequencer/src/sequencer_snd.rs @@ -9,7 +9,7 @@ impl Phrase { (frame0, frames, _): (usize, usize, f64), ) { let mut buf = Vec::with_capacity(8); - for (time, tick) in Ticks(timebase.pulses_per_sample()).between_frames( + for (time, tick) in Ticks(timebase.pulses_per_sample()).between_samples( frame0, frame0 + frames ) { let tick = tick % self.length; diff --git a/crates/tek_sequencer/src/transport.rs b/crates/tek_sequencer/src/transport.rs index 9e9ff3d8..7c1eb9a6 100644 --- a/crates/tek_sequencer/src/transport.rs +++ b/crates/tek_sequencer/src/transport.rs @@ -5,8 +5,8 @@ pub struct TransportTime { pub timebase: Timebase, /// Playback state pub playing: RwLock>, - /// Current time in frames - pub frame: AtomicUsize, + /// Current time in samples + pub sample: AtomicUsize, /// Current time in pulses pub pulse: AtomicUsize, /// Current time in microseconds @@ -27,7 +27,7 @@ pub struct TransportToolbar { pub jack: Option, /// JACK transport handle. pub transport: Option, - /// Global frame and usec at which playback started + /// Global sample and usec at which playback started pub started: Option<(usize, usize)>, /// Whether the toolbar is focused pub focused: bool, @@ -52,8 +52,8 @@ impl PulsesPerQuaver for TransportTime { #[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(ppq); } } impl FramePosition for TransportTime { - #[inline] fn frame (&self) -> usize { self.frame.load(Ordering::Relaxed) } - #[inline] fn set_frame (&self, frame: usize) { self.frame.store(frame, Ordering::Relaxed); } + #[inline] fn sample (&self) -> usize { self.sample.load(Ordering::Relaxed) } + #[inline] fn set_sample (&self, sample: usize) { self.sample.store(sample, Ordering::Relaxed); } } impl UsecPosition for TransportTime { #[inline] fn usec (&self) -> usize { self.usecs.load(Ordering::Relaxed) } @@ -92,7 +92,7 @@ impl TransportToolbar { playing: Some(TransportState::Stopped).into(), quant: 24.into(), sync: (timebase.ppq() as usize * 4).into(), - frame: 0.into(), + sample: 0.into(), pulse: 0.into(), usecs: 0.into(), timebase, @@ -102,13 +102,13 @@ impl TransportToolbar { } pub fn bpm (&self) -> usize { self.clock.bpm() as usize } pub fn ppq (&self) -> usize { self.clock.ppq() as usize } - pub fn pulse (&self) -> usize { self.clock.samples_to_pulse(self.clock.frame()as f64) as usize } - pub fn usecs (&self) -> usize { self.clock.samples_to_usec(self.clock.frame() as f64) as usize } + pub fn pulse (&self) -> usize { self.clock.samples_to_pulse(self.clock.sample()as f64) as usize } + pub fn usecs (&self) -> usize { self.clock.samples_to_usec(self.clock.sample() as f64) as usize } pub fn quant (&self) -> usize { self.clock.quant() } pub fn sync (&self) -> usize { self.clock.sync() } pub fn toggle_play (&mut self) -> Usually<()> { let transport = self.transport.as_ref().unwrap(); - let playing = self.clock.playing.read().unwrap().expect("1st frame has not been processed yet"); + let playing = self.clock.playing.read().unwrap().expect("1st sample has not been processed yet"); let playing = match playing { TransportState::Stopped => { transport.start()?; diff --git a/crates/tek_sequencer/src/transport_snd.rs b/crates/tek_sequencer/src/transport_snd.rs index 8c8cbb1a..dfd68e49 100644 --- a/crates/tek_sequencer/src/transport_snd.rs +++ b/crates/tek_sequencer/src/transport_snd.rs @@ -11,7 +11,7 @@ impl TransportToolbar { let CycleTimes { current_frames, current_usecs, next_usecs, period_usecs } = times; let chunk_size = scope.n_frames() as usize; let transport = self.transport.as_ref().unwrap().query().unwrap(); - self.clock.set_frame(transport.pos.frame() as usize); + self.clock.set_sample(transport.pos.frame() as usize); let mut reset = false; if *self.clock.playing.read().unwrap() != Some(transport.state) { match transport.state {