diff --git a/crates/tek_core/src/time.rs b/crates/tek_core/src/time.rs index 16e3f72b..cf6d8479 100644 --- a/crates/tek_core/src/time.rs +++ b/crates/tek_core/src/time.rs @@ -2,10 +2,10 @@ use crate::*; use std::iter::Iterator; /// Any numeric type that represents time -pub trait TimeUnit: PartialEq + Copy +pub trait TimeUnit: PartialEq + Copy + Display + Add + Mul + Div + Rem {} -impl TimeUnit for T where T: PartialEq + Copy +impl TimeUnit for T where T: PartialEq + Copy + Display + Add + Mul + Div + Rem {} @@ -79,6 +79,12 @@ 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 + where U: TimeFloat, Self: BeatsPerMinute + { + usec / self.usec_per_pulse() + } /// Return duration of a pulse in microseconds (BPM-dependent) #[inline] fn usec_per_pulse (&self) -> U where U: TimeFloat, Self: BeatsPerMinute @@ -135,13 +141,13 @@ pub trait UsecPosition { pub trait LaunchSync { fn sync (&self) -> U; fn set_sync (&self, sync: U); - #[inline] fn next_launch_sample (&self) -> U where U: TimeInteger, Self: FramePosition { + #[inline] fn next_launch_sample (&self) -> U where U: TimeInteger, Self: PulsePosition { let sync = self.sync(); - let sample = self.sample(); - if sample % sync == U::from(0) { - sample + let pulse = self.pulse(); + if pulse % sync == U::from(0) { + pulse } else { - (sample / sync) * sync + U::from(1) + (pulse / sync) * sync + U::from(1) } } } @@ -251,10 +257,10 @@ impl Iterator for TicksIterator { if self.1 > self.3 { return None } - let fpt = self.0; + let fpt = self.0; let sample = self.1 as f64; - let start = self.2; - let end = self.3; + let start = self.2; + let end = self.3; self.1 = self.1 + 1; //println!("{fpt} {sample} {start} {end}"); let jitter = sample.rem_euclid(fpt); // ramps diff --git a/crates/tek_sequencer/src/arranger.rs b/crates/tek_sequencer/src/arranger.rs index 187077e5..8ef229af 100644 --- a/crates/tek_sequencer/src/arranger.rs +++ b/crates/tek_sequencer/src/arranger.rs @@ -237,13 +237,11 @@ impl Arrangement { match self.selected { ArrangementFocus::Scene(s) => { for (t, track) in self.tracks.iter_mut().enumerate() { - let start = self.clock.next_launch_sample(); - track.player.enqueue_next(start, self.scenes[s].clips[t].as_ref()); + track.player.enqueue_next(self.scenes[s].clips[t].as_ref()); } }, ArrangementFocus::Clip(t, s) => { - let start = self.clock.next_launch_sample(); - self.tracks[t].player.enqueue_next(start, self.scenes[s].clips[t].as_ref()); + self.tracks[t].player.enqueue_next(self.scenes[s].clips[t].as_ref()); }, _ => {} } diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_sequencer/src/sequencer.rs index 80dbcb18..16ad60a8 100644 --- a/crates/tek_sequencer/src/sequencer.rs +++ b/crates/tek_sequencer/src/sequencer.rs @@ -345,8 +345,9 @@ impl PhrasePlayer { pub fn toggle_monitor (&mut self) { self.monitoring = !self.monitoring; } pub fn toggle_record (&mut self) { self.recording = !self.recording; } pub fn toggle_overdub (&mut self) { self.overdub = !self.overdub; } - pub fn enqueue_next (&mut self, start_at: usize, phrase: Option<&Arc>>) { - self.next_phrase = Some((start_at.into(), phrase.map(|p|p.clone()))); + pub fn enqueue_next (&mut self, phrase: Option<&Arc>>) { + let start = self.clock.next_launch_sample(); + self.next_phrase = Some((start.into(), phrase.map(|p|p.clone()))); self.reset = true; } pub fn frames_since_start (&self) -> Option { diff --git a/crates/tek_sequencer/src/transport_snd.rs b/crates/tek_sequencer/src/transport_snd.rs index dfd68e49..d568dd3c 100644 --- a/crates/tek_sequencer/src/transport_snd.rs +++ b/crates/tek_sequencer/src/transport_snd.rs @@ -1,28 +1,16 @@ use crate::*; impl Audio for TransportToolbar { fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { - let _ = self.update(&scope); - Control::Continue - } -} -impl TransportToolbar { - pub fn update (&mut self, scope: &ProcessScope) -> (bool, usize, usize, usize, usize, f64) { let times = scope.cycle_times().unwrap(); - let CycleTimes { current_frames, current_usecs, next_usecs, period_usecs } = times; - let chunk_size = scope.n_frames() as usize; + 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_sample(transport.pos.frame() as usize); - let mut reset = false; if *self.clock.playing.read().unwrap() != Some(transport.state) { - match transport.state { - TransportState::Rolling => { - self.started = Some((current_frames as usize, current_usecs as usize)); - }, - TransportState::Stopped => { - self.started = None; - reset = true; - }, - _ => {} + self.started = match transport.state { + TransportState::Rolling => Some((current_frames as usize, current_usecs as usize)), + TransportState::Stopped => None, + _ => self.started } }; *self.clock.playing.write().unwrap() = Some(transport.state); @@ -30,16 +18,14 @@ impl TransportToolbar { self.started = None; } match self.started { - Some((_, usecs)) => { self.clock.set_usec(current_usecs as usize - usecs); }, + Some((_, usecs)) => { + let usec = current_usecs as usize - usecs; + let pulse = self.clock.usecs_to_pulse(usec as f64); + self.clock.set_usec(usec); + self.clock.set_pulse(pulse as usize); + }, None => { self.clock.set_usec(0); } }; - ( - reset, - current_frames as usize, - chunk_size as usize, - current_usecs as usize, - next_usecs as usize, - period_usecs as f64 - ) + Control::Continue } }