move started field onto TransportTime

This commit is contained in:
🪞👃🪞 2024-11-02 01:17:02 +02:00
parent 4df15d6bac
commit 3ee9a670da
4 changed files with 40 additions and 48 deletions

View file

@ -59,13 +59,21 @@ macro_rules! time_unit {
time_unit!(SampleRate); time_unit!(SampleRate);
impl SampleRate { impl SampleRate {
/// Return the duration of a sample in microseconds (floating) /// Return the duration of a sample in microseconds (floating)
#[inline] pub fn usec_per_sample (&self) -> f64 { 1_000_000f64 / self.get() } #[inline] pub fn usec_per_sample (&self) -> f64 {
1_000_000f64 / self.get()
}
/// Return the duration of a sample in microseconds (floating) /// Return the duration of a sample in microseconds (floating)
#[inline] pub fn sample_per_usec (&self) -> f64 { self.get() / 1_000_000f64 } #[inline] pub fn sample_per_usec (&self) -> f64 {
self.get() / 1_000_000f64
}
/// Convert a number of samples to microseconds (floating) /// Convert a number of samples to microseconds (floating)
#[inline] pub fn samples_to_usec (&self, samples: f64) -> f64 { samples * self.usec_per_sample() } #[inline] pub fn samples_to_usec (&self, samples: f64) -> f64 {
self.usec_per_sample() * samples
}
/// Convert a number of microseconds to samples (floating) /// Convert a number of microseconds to samples (floating)
#[inline] pub fn usecs_to_sample (&self, usecs: f64) -> f64 { usecs * self.sample_per_usec() } #[inline] pub fn usecs_to_sample (&self, usecs: f64) -> f64 {
self.sample_per_usec() * usecs
}
} }
time_unit!(BeatsPerMinute); time_unit!(BeatsPerMinute);
@ -256,28 +264,6 @@ impl Instant {
self.timebase.format_beats_1(self.pulse.get()) self.timebase.format_beats_1(self.pulse.get())
} }
} }
/// A timer with starting point, current time, and quantization
pub struct Timer {
pub timebase: Arc<Timebase>,
/// Starting point in global time
pub started: Option<Instant>,
/// Current moment in global time
pub current: Instant,
/// Note quantization factor
pub quant: Quantize,
/// Launch quantization factor
pub sync: LaunchSync,
/// Playback state
pub playing: RwLock<Option<jack::TransportState>>,
}
/// Something that defines launch quantization
impl Timer {
#[inline] pub fn next_launch_pulse (&self) -> usize {
let sync = self.sync.get() as usize;
let pulse = self.current.pulse.get() as usize;
if pulse % sync == 0 { pulse } else { (pulse / sync + 1) * sync }
}
}
/// Iterator that emits subsequent ticks within a range. /// Iterator that emits subsequent ticks within a range.
pub struct TicksIterator { pub struct TicksIterator {
spp: f64, spp: f64,

View file

@ -1,14 +1,16 @@
use crate::*; use crate::*;
#[derive(Debug, Default)] /// A timer with starting point, current time, and quantization
pub struct TransportTime { #[derive(Debug, Default)] pub struct TransportTime {
/// Playback state
pub playing: RwLock<Option<TransportState>>,
/// Global sample and usec at which playback started
pub started: RwLock<Option<(usize, usize)>>,
/// Current moment in time /// Current moment in time
pub current: Instant, pub current: Instant,
/// Note quantization factor /// Note quantization factor
pub quant: Quantize, pub quant: Quantize,
/// Launch quantization factor /// Launch quantization factor
pub sync: LaunchSync, pub sync: LaunchSync,
/// Playback state
pub playing: RwLock<Option<TransportState>>,
} }
impl TransportTime { impl TransportTime {
#[inline] pub fn timebase (&self) -> &Arc<Timebase> { &self.current.timebase } #[inline] pub fn timebase (&self) -> &Arc<Timebase> { &self.current.timebase }
@ -32,8 +34,6 @@ pub struct TransportToolbar<E: Engine> {
pub jack: Option<Arc<JackClient>>, pub jack: Option<Arc<JackClient>>,
/// JACK transport handle. /// JACK transport handle.
pub transport: Option<Transport>, pub transport: Option<Transport>,
/// Global sample and usec at which playback started
pub started: Option<(usize, usize)>,
/// Whether the toolbar is focused /// Whether the toolbar is focused
pub focused: bool, pub focused: bool,
/// Which part of the toolbar is focused /// Which part of the toolbar is focused
@ -52,7 +52,6 @@ impl<E: Engine> TransportToolbar<E> {
focused: false, focused: false,
focus: TransportToolbarFocus::PlayPause, focus: TransportToolbarFocus::PlayPause,
metronome: false, metronome: false,
started: None,
jack: None, jack: None,
transport, transport,
clock: match clock { clock: match clock {
@ -64,6 +63,7 @@ impl<E: Engine> TransportToolbar<E> {
quant: 24.into(), quant: 24.into(),
sync: (timebase.ppq.get() * 4.).into(), sync: (timebase.ppq.get() * 4.).into(),
current: Instant::default(), current: Instant::default(),
started: None.into(),
}) })
} }
} }

View file

@ -6,18 +6,24 @@ impl<E: Engine> Audio for TransportToolbar<E> {
let _chunk_size = scope.n_frames() as usize; let _chunk_size = scope.n_frames() as usize;
let transport = self.transport.as_ref().unwrap().query().unwrap(); let transport = self.transport.as_ref().unwrap().query().unwrap();
self.clock.current.sample.set(transport.pos.frame() as f64); self.clock.current.sample.set(transport.pos.frame() as f64);
if *self.clock.playing.read().unwrap() != Some(transport.state) { let mut playing = self.clock.playing.write().unwrap();
self.started = match transport.state { let mut started = self.clock.started.write().unwrap();
TransportState::Rolling => Some((current_frames as usize, current_usecs as usize)), if *playing != Some(transport.state) {
TransportState::Stopped => None, match transport.state {
_ => self.started TransportState::Rolling => {
*started = Some((current_frames as usize, current_usecs as usize))
},
TransportState::Stopped => {
*started = None
},
_ => {}
} }
}; };
*self.clock.playing.write().unwrap() = Some(transport.state); *playing = Some(transport.state);
if *self.clock.playing.read().unwrap() == Some(TransportState::Stopped) { if *playing == Some(TransportState::Stopped) {
self.started = None; *started = None;
} }
self.clock.current.update_from_usec(match self.started { self.clock.current.update_from_usec(match *started {
Some((_, usecs)) => current_usecs as f64 - usecs as f64, Some((_, usecs)) => current_usecs as f64 - usecs as f64,
None => 0. None => 0.
}); });