mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 20:56:43 +01:00
fix warnings (not 55 errors)
This commit is contained in:
parent
a50e022ab6
commit
87c5e47b43
8 changed files with 290 additions and 269 deletions
237
src/time.rs
237
src/time.rs
|
|
@ -1,89 +1,16 @@
|
|||
/// Number of data frames in a second.
|
||||
#[derive(Debug)]
|
||||
pub struct Hz(pub u32);
|
||||
|
||||
/// One data frame.
|
||||
#[derive(Debug)]
|
||||
pub struct Frame(pub u32);
|
||||
|
||||
/// One microsecond.
|
||||
#[derive(Debug)]
|
||||
pub struct Usec(pub u64);
|
||||
|
||||
/// Beats per minute as `120000` = 120.000BPM
|
||||
#[derive(Debug)]
|
||||
pub struct Tempo(pub u64);
|
||||
|
||||
/// Time signature: N/Mths per bar.
|
||||
#[derive(Debug)]
|
||||
pub struct Signature(pub u32, pub u32);
|
||||
|
||||
/// NoteDuration in musical terms. Has definite usec value
|
||||
/// for given bpm and sample rate.
|
||||
pub enum NoteDuration {
|
||||
Nth(u16, u16),
|
||||
Dotted(Box<Self>),
|
||||
Tuplet(u16, Box<Self>),
|
||||
pub struct Timebase {
|
||||
/// Frames per second
|
||||
pub rate: Option<usize>,
|
||||
/// Beats per minute
|
||||
pub tempo: Option<usize>,
|
||||
/// Ticks per beat
|
||||
pub ppq: usize,
|
||||
}
|
||||
|
||||
impl Frame {
|
||||
#[inline]
|
||||
pub fn to_usec (&self, rate: &Hz) -> Usec {
|
||||
Usec((self.0 as u64 * 1000000) / rate.0 as u64)
|
||||
}
|
||||
}
|
||||
|
||||
impl Usec {
|
||||
#[inline]
|
||||
pub fn to_frame (&self, rate: &Hz) -> Frame {
|
||||
Frame(((self.0 * rate.0 as u64) / 1000) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Tempo {
|
||||
#[inline]
|
||||
pub fn usec_per_bar (&self, beats: u64) -> Usec {
|
||||
Usec(beats * self.usec_per_beat().0)
|
||||
}
|
||||
#[inline]
|
||||
pub fn usec_per_beat (&self) -> Usec {
|
||||
Usec(60_000_000_000 / self.0 as u64)
|
||||
}
|
||||
#[inline]
|
||||
pub fn usec_per_step (&self, divisor: u64) -> Usec {
|
||||
Usec(self.usec_per_beat().0 / divisor as u64)
|
||||
}
|
||||
#[inline]
|
||||
pub fn quantize (&self, step: &NoteDuration, time: Usec) -> Usec {
|
||||
let step = step.to_usec(self);
|
||||
let t = time.0 / step.0;
|
||||
Usec(step.0 * t)
|
||||
}
|
||||
#[inline]
|
||||
pub fn quantize_into <T, U> (&self, step: &NoteDuration, events: U)
|
||||
-> Vec<(Usec, T)>
|
||||
where U: std::iter::Iterator<Item=(Usec, T)> + Sized
|
||||
{
|
||||
events
|
||||
.map(|(time, event)|(self.quantize(step, time), event))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl NoteDuration {
|
||||
fn to_usec (&self, bpm: &Tempo) -> Usec {
|
||||
Usec(match self {
|
||||
Self::Nth(time, flies) =>
|
||||
bpm.usec_per_beat().0 * *time as u64 / *flies as u64,
|
||||
Self::Dotted(duration) =>
|
||||
duration.to_usec(bpm).0 * 3 / 2,
|
||||
Self::Tuplet(n, duration) =>
|
||||
duration.to_usec(bpm).0 * 2 / *n as u64,
|
||||
})
|
||||
}
|
||||
fn to_frame (&self, bpm: &Tempo, rate: &Hz) -> Frame {
|
||||
self.to_usec(bpm).to_frame(rate)
|
||||
}
|
||||
enum QuantizeMode {
|
||||
Forward,
|
||||
Backward,
|
||||
Nearest,
|
||||
}
|
||||
|
||||
struct Loop<T> {
|
||||
|
|
@ -93,3 +20,145 @@ struct Loop<T> {
|
|||
end: T,
|
||||
post_end: T,
|
||||
}
|
||||
|
||||
/// NoteDuration in musical terms. Has definite usec value
|
||||
/// for given bpm and sample rate.
|
||||
pub enum NoteDuration {
|
||||
Nth(u16, u16),
|
||||
Dotted(Box<Self>),
|
||||
Tuplet(u16, Box<Self>),
|
||||
}
|
||||
|
||||
impl Timebase {
|
||||
/// Beats per second
|
||||
#[inline] fn bps (&self) -> f64 {
|
||||
self.tempo.0 as f64 / 60000.0
|
||||
}
|
||||
/// Frames per second
|
||||
#[inline] fn fps (&self) -> u64 {
|
||||
self.rate.0 as u64
|
||||
}
|
||||
/// Frames per beat
|
||||
#[inline] fn fpb (&self) -> f64 {
|
||||
self.fps() as f64 / self.bps()
|
||||
}
|
||||
/// Frames per tick FIXME double times
|
||||
#[inline] fn fpt (&self) -> f64 {
|
||||
self.fps() as f64 / self.tps()
|
||||
}
|
||||
/// Frames per loop
|
||||
#[inline] fn fpl (&self) -> f64 {
|
||||
self.fpb() * self.steps as f64 / self.steps_per_beat as f64
|
||||
}
|
||||
/// Ticks per beat
|
||||
#[inline] fn tpb (&self) -> f64 {
|
||||
self.ticks_per_beat as f64
|
||||
}
|
||||
/// Ticks per second
|
||||
#[inline] fn tps (&self) -> f64 {
|
||||
self.bps() * self.tpb()
|
||||
}
|
||||
fn frames_to_ticks (&self, start: u64, end: u64) -> Vec<(u64, u64)> {
|
||||
let fpl = self.fpl() as u64;
|
||||
let start_frame = start % fpl;
|
||||
let end_frame = end % fpl;
|
||||
let fpt = self.fpt();
|
||||
let mut ticks = vec![];
|
||||
let mut add_frame = |frame: f64|{
|
||||
let jitter = frame.rem_euclid(fpt);
|
||||
let last_jitter = (frame - 1.0).max(0.0) % fpt;
|
||||
let next_jitter = frame + 1.0 % fpt;
|
||||
if jitter <= last_jitter && jitter <= next_jitter {
|
||||
ticks.push((frame as u64 % (end-start), (frame / fpt) as u64));
|
||||
};
|
||||
};
|
||||
if start_frame < end_frame {
|
||||
for frame in start_frame..end_frame {
|
||||
add_frame(frame as f64);
|
||||
}
|
||||
} else {
|
||||
let mut frame = start_frame;
|
||||
loop {
|
||||
add_frame(frame as f64);
|
||||
frame = frame + 1;
|
||||
if frame >= fpl {
|
||||
frame = 0;
|
||||
loop {
|
||||
add_frame(frame as f64);
|
||||
frame = frame + 1;
|
||||
if frame >= end_frame.saturating_sub(1) {
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
ticks
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn frame_to_usec (&self, frame: usize) -> usize {
|
||||
frame * 1000000 / self.rate
|
||||
}
|
||||
#[inline]
|
||||
pub fn usec_to_frame (&self, usec: usize) -> usize {
|
||||
frame * self.rate / 1000
|
||||
}
|
||||
#[inline]
|
||||
pub fn usec_per_bar (&self, beats_per_bar: usize) -> usize {
|
||||
self.usec_per_beat() * beats_per_bar
|
||||
}
|
||||
#[inline]
|
||||
pub fn usec_per_beat (&self) -> usize {
|
||||
60_000_000_000 / self.tempo
|
||||
}
|
||||
#[inline]
|
||||
pub fn usec_per_step (&self, divisor: usize) -> usize {
|
||||
self.usec_per_beat() / divisor
|
||||
}
|
||||
#[inline]
|
||||
pub fn usec_per_tick (&self) -> usize {
|
||||
self.usec_per_beat() / self.ppq
|
||||
}
|
||||
#[inline]
|
||||
pub fn usec_per_note (&self, note: &NoteDuration) -> usize {
|
||||
match note {
|
||||
NoteDuration::Nth(time, flies) =>
|
||||
self.usec_per_beat() * *time / *flies,
|
||||
NoteDuration::Dotted(note) =>
|
||||
self.usec_per_note(note) * 3 / 2,
|
||||
NoteDuration::Tuplet(n, note) =>
|
||||
self.usec_per_note(note) * 2 / *n,
|
||||
}
|
||||
}
|
||||
pub fn quantize (&self, step: &NoteDuration, time: usize) -> (usize, usize) {
|
||||
let step = self.usec_per_note(step);
|
||||
let time = time / step;
|
||||
let offset = time % step;
|
||||
(time, offset)
|
||||
}
|
||||
pub fn quantize_into <T, U> (&self, step: &NoteDuration, events: U) -> Vec<(usize, T)>
|
||||
where U: std::iter::Iterator<Item=(usize, T)> + Sized
|
||||
{
|
||||
events
|
||||
.map(|(time, event)|(self.quantize(step, time).0, event))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl NoteDuration {
|
||||
fn to_usec (&self, bpm: &Tempo) -> Usec {
|
||||
Usec(match self {
|
||||
Self::Nth(time, flies) =>
|
||||
bpm.usec_per_beat().0 * *time as usize / *flies as usize,
|
||||
Self::Dotted(duration) =>
|
||||
duration.to_usec(bpm).0 * 3 / 2,
|
||||
Self::Tuplet(n, duration) =>
|
||||
duration.to_usec(bpm).0 * 2 / *n as usize,
|
||||
})
|
||||
}
|
||||
fn to_frame (&self, bpm: &Tempo, rate: &Hz) -> Frame {
|
||||
self.to_usec(bpm).to_frame(rate)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue