From 276e7ac3c5cf24bbc3d5e41d22f4ecf4e88e37d1 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sun, 27 Oct 2024 17:30:08 +0200 Subject: [PATCH] store Timebase with Instant --- crates/tek_core/src/time.rs | 75 ++++++++++++++++++-------- crates/tek_sequencer/src/transport.rs | 76 +++++++++++++-------------- 2 files changed, 91 insertions(+), 60 deletions(-) diff --git a/crates/tek_core/src/time.rs b/crates/tek_core/src/time.rs index ae1c98f1..d7adb48f 100644 --- a/crates/tek_core/src/time.rs +++ b/crates/tek_core/src/time.rs @@ -155,7 +155,7 @@ pub trait PulsesPerQuaver { } } -pub trait FramePosition { +pub trait SamplePosition { fn sample (&self) -> U; fn set_sample (&self, sample: U); } @@ -233,54 +233,85 @@ impl PulsesPerQuaver for Timebase { #[derive(Debug, Default)] /// Represents a point in time in all scales pub struct Instant { + timebase: Arc, /// Current time in microseconds - pub usec: AtomicUsize, + usec: AtomicUsize, /// Current time in audio samples - pub sample: AtomicUsize, + sample: AtomicUsize, /// Current time in MIDI pulses - pub pulse: AtomicF64, + pulse: AtomicF64, } -impl FramePosition for Instant { +impl SampleRate for Instant { + #[inline] fn sr (&self) -> f64 { self.timebase.sr() } + #[inline] fn set_sr (&self, sr: f64) { self.timebase.set_sr(sr); } +} +impl BeatsPerMinute for Instant { + #[inline] fn bpm (&self) -> f64 { self.timebase.bpm() } + #[inline] fn set_bpm (&self, bpm: f64) { self.timebase.set_bpm(bpm); } +} +impl PulsesPerQuaver for Instant { + const DEFAULT_PPQ: f64 = 96f64; + #[inline] fn ppq (&self) -> f64 { self.timebase.ppq() } + #[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(ppq); } +} +impl SamplePosition for Instant { #[inline] fn sample (&self) -> usize { self.sample.load(Ordering::Relaxed) } - #[inline] fn set_sample (&self, sample: usize) { self.sample.store(sample, Ordering::Relaxed); } + #[inline] fn set_sample (&self, sample: usize) { + self.sample.store(sample, Ordering::Relaxed); + self.set_usec(self.timebase.samples_to_usec(sample as f64) as usize); + self.set_pulse(self.timebase.samples_to_pulse(sample as f64)); + } } impl UsecPosition for Instant { #[inline] fn usec (&self) -> usize { self.usec.load(Ordering::Relaxed) } - #[inline] fn set_usec (&self, usec: usize) { self.usec.store(usec, Ordering::Relaxed); } + #[inline] fn set_usec (&self, usec: usize) { + self.usec.store(usec, Ordering::Relaxed); + self.set_sample(self.timebase.usecs_to_sample(usec as f64) as usize); + self.set_pulse(self.timebase.usecs_to_pulse(usec as f64)); + } } impl PulsePosition for Instant { #[inline] fn pulse (&self) -> f64 { self.pulse.load(Ordering::Relaxed) } - #[inline] fn set_pulse (&self, usec: f64) { self.pulse.store(usec, Ordering::Relaxed); } + #[inline] fn set_pulse (&self, pulse: f64) { + self.pulse.store(pulse, Ordering::Relaxed); + self.set_sample(self.timebase.pulses_to_sample(pulse) as usize); + self.set_usec(self.timebase.pulses_to_usec(pulse) as usize); + } } 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); } + #[inline] fn set_pulse (&self, pulse: usize) { + PulsePosition::::set_pulse(self, pulse as f64) + } } impl Instant { - pub fn from_usec (timebase: &Timebase, usec: usize) -> Self { + pub fn from_usec (timebase: &Arc, 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() + usec: usec.into(), + sample: (timebase.usecs_to_sample(usec as f64) as usize).into(), + pulse: timebase.usecs_to_pulse(usec as f64).into(), + timebase: timebase.clone(), } } - pub fn from_sample (timebase: &Timebase, sample: usize) -> Self { + pub fn from_sample (timebase: &Arc, 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() + sample: sample.into(), + usec: (timebase.samples_to_usec(sample as f64) as usize).into(), + pulse: timebase.samples_to_pulse(sample as f64).into(), + timebase: timebase.clone(), } } - pub fn from_pulse (timebase: &Timebase, pulse: f64) -> Self { + pub fn from_pulse (timebase: &Arc, 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() + pulse: pulse.into(), + sample: (timebase.pulses_to_sample(pulse) as usize).into(), + usec: (timebase.pulses_to_usec(pulse) as usize).into(), + timebase: timebase.clone(), } } } -/// (pulses, name) +/// (pulses, name), assuming 96 PPQ pub const NOTE_DURATIONS: [(usize, &str);26] = [ (1, "1/384"), (2, "1/192"), diff --git a/crates/tek_sequencer/src/transport.rs b/crates/tek_sequencer/src/transport.rs index 32b740b8..5606db3c 100644 --- a/crates/tek_sequencer/src/transport.rs +++ b/crates/tek_sequencer/src/transport.rs @@ -12,6 +12,44 @@ pub struct TransportTime { /// Launch quantization factor pub sync: AtomicUsize, } +impl SampleRate for TransportTime { + #[inline] fn sr (&self) -> f64 { self.timebase.sr() } + #[inline] fn set_sr (&self, sr: f64) { self.timebase.set_sr(sr); } +} +impl BeatsPerMinute for TransportTime { + #[inline] fn bpm (&self) -> f64 { self.timebase.bpm() } + #[inline] fn set_bpm (&self, bpm: f64) { self.timebase.set_bpm(bpm); } +} +impl PulsesPerQuaver for TransportTime { + const DEFAULT_PPQ: f64 = Timebase::DEFAULT_PPQ; + #[inline] fn ppq (&self) -> f64 { self.timebase.ppq() } + #[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(ppq); } +} +impl PulsesPerQuaver for TransportTime { + const DEFAULT_PPQ: usize = Timebase::DEFAULT_PPQ as usize; + #[inline] fn ppq (&self) -> usize { self.timebase.ppq() as usize } + #[inline] fn set_ppq (&self, ppq: usize) { self.timebase.set_ppq(ppq as f64); } +} +impl SamplePosition for TransportTime { + #[inline] fn sample (&self) -> usize { self.instant.sample() } + #[inline] fn set_sample (&self, sample: usize) { self.instant.set_sample(sample) } +} +impl UsecPosition for TransportTime { + #[inline] fn usec (&self) -> usize { self.instant.usec() } + #[inline] fn set_usec (&self, usec: usize) { self.instant.set_usec(usec) } +} +impl PulsePosition for TransportTime { + #[inline] fn pulse (&self) -> usize { self.instant.pulse() } + #[inline] fn set_pulse (&self, usec: usize) { self.instant.set_pulse(usec); } +} +impl Quantize for TransportTime { + #[inline] fn quant (&self) -> usize { self.quant.load(Ordering::Relaxed) } + #[inline] fn set_quant (&self, quant: usize) { self.quant.store(quant, Ordering::Relaxed); } +} +impl LaunchSync for TransportTime { + #[inline] fn sync (&self) -> usize { self.sync.load(Ordering::Relaxed) } + #[inline] fn set_sync (&self, sync: usize) { self.sync.store(sync, Ordering::Relaxed); } +} /// Stores and displays time-related state. pub struct TransportToolbar { _engine: PhantomData, @@ -34,44 +72,6 @@ pub struct TransportToolbar { #[derive(Clone, Copy, PartialEq)] pub enum TransportToolbarFocus { Bpm, Sync, PlayPause, Clock, Quant, } -impl SampleRate for TransportTime { - #[inline] fn sr (&self) -> f64 { self.timebase.sr() } - #[inline] fn set_sr (&self, sr: f64) { self.timebase.set_sr(sr); } -} -impl BeatsPerMinute for TransportTime { - #[inline] fn bpm (&self) -> f64 { self.timebase.bpm() } - #[inline] fn set_bpm (&self, bpm: f64) { self.timebase.set_bpm(bpm); } -} -impl PulsesPerQuaver for TransportTime { - const DEFAULT_PPQ: f64 = Timebase::DEFAULT_PPQ; - #[inline] fn ppq (&self) -> f64 { self.timebase.ppq() } - #[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(ppq); } -} -impl PulsesPerQuaver for TransportTime { - const DEFAULT_PPQ: usize = Timebase::DEFAULT_PPQ as usize; - #[inline] fn ppq (&self) -> usize { self.timebase.ppq() as usize } - #[inline] fn set_ppq (&self, ppq: usize) { self.timebase.set_ppq(ppq as f64); } -} -impl FramePosition for TransportTime { - #[inline] fn sample (&self) -> usize { self.instant.sample() } - #[inline] fn set_sample (&self, sample: usize) { self.instant.set_sample(sample) } -} -impl UsecPosition for TransportTime { - #[inline] fn usec (&self) -> usize { self.instant.usec() } - #[inline] fn set_usec (&self, usec: usize) { self.instant.set_usec(usec) } -} -impl PulsePosition for TransportTime { - #[inline] fn pulse (&self) -> usize { self.instant.pulse() } - #[inline] fn set_pulse (&self, usec: usize) { self.instant.set_pulse(usec); } -} -impl Quantize for TransportTime { - #[inline] fn quant (&self) -> usize { self.quant.load(Ordering::Relaxed) } - #[inline] fn set_quant (&self, quant: usize) { self.quant.store(quant, Ordering::Relaxed); } -} -impl LaunchSync for TransportTime { - #[inline] fn sync (&self) -> usize { self.sync.load(Ordering::Relaxed) } - #[inline] fn set_sync (&self, sync: usize) { self.sync.store(sync, Ordering::Relaxed); } -} impl TransportToolbar { pub fn new ( clock: Option<&Arc>,