mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-07-17 15:56:57 +02:00
restruct: 21e
This commit is contained in:
parent
3bbe52093e
commit
47ef33180c
5 changed files with 85 additions and 80 deletions
|
|
@ -65,18 +65,6 @@ pub trait HasClock: AsRef<Clock> + AsMut<Clock> {
|
||||||
/// can be clocked in microseconds with f64 without losing precision.
|
/// can be clocked in microseconds with f64 without losing precision.
|
||||||
pub trait TimeUnit: InteriorMutable<f64> {}
|
pub trait TimeUnit: InteriorMutable<f64> {}
|
||||||
|
|
||||||
/// Contains memoized renders of clock values.
|
|
||||||
///
|
|
||||||
/// Performance optimization.
|
|
||||||
#[derive(Debug)] pub struct ClockView {
|
|
||||||
pub sr: Memo<Option<(bool, f64)>, String>,
|
|
||||||
pub buf: Memo<Option<f64>, String>,
|
|
||||||
pub lat: Memo<Option<f64>, String>,
|
|
||||||
pub bpm: Memo<Option<f64>, String>,
|
|
||||||
pub beat: Memo<Option<f64>, String>,
|
|
||||||
pub time: Memo<Option<f64>, String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const DEFAULT_PPQ: f64 = 96.0;
|
pub const DEFAULT_PPQ: f64 = 96.0;
|
||||||
|
|
||||||
/// FIXME: remove this and use PPQ from timebase everywhere:
|
/// FIXME: remove this and use PPQ from timebase everywhere:
|
||||||
|
|
@ -377,71 +365,6 @@ impl<T: HasClock> Act<T> for ClockCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClockView {
|
|
||||||
pub const BEAT_EMPTY: &'static str = "-.-.--";
|
|
||||||
pub const TIME_EMPTY: &'static str = "-.---s";
|
|
||||||
pub const BPM_EMPTY: &'static str = "---.---";
|
|
||||||
pub fn update_clock (cache: &Arc<RwLock<Self>>, clock: &Clock, compact: bool) {
|
|
||||||
let rate = clock.timebase.sr.get();
|
|
||||||
let chunk = clock.chunk.load(Relaxed) as f64;
|
|
||||||
let lat = chunk / rate * 1000.;
|
|
||||||
let delta = |start: &Moment|clock.global.usec.get() - start.usec.get();
|
|
||||||
let mut cache = cache.write().unwrap();
|
|
||||||
|
|
||||||
cache.buf.update(
|
|
||||||
Some(chunk), rewrite!(buf, "{chunk}")
|
|
||||||
);
|
|
||||||
|
|
||||||
cache.lat.update(
|
|
||||||
Some(lat), rewrite!(buf, "{lat:.1}ms")
|
|
||||||
);
|
|
||||||
|
|
||||||
cache.sr.update(
|
|
||||||
Some((compact, rate)), |buf: &mut String,_,_|{
|
|
||||||
buf.clear();
|
|
||||||
if compact {
|
|
||||||
write!(buf, "{:.1}kHz", rate / 1000.)
|
|
||||||
} else {
|
|
||||||
write!(buf, "{:.0}Hz", rate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Some(now) = clock.started.read().unwrap().as_ref().map(delta) {
|
|
||||||
let pulse = clock.timebase.usecs_to_pulse(now);
|
|
||||||
let time = now/1000000.;
|
|
||||||
let bpm = clock.timebase.bpm.get();
|
|
||||||
cache.beat.update(Some(pulse), |buf, _, _|{
|
|
||||||
buf.clear();
|
|
||||||
clock.timebase.format_beats_1_to(buf, pulse)
|
|
||||||
});
|
|
||||||
cache.time.update(Some(time), rewrite!(buf, "{:.3}s", time));
|
|
||||||
cache.bpm.update(Some(bpm), rewrite!(buf, "{:.3}", bpm));
|
|
||||||
} else {
|
|
||||||
cache.beat.update(None, rewrite!(buf, "{}", ClockView::BEAT_EMPTY));
|
|
||||||
cache.time.update(None, rewrite!(buf, "{}", ClockView::TIME_EMPTY));
|
|
||||||
cache.bpm.update(None, rewrite!(buf, "{}", ClockView::BPM_EMPTY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_default!(ClockView: {
|
|
||||||
let mut beat = String::with_capacity(16);
|
|
||||||
let _ = write!(beat, "{}", Self::BEAT_EMPTY);
|
|
||||||
let mut time = String::with_capacity(16);
|
|
||||||
let _ = write!(time, "{}", Self::TIME_EMPTY);
|
|
||||||
let mut bpm = String::with_capacity(16);
|
|
||||||
let _ = write!(bpm, "{}", Self::BPM_EMPTY);
|
|
||||||
Self {
|
|
||||||
beat: Memo::new(None, beat),
|
|
||||||
time: Memo::new(None, time),
|
|
||||||
bpm: Memo::new(None, bpm),
|
|
||||||
sr: Memo::new(None, String::with_capacity(16)),
|
|
||||||
buf: Memo::new(None, String::with_capacity(16)),
|
|
||||||
lat: Memo::new(None, String::with_capacity(16)),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
#[cfg(feature = "clock")] impl_has!(Clock: |self: Track|self.sequencer.clock);
|
#[cfg(feature = "clock")] impl_has!(Clock: |self: Track|self.sequencer.clock);
|
||||||
impl_default!(Timebase: Self::new(48000f64, 150f64, DEFAULT_PPQ));
|
impl_default!(Timebase: Self::new(48000f64, 150f64, DEFAULT_PPQ));
|
||||||
impl_time_unit!(SampleCount);
|
impl_time_unit!(SampleCount);
|
||||||
|
|
@ -456,3 +379,4 @@ impl_time_unit!(LaunchSync);
|
||||||
mod moment; pub use self::moment::*;
|
mod moment; pub use self::moment::*;
|
||||||
mod ticker; pub use self::ticker::*;
|
mod ticker; pub use self::ticker::*;
|
||||||
mod timebase; pub use self::timebase::*;
|
mod timebase; pub use self::timebase::*;
|
||||||
|
mod clock_view; pub use self::clock_view::*;
|
||||||
|
|
|
||||||
78
src/device/clock/clock_view.rs
Normal file
78
src/device/clock/clock_view.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
/// Contains memoized renders of clock values.
|
||||||
|
///
|
||||||
|
/// Performance optimization.
|
||||||
|
#[derive(Debug)] pub struct ClockView {
|
||||||
|
pub sr: Memo<Option<(bool, f64)>, String>,
|
||||||
|
pub buf: Memo<Option<f64>, String>,
|
||||||
|
pub lat: Memo<Option<f64>, String>,
|
||||||
|
pub bpm: Memo<Option<f64>, String>,
|
||||||
|
pub beat: Memo<Option<f64>, String>,
|
||||||
|
pub time: Memo<Option<f64>, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_default!(ClockView: {
|
||||||
|
let mut beat = String::with_capacity(16);
|
||||||
|
let _ = write!(beat, "{}", Self::BEAT_EMPTY);
|
||||||
|
let mut time = String::with_capacity(16);
|
||||||
|
let _ = write!(time, "{}", Self::TIME_EMPTY);
|
||||||
|
let mut bpm = String::with_capacity(16);
|
||||||
|
let _ = write!(bpm, "{}", Self::BPM_EMPTY);
|
||||||
|
Self {
|
||||||
|
beat: Memo::new(None, beat),
|
||||||
|
time: Memo::new(None, time),
|
||||||
|
bpm: Memo::new(None, bpm),
|
||||||
|
sr: Memo::new(None, String::with_capacity(16)),
|
||||||
|
buf: Memo::new(None, String::with_capacity(16)),
|
||||||
|
lat: Memo::new(None, String::with_capacity(16)),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
impl ClockView {
|
||||||
|
pub const BEAT_EMPTY: &'static str = "-.-.--";
|
||||||
|
pub const TIME_EMPTY: &'static str = "-.---s";
|
||||||
|
pub const BPM_EMPTY: &'static str = "---.---";
|
||||||
|
pub fn update_clock (cache: &Arc<RwLock<Self>>, clock: &Clock, compact: bool) {
|
||||||
|
let rate = clock.timebase.sr.get();
|
||||||
|
let chunk = clock.chunk.load(Relaxed) as f64;
|
||||||
|
let lat = chunk / rate * 1000.;
|
||||||
|
let delta = |start: &Moment|clock.global.usec.get() - start.usec.get();
|
||||||
|
let mut cache = cache.write().unwrap();
|
||||||
|
|
||||||
|
cache.buf.update(
|
||||||
|
Some(chunk), rewrite!(buf, "{chunk}")
|
||||||
|
);
|
||||||
|
|
||||||
|
cache.lat.update(
|
||||||
|
Some(lat), rewrite!(buf, "{lat:.1}ms")
|
||||||
|
);
|
||||||
|
|
||||||
|
cache.sr.update(
|
||||||
|
Some((compact, rate)), |buf: &mut String,_,_|{
|
||||||
|
buf.clear();
|
||||||
|
if compact {
|
||||||
|
write!(buf, "{:.1}kHz", rate / 1000.)
|
||||||
|
} else {
|
||||||
|
write!(buf, "{:.0}Hz", rate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(now) = clock.started.read().unwrap().as_ref().map(delta) {
|
||||||
|
let pulse = clock.timebase.usecs_to_pulse(now);
|
||||||
|
let time = now/1000000.;
|
||||||
|
let bpm = clock.timebase.bpm.get();
|
||||||
|
cache.beat.update(Some(pulse), |buf, _, _|{
|
||||||
|
buf.clear();
|
||||||
|
clock.timebase.format_beats_1_to(buf, pulse)
|
||||||
|
});
|
||||||
|
cache.time.update(Some(time), rewrite!(buf, "{:.3}s", time));
|
||||||
|
cache.bpm.update(Some(bpm), rewrite!(buf, "{:.3}", bpm));
|
||||||
|
} else {
|
||||||
|
cache.beat.update(None, rewrite!(buf, "{}", ClockView::BEAT_EMPTY));
|
||||||
|
cache.time.update(None, rewrite!(buf, "{}", ClockView::TIME_EMPTY));
|
||||||
|
cache.bpm.update(None, rewrite!(buf, "{}", ClockView::BPM_EMPTY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -24,7 +24,10 @@ pub struct MidiEditor {
|
||||||
|
|
||||||
impl_default!(MidiEditor: Self {
|
impl_default!(MidiEditor: Self {
|
||||||
mode: PianoHorizontal::new(None),
|
mode: PianoHorizontal::new(None),
|
||||||
size: Size(0.into(), 0.into()),
|
size: Size(
|
||||||
|
Arc::new(0usize.into()),
|
||||||
|
Arc::new(0usize.into()),
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
impl MidiEditor {
|
impl MidiEditor {
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ impl NoteRange for Sampler {
|
||||||
&self.note_lo
|
&self.note_lo
|
||||||
}
|
}
|
||||||
fn note_axis (&self) -> &AtomicUsize {
|
fn note_axis (&self) -> &AtomicUsize {
|
||||||
&self.size.y
|
&self.size.1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0273d2ac75b8a144ea03b4bdd94d08003f3589df
|
Subproject commit cb382cf12e9169310ddab4eca2ca01e87fde9869
|
||||||
Loading…
Add table
Add a link
Reference in a new issue