mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
show buffer size and latency
This commit is contained in:
parent
763063f4ed
commit
51889d4b43
5 changed files with 33 additions and 14 deletions
|
|
@ -47,17 +47,23 @@ pub struct ClockModel {
|
||||||
pub quant: Arc<Quantize>,
|
pub quant: Arc<Quantize>,
|
||||||
/// Launch quantization factor
|
/// Launch quantization factor
|
||||||
pub sync: Arc<LaunchSync>,
|
pub sync: Arc<LaunchSync>,
|
||||||
|
/// Size of buffer in samples
|
||||||
|
pub chunk: Arc<AtomicUsize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&Arc<Transport>> for ClockModel {
|
impl From<&Arc<RwLock<JackClient>>> for ClockModel {
|
||||||
fn from (transport: &Arc<Transport>) -> Self {
|
fn from (jack: &Arc<RwLock<JackClient>>) -> Self {
|
||||||
|
let jack = jack.read().unwrap();
|
||||||
|
let chunk = jack.client().buffer_size();
|
||||||
|
let transport = jack.client().transport();
|
||||||
Self {
|
Self {
|
||||||
playing: RwLock::new(None).into(),
|
playing: RwLock::new(None).into(),
|
||||||
started: RwLock::new(None).into(),
|
started: RwLock::new(None).into(),
|
||||||
current: Instant::default().into(),
|
current: Instant::default().into(),
|
||||||
quant: Arc::new(24.into()),
|
quant: Arc::new(24.into()),
|
||||||
sync: Arc::new(384.into()),
|
sync: Arc::new(384.into()),
|
||||||
transport: transport.clone(),
|
transport: Arc::new(transport),
|
||||||
|
chunk: Arc::new((chunk as usize).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -137,11 +143,18 @@ pub struct ClockAudio<'a, T: HasClock>(pub &'a mut T);
|
||||||
impl<'a, T: HasClock> Audio for ClockAudio<'a, T> {
|
impl<'a, T: HasClock> Audio for ClockAudio<'a, T> {
|
||||||
#[inline] fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
#[inline] fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||||
let state = self.0.clock();
|
let state = self.0.clock();
|
||||||
let times = scope.cycle_times().unwrap();
|
|
||||||
let CycleTimes { current_frames, current_usecs, next_usecs: _, period_usecs: _ } = times;
|
// Update chunk size
|
||||||
let _chunk_size = scope.n_frames() as usize;
|
state.chunk.store(scope.n_frames() as usize, Ordering::Relaxed);
|
||||||
|
|
||||||
|
// Query transport state
|
||||||
let transport = state.transport.query().unwrap();
|
let transport = state.transport.query().unwrap();
|
||||||
|
|
||||||
|
// FIXME duplicated
|
||||||
state.current.sample.set(transport.pos.frame() as f64);
|
state.current.sample.set(transport.pos.frame() as f64);
|
||||||
|
|
||||||
|
// Update play/pause state and starting point
|
||||||
|
let CycleTimes { current_frames, current_usecs, .. } = scope.cycle_times().unwrap();
|
||||||
let mut playing = state.playing.write().unwrap();
|
let mut playing = state.playing.write().unwrap();
|
||||||
let mut started = state.started.write().unwrap();
|
let mut started = state.started.write().unwrap();
|
||||||
if *playing != Some(transport.state) {
|
if *playing != Some(transport.state) {
|
||||||
|
|
@ -159,10 +172,13 @@ impl<'a, T: HasClock> Audio for ClockAudio<'a, T> {
|
||||||
if *playing == Some(TransportState::Stopped) {
|
if *playing == Some(TransportState::Stopped) {
|
||||||
*started = None;
|
*started = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME duplicated
|
||||||
state.current.update_from_usec(match *started {
|
state.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.
|
||||||
});
|
});
|
||||||
|
|
||||||
Control::Continue
|
Control::Continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for ArrangerTui {
|
||||||
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
jack: jack.clone(),
|
jack: jack.clone(),
|
||||||
clock: ClockModel::from(&Arc::new(jack.read().unwrap().transport())),
|
clock: ClockModel::from(jack),
|
||||||
phrases: PhraseListModel::default(),
|
phrases: PhraseListModel::default(),
|
||||||
editor: PhraseEditorModel::default(),
|
editor: PhraseEditorModel::default(),
|
||||||
selected: ArrangerSelection::Clip(0, 0),
|
selected: ArrangerSelection::Clip(0, 0),
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ pub struct SequencerTui {
|
||||||
impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
|
impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
|
||||||
type Error = Box<dyn std::error::Error>;
|
type Error = Box<dyn std::error::Error>;
|
||||||
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
||||||
let clock = ClockModel::from(&Arc::new(jack.read().unwrap().transport()));
|
let clock = ClockModel::from(jack);
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
jack: jack.clone(),
|
jack: jack.clone(),
|
||||||
phrases: PhraseListModel::default(),
|
phrases: PhraseListModel::default(),
|
||||||
|
|
@ -111,7 +111,7 @@ impl_focus!(SequencerTui SequencerFocus [
|
||||||
pub struct SequencerStatusBar {
|
pub struct SequencerStatusBar {
|
||||||
pub(crate) cpu: Option<String>,
|
pub(crate) cpu: Option<String>,
|
||||||
pub(crate) size: String,
|
pub(crate) size: String,
|
||||||
pub(crate) sr: String,
|
pub(crate) res: String,
|
||||||
pub(crate) mode: &'static str,
|
pub(crate) mode: &'static str,
|
||||||
pub(crate) help: &'static [(&'static str, &'static str, &'static str)]
|
pub(crate) help: &'static [(&'static str, &'static str, &'static str)]
|
||||||
}
|
}
|
||||||
|
|
@ -130,10 +130,13 @@ impl From<&SequencerTui> for SequencerStatusBar {
|
||||||
fn from (state: &SequencerTui) -> Self {
|
fn from (state: &SequencerTui) -> Self {
|
||||||
use SequencerFocus::*;
|
use SequencerFocus::*;
|
||||||
use TransportFocus::*;
|
use TransportFocus::*;
|
||||||
|
let samples = state.clock.chunk.load(Ordering::Relaxed);
|
||||||
|
let rate = state.clock.current.timebase.sr.get() as f64;
|
||||||
|
let buffer = samples as f64 / rate;
|
||||||
Self {
|
Self {
|
||||||
cpu: state.perf.percentage().map(|cpu|format!(" {cpu:.01}% ")),
|
cpu: state.perf.percentage().map(|cpu|format!("│{cpu:.01}%")),
|
||||||
size: format!(" {}x{} ", state.size.w(), state.size.h()),
|
size: format!("{}x{}│", state.size.w(), state.size.h()),
|
||||||
sr: format!(" {}Hz ", state.clock.current.timebase.sr.get()),
|
res: format!("│{}s│{:.1}kHz│{:.1}ms│", samples, rate / 1000., buffer * 1000.),
|
||||||
mode: match state.focused() {
|
mode: match state.focused() {
|
||||||
Transport(focus) => match focus {
|
Transport(focus) => match focus {
|
||||||
PlayPause => " PLAY/PAUSE ",
|
PlayPause => " PLAY/PAUSE ",
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ impl TryFrom<&Arc<RwLock<JackClient>>> for TransportTui {
|
||||||
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
fn try_from (jack: &Arc<RwLock<JackClient>>) -> Usually<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
jack: jack.clone(),
|
jack: jack.clone(),
|
||||||
clock: ClockModel::from(&Arc::new(jack.read().unwrap().transport())),
|
clock: ClockModel::from(jack),
|
||||||
size: Measure::new(),
|
size: Measure::new(),
|
||||||
cursor: (0, 0),
|
cursor: (0, 0),
|
||||||
focus: FocusState::Entered(TransportFocus::PlayPause)
|
focus: FocusState::Entered(TransportFocus::PlayPause)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ impl Content for SequencerStatusBar {
|
||||||
widget(&self.mode).bg(orange).fg(black).bold(true),
|
widget(&self.mode).bg(orange).fg(black).bold(true),
|
||||||
row!(
|
row!(
|
||||||
widget(&self.cpu).fg(orange),
|
widget(&self.cpu).fg(orange),
|
||||||
widget(&self.sr).fg(orange),
|
widget(&self.res).fg(orange),
|
||||||
widget(&self.size).fg(orange),
|
widget(&self.size).fg(orange),
|
||||||
).align_se().fill_x()
|
).align_se().fill_x()
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue