mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
rename frame to sample everywhere
This commit is contained in:
parent
063706017e
commit
d77fe325b0
7 changed files with 40 additions and 38 deletions
|
|
@ -9,7 +9,7 @@ impl<T> TimeUnit for T where T: PartialEq + Copy
|
||||||
+ Add<Self, Output=Self> + Mul<Self, Output=Self>
|
+ Add<Self, Output=Self> + Mul<Self, Output=Self>
|
||||||
+ Div<Self, Output=Self> + Rem<Self, Output=Self> {}
|
+ Div<Self, Output=Self> + Rem<Self, Output=Self> {}
|
||||||
|
|
||||||
/// Integer time unit, such as frames, pulses, or microseconds
|
/// Integer time unit, such as samples, pulses, or microseconds
|
||||||
pub trait TimeInteger: TimeUnit + From<usize> + Into<usize> + Copy {}
|
pub trait TimeInteger: TimeUnit + From<usize> + Into<usize> + Copy {}
|
||||||
impl<T> TimeInteger for T where T: TimeUnit + From<usize> + Into<usize> + Copy {}
|
impl<T> TimeInteger for T where T: TimeUnit + From<usize> + Into<usize> + Copy {}
|
||||||
|
|
||||||
|
|
@ -51,12 +51,12 @@ pub trait BeatsPerMinute<U: TimeFloat> {
|
||||||
#[inline] fn note_to_usec (&self, (num, den): (U, U)) -> U {
|
#[inline] fn note_to_usec (&self, (num, den): (U, U)) -> U {
|
||||||
U::from(4.0) * self.usec_per_beat() * num / den
|
U::from(4.0) * self.usec_per_beat() * num / den
|
||||||
}
|
}
|
||||||
/// Return the number of frames corresponding to a note of the given duration
|
/// Return the number of samples corresponding to a note of the given duration
|
||||||
#[inline] fn note_to_frame (&self, note: (U, U)) -> U where Self: SampleRate<U> {
|
#[inline] fn note_to_samples (&self, note: (U, U)) -> U where Self: SampleRate<U> {
|
||||||
self.usec_to_frame(self.note_to_usec(note))
|
self.usec_to_sample(self.note_to_usec(note))
|
||||||
}
|
}
|
||||||
/// Return the number of frames corresponding to the given number of microseconds
|
/// Return the number of samples corresponding to the given number of microseconds
|
||||||
#[inline] fn usec_to_frame (&self, usec: U) -> U where Self: SampleRate<U> {
|
#[inline] fn usec_to_sample (&self, usec: U) -> U where Self: SampleRate<U> {
|
||||||
usec * self.sr() / U::from(1000f64)
|
usec * self.sr() / U::from(1000f64)
|
||||||
}
|
}
|
||||||
/// Return the quantized position of a moment in time given a step
|
/// Return the quantized position of a moment in time given a step
|
||||||
|
|
@ -118,8 +118,8 @@ pub trait PulsesPerQuaver<U: TimeUnit> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FramePosition<U: TimeUnit> {
|
pub trait FramePosition<U: TimeUnit> {
|
||||||
fn frame (&self) -> U;
|
fn sample (&self) -> U;
|
||||||
fn set_frame (&self, frame: U);
|
fn set_sample (&self, sample: U);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PulsePosition<U: TimeUnit> {
|
pub trait PulsePosition<U: TimeUnit> {
|
||||||
|
|
@ -135,13 +135,13 @@ pub trait UsecPosition<U: TimeUnit> {
|
||||||
pub trait LaunchSync<U: TimeUnit> {
|
pub trait LaunchSync<U: TimeUnit> {
|
||||||
fn sync (&self) -> U;
|
fn sync (&self) -> U;
|
||||||
fn set_sync (&self, sync: U);
|
fn set_sync (&self, sync: U);
|
||||||
#[inline] fn next_launch_frame (&self) -> U where U: TimeInteger, Self: FramePosition<U> {
|
#[inline] fn next_launch_sample (&self) -> U where U: TimeInteger, Self: FramePosition<U> {
|
||||||
let sync = self.sync();
|
let sync = self.sync();
|
||||||
let frame = self.frame();
|
let sample = self.sample();
|
||||||
if frame % sync == U::from(0) {
|
if sample % sync == U::from(0) {
|
||||||
frame
|
sample
|
||||||
} else {
|
} 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);
|
pub struct Ticks(pub f64);
|
||||||
|
|
||||||
impl Ticks {
|
impl Ticks {
|
||||||
/// Iterate over ticks between start and end.
|
/// 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)
|
TicksIterator(self.0, start, start, end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -252,16 +252,16 @@ impl Iterator for TicksIterator {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
let fpt = self.0;
|
let fpt = self.0;
|
||||||
let frame = self.1 as f64;
|
let sample = self.1 as f64;
|
||||||
let start = self.2;
|
let start = self.2;
|
||||||
let end = self.3;
|
let end = self.3;
|
||||||
self.1 = self.1 + 1;
|
self.1 = self.1 + 1;
|
||||||
//println!("{fpt} {frame} {start} {end}");
|
//println!("{fpt} {sample} {start} {end}");
|
||||||
let jitter = frame.rem_euclid(fpt); // ramps
|
let jitter = sample.rem_euclid(fpt); // ramps
|
||||||
let next_jitter = (frame + 1.0).rem_euclid(fpt);
|
let next_jitter = (sample + 1.0).rem_euclid(fpt);
|
||||||
if jitter > next_jitter { // at crossing:
|
if jitter > next_jitter { // at crossing:
|
||||||
let time = (frame as usize) % (end as usize-start as usize);
|
let time = (sample as usize) % (end as usize-start as usize);
|
||||||
let tick = (frame / fpt) as usize;
|
let tick = (sample / fpt) as usize;
|
||||||
return Some((time, tick))
|
return Some((time, tick))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -273,8 +273,8 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_frames_to_ticks () {
|
fn test_samples_to_ticks () {
|
||||||
let ticks = Ticks(12.3).between_frames(0, 100).collect::<Vec<_>>();
|
let ticks = Ticks(12.3).between_samples(0, 100).collect::<Vec<_>>();
|
||||||
println!("{ticks:?}");
|
println!("{ticks:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -237,12 +237,12 @@ impl<E: Engine> Arrangement<E> {
|
||||||
match self.selected {
|
match self.selected {
|
||||||
ArrangementFocus::Scene(s) => {
|
ArrangementFocus::Scene(s) => {
|
||||||
for (t, track) in self.tracks.iter_mut().enumerate() {
|
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());
|
track.player.enqueue_next(start, self.scenes[s].clips[t].as_ref());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ArrangementFocus::Clip(t, s) => {
|
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());
|
self.tracks[t].player.enqueue_next(start, self.scenes[s].clips[t].as_ref());
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,9 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
.map(|t|format!("▎{t:>}"))
|
.map(|t|format!("▎{t:>}"))
|
||||||
.unwrap_or(String::from("▎"));
|
.unwrap_or(String::from("▎"));
|
||||||
let time2 = track.player.next_phrase.as_ref()
|
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("▎"));
|
.unwrap_or(String::from("▎"));
|
||||||
col!(name, time1, time2)
|
col!(name, time1, time2)
|
||||||
.min_xy(w as u16, title_h)
|
.min_xy(w as u16, title_h)
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ impl<E: Engine> PhrasePlayer<E> {
|
||||||
pub fn frames_since_start (&self) -> Option<usize> {
|
pub fn frames_since_start (&self) -> Option<usize> {
|
||||||
self.phrase.as_ref()
|
self.phrase.as_ref()
|
||||||
.map(|(started,_)|started.load(Ordering::Relaxed))
|
.map(|(started,_)|started.load(Ordering::Relaxed))
|
||||||
.map(|started|started - self.clock.frame())
|
.map(|started|started - self.clock.sample())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Displays and edits phrase length
|
/// Displays and edits phrase length
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ impl Phrase {
|
||||||
(frame0, frames, _): (usize, usize, f64),
|
(frame0, frames, _): (usize, usize, f64),
|
||||||
) {
|
) {
|
||||||
let mut buf = Vec::with_capacity(8);
|
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
|
frame0, frame0 + frames
|
||||||
) {
|
) {
|
||||||
let tick = tick % self.length;
|
let tick = tick % self.length;
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ pub struct TransportTime {
|
||||||
pub timebase: Timebase,
|
pub timebase: Timebase,
|
||||||
/// Playback state
|
/// Playback state
|
||||||
pub playing: RwLock<Option<TransportState>>,
|
pub playing: RwLock<Option<TransportState>>,
|
||||||
/// Current time in frames
|
/// Current time in samples
|
||||||
pub frame: AtomicUsize,
|
pub sample: AtomicUsize,
|
||||||
/// Current time in pulses
|
/// Current time in pulses
|
||||||
pub pulse: AtomicUsize,
|
pub pulse: AtomicUsize,
|
||||||
/// Current time in microseconds
|
/// Current time in microseconds
|
||||||
|
|
@ -27,7 +27,7 @@ pub struct TransportToolbar<E: Engine> {
|
||||||
pub jack: Option<JackClient>,
|
pub jack: Option<JackClient>,
|
||||||
/// JACK transport handle.
|
/// JACK transport handle.
|
||||||
pub transport: Option<Transport>,
|
pub transport: Option<Transport>,
|
||||||
/// Global frame and usec at which playback started
|
/// Global sample and usec at which playback started
|
||||||
pub started: Option<(usize, usize)>,
|
pub started: Option<(usize, usize)>,
|
||||||
/// Whether the toolbar is focused
|
/// Whether the toolbar is focused
|
||||||
pub focused: bool,
|
pub focused: bool,
|
||||||
|
|
@ -52,8 +52,8 @@ impl PulsesPerQuaver<f64> for TransportTime {
|
||||||
#[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(ppq); }
|
#[inline] fn set_ppq (&self, ppq: f64) { self.timebase.set_ppq(ppq); }
|
||||||
}
|
}
|
||||||
impl FramePosition<usize> for TransportTime {
|
impl FramePosition<usize> for TransportTime {
|
||||||
#[inline] fn frame (&self) -> usize { self.frame.load(Ordering::Relaxed) }
|
#[inline] fn sample (&self) -> usize { self.sample.load(Ordering::Relaxed) }
|
||||||
#[inline] fn set_frame (&self, frame: usize) { self.frame.store(frame, Ordering::Relaxed); }
|
#[inline] fn set_sample (&self, sample: usize) { self.sample.store(sample, Ordering::Relaxed); }
|
||||||
}
|
}
|
||||||
impl UsecPosition<usize> for TransportTime {
|
impl UsecPosition<usize> for TransportTime {
|
||||||
#[inline] fn usec (&self) -> usize { self.usecs.load(Ordering::Relaxed) }
|
#[inline] fn usec (&self) -> usize { self.usecs.load(Ordering::Relaxed) }
|
||||||
|
|
@ -92,7 +92,7 @@ impl<E: Engine> TransportToolbar<E> {
|
||||||
playing: Some(TransportState::Stopped).into(),
|
playing: Some(TransportState::Stopped).into(),
|
||||||
quant: 24.into(),
|
quant: 24.into(),
|
||||||
sync: (timebase.ppq() as usize * 4).into(),
|
sync: (timebase.ppq() as usize * 4).into(),
|
||||||
frame: 0.into(),
|
sample: 0.into(),
|
||||||
pulse: 0.into(),
|
pulse: 0.into(),
|
||||||
usecs: 0.into(),
|
usecs: 0.into(),
|
||||||
timebase,
|
timebase,
|
||||||
|
|
@ -102,13 +102,13 @@ impl<E: Engine> TransportToolbar<E> {
|
||||||
}
|
}
|
||||||
pub fn bpm (&self) -> usize { self.clock.bpm() as usize }
|
pub fn bpm (&self) -> usize { self.clock.bpm() as usize }
|
||||||
pub fn ppq (&self) -> usize { self.clock.ppq() 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 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.frame() 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 quant (&self) -> usize { self.clock.quant() }
|
||||||
pub fn sync (&self) -> usize { self.clock.sync() }
|
pub fn sync (&self) -> usize { self.clock.sync() }
|
||||||
pub fn toggle_play (&mut self) -> Usually<()> {
|
pub fn toggle_play (&mut self) -> Usually<()> {
|
||||||
let transport = self.transport.as_ref().unwrap();
|
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 {
|
let playing = match playing {
|
||||||
TransportState::Stopped => {
|
TransportState::Stopped => {
|
||||||
transport.start()?;
|
transport.start()?;
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ impl<E: Engine> TransportToolbar<E> {
|
||||||
let CycleTimes { current_frames, current_usecs, next_usecs, period_usecs } = times;
|
let CycleTimes { current_frames, current_usecs, next_usecs, period_usecs } = times;
|
||||||
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.set_frame(transport.pos.frame() as usize);
|
self.clock.set_sample(transport.pos.frame() as usize);
|
||||||
let mut reset = false;
|
let mut reset = false;
|
||||||
if *self.clock.playing.read().unwrap() != Some(transport.state) {
|
if *self.clock.playing.read().unwrap() != Some(transport.state) {
|
||||||
match transport.state {
|
match transport.state {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue