mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-04-03 21:00:44 +02:00
168 lines
4.4 KiB
Rust
168 lines
4.4 KiB
Rust
pub trait HasClock: AsRef<Clock> + AsMut<Clock> {
|
|
fn clock (&self) -> &Clock { self.as_ref() }
|
|
fn clock_mut (&mut self) -> &mut Clock { self.as_mut() }
|
|
}
|
|
|
|
|
|
/// Temporal resolutions: sample rate, tempo, MIDI pulses per quaver (beat)
|
|
///
|
|
/// ```
|
|
/// let _ = tek::Timebase::default();
|
|
/// ```
|
|
#[derive(Debug, Clone)] pub struct Timebase {
|
|
/// Audio samples per second
|
|
pub sr: SampleRate,
|
|
/// MIDI beats per minute
|
|
pub bpm: Bpm,
|
|
/// MIDI ticks per beat
|
|
pub ppq: Ppq,
|
|
}
|
|
|
|
/// Iterator that emits subsequent ticks within a range.
|
|
///
|
|
/// ```
|
|
/// let iter = tek::Ticker::default();
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct Ticker {
|
|
pub spp: f64,
|
|
pub sample: usize,
|
|
pub start: usize,
|
|
pub end: usize,
|
|
}
|
|
|
|
/// A point in time in all time scales (microsecond, sample, MIDI pulse)
|
|
///
|
|
/// ```
|
|
/// let _ = tek::Moment::default();
|
|
/// ```
|
|
#[derive(Debug, Default, Clone)] pub struct Moment {
|
|
pub timebase: Arc<Timebase>,
|
|
/// Current time in microseconds
|
|
pub usec: Microsecond,
|
|
/// Current time in audio samples
|
|
pub sample: SampleCount,
|
|
/// Current time in MIDI pulses
|
|
pub pulse: Pulse,
|
|
}
|
|
|
|
///
|
|
/// ```
|
|
/// let _ = tek::Moment2::default();
|
|
/// ```
|
|
#[derive(Debug, Clone, Default)] pub enum Moment2 {
|
|
#[default] None,
|
|
Zero,
|
|
Usec(Microsecond),
|
|
Sample(SampleCount),
|
|
Pulse(Pulse),
|
|
}
|
|
|
|
/// MIDI resolution in PPQ (pulses per quarter note)
|
|
///
|
|
/// ```
|
|
///
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct Ppq (pub(crate) AtomicF64);
|
|
|
|
/// Timestamp in MIDI pulses
|
|
///
|
|
/// ```
|
|
///
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct Pulse (pub(crate) AtomicF64);
|
|
|
|
/// Tempo in beats per minute
|
|
///
|
|
/// ```
|
|
///
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct Bpm (pub(crate) AtomicF64);
|
|
|
|
/// Quantization setting for launching clips
|
|
///
|
|
/// ```
|
|
///
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct LaunchSync (pub(crate) AtomicF64);
|
|
|
|
/// Quantization setting for notes
|
|
///
|
|
/// ```
|
|
///
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct Quantize (pub(crate) AtomicF64);
|
|
|
|
/// Timestamp in audio samples
|
|
///
|
|
/// ```
|
|
///
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct SampleCount (pub(crate) AtomicF64);
|
|
|
|
/// Audio sample rate in Hz (samples per second)
|
|
///
|
|
/// ```
|
|
///
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct SampleRate (pub(crate) AtomicF64);
|
|
|
|
/// Timestamp in microseconds
|
|
///
|
|
/// ```
|
|
///
|
|
/// ```
|
|
#[derive(Debug, Default)] pub struct Microsecond (pub(crate) AtomicF64);
|
|
|
|
/// The source of time.
|
|
///
|
|
/// ```
|
|
/// let clock = tek::Clock::default();
|
|
/// ```
|
|
#[derive(Clone, Default)] pub struct Clock {
|
|
/// JACK transport handle.
|
|
pub transport: Arc<Option<Transport>>,
|
|
/// Global temporal resolution (shared by [Moment] fields)
|
|
pub timebase: Arc<Timebase>,
|
|
/// Current global sample and usec (monotonic from JACK clock)
|
|
pub global: Arc<Moment>,
|
|
/// Global sample and usec at which playback started
|
|
pub started: Arc<RwLock<Option<Moment>>>,
|
|
/// Playback offset (when playing not from start)
|
|
pub offset: Arc<Moment>,
|
|
/// Current playhead position
|
|
pub playhead: Arc<Moment>,
|
|
/// Note quantization factor
|
|
pub quant: Arc<Quantize>,
|
|
/// Launch quantization factor
|
|
pub sync: Arc<LaunchSync>,
|
|
/// Size of buffer in samples
|
|
pub chunk: Arc<AtomicUsize>,
|
|
// Cache of formatted strings
|
|
pub view_cache: Arc<RwLock<ClockView>>,
|
|
/// For syncing the clock to an external source
|
|
#[cfg(feature = "port")] pub midi_in: Arc<RwLock<Option<MidiInput>>>,
|
|
/// For syncing other devices to this clock
|
|
#[cfg(feature = "port")] pub midi_out: Arc<RwLock<Option<MidiOutput>>>,
|
|
/// For emitting a metronome
|
|
#[cfg(feature = "port")] pub click_out: Arc<RwLock<Option<AudioOutput>>>,
|
|
}
|
|
|
|
/// A unit of time, represented as an atomic 64-bit float.
|
|
///
|
|
/// According to https://stackoverflow.com/a/873367, as per IEEE754,
|
|
/// every integer between 1 and 2^53 can be represented exactly.
|
|
/// This should mean that, even at 192kHz sampling rate, over 1 year of audio
|
|
/// can be clocked in microseconds with f64 without losing precision.
|
|
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>,
|
|
}
|