mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-02-21 16:29:04 +01:00
refactor(engine): flatten
- add `just stats` - add basic doctests
This commit is contained in:
parent
7afab8eade
commit
37068784cb
34 changed files with 1285 additions and 1173 deletions
149
engine/engine.rs
149
engine/engine.rs
|
|
@ -1,74 +1,115 @@
|
|||
mod engine_deps; pub use self::engine_deps::*;
|
||||
mod time; pub use self::time::*;
|
||||
mod note; pub use self::note::*;
|
||||
mod jack; pub use self::jack::*;
|
||||
mod midi; pub use self::midi::*;
|
||||
pub extern crate jack;
|
||||
pub extern crate midly;
|
||||
pub extern crate tengri;
|
||||
mod engine_structs; pub use self::engine_structs::*;
|
||||
mod engine_traits; pub use self::engine_traits::*;
|
||||
mod engine_impls;
|
||||
mod jack_structs; pub use self::jack_structs::*;
|
||||
mod jack_traits; pub use self::jack_traits::*;
|
||||
mod jack_types; pub use self::jack_types::*;
|
||||
mod jack_impls;
|
||||
pub(crate) use ::{
|
||||
tengri::{Usually, from, output::PerfModel},
|
||||
atomic_float::AtomicF64,
|
||||
std::{
|
||||
fmt::Debug, ops::{Add, Sub, Mul, Div, Rem},
|
||||
sync::{Arc, RwLock, atomic::{AtomicBool, AtomicUsize, Ordering::Relaxed}},
|
||||
},
|
||||
};
|
||||
pub use ::{
|
||||
jack::{*, contrib::{*, ClosureProcessHandler}},
|
||||
midly::{Smf, TrackEventKind, MidiMessage, Error as MidiError, num::*, live::*,}
|
||||
};
|
||||
|
||||
//pub trait MaybeHas<T>: Send + Sync {
|
||||
//fn get (&self) -> Option<&T>;
|
||||
//}
|
||||
pub const DEFAULT_PPQ: f64 = 96.0;
|
||||
|
||||
//impl<T, U: Has<Option<T>>> MaybeHas<T> for U {
|
||||
//fn get (&self) -> Option<&T> {
|
||||
//Has::<Option<T>>::get(self).as_ref()
|
||||
//}
|
||||
//}
|
||||
/// FIXME: remove this and use PPQ from timebase everywhere:
|
||||
pub const PPQ: usize = 96;
|
||||
|
||||
pub trait HasN<T>: Send + Sync {
|
||||
fn get_nth (&self, key: usize) -> &T;
|
||||
fn get_nth_mut (&mut self, key: usize) -> &mut T;
|
||||
/// (pulses, name), assuming 96 PPQ
|
||||
pub const NOTE_DURATIONS: [(usize, &str);26] = [
|
||||
(1, "1/384"), (2, "1/192"),
|
||||
(3, "1/128"), (4, "1/96"),
|
||||
(6, "1/64"), (8, "1/48"),
|
||||
(12, "1/32"), (16, "1/24"),
|
||||
(24, "1/16"), (32, "1/12"),
|
||||
(48, "1/8"), (64, "1/6"),
|
||||
(96, "1/4"), (128, "1/3"),
|
||||
(192, "1/2"), (256, "2/3"),
|
||||
(384, "1/1"), (512, "4/3"),
|
||||
(576, "3/2"), (768, "2/1"),
|
||||
(1152, "3/1"), (1536, "4/1"),
|
||||
(2304, "6/1"), (3072, "8/1"),
|
||||
(3456, "9/1"), (6144, "16/1"),
|
||||
];
|
||||
|
||||
pub const NOTE_NAMES: [&str; 128] = [
|
||||
"C0", "C#0", "D0", "D#0", "E0", "F0", "F#0", "G0", "G#0", "A0", "A#0", "B0",
|
||||
"C1", "C#1", "D1", "D#1", "E1", "F1", "F#1", "G1", "G#1", "A1", "A#1", "B1",
|
||||
"C2", "C#2", "D2", "D#2", "E2", "F2", "F#2", "G2", "G#2", "A2", "A#2", "B2",
|
||||
"C3", "C#3", "D3", "D#3", "E3", "F3", "F#3", "G3", "G#3", "A3", "A#3", "B3",
|
||||
"C4", "C#4", "D4", "D#4", "E4", "F4", "F#4", "G4", "G#4", "A4", "A#4", "B4",
|
||||
"C5", "C#5", "D5", "D#5", "E5", "F5", "F#5", "G5", "G#5", "A5", "A#5", "B5",
|
||||
"C6", "C#6", "D6", "D#6", "E6", "F6", "F#6", "G6", "G#6", "A6", "A#6", "B6",
|
||||
"C7", "C#7", "D7", "D#7", "E7", "F7", "F#7", "G7", "G#7", "A7", "A#7", "B7",
|
||||
"C8", "C#8", "D8", "D#8", "E8", "F8", "F#8", "G8", "G#8", "A8", "A#8", "B8",
|
||||
"C9", "C#9", "D9", "D#9", "E9", "F9", "F#9", "G9", "G#9", "A9", "A#9", "B9",
|
||||
"C10", "C#10", "D10", "D#10", "E10", "F10", "F#10", "G10",
|
||||
];
|
||||
|
||||
/// Return boxed iterator of MIDI events
|
||||
pub fn parse_midi_input <'a> (input: ::jack::MidiIter<'a>)
|
||||
-> Box<dyn Iterator<Item=(usize, LiveEvent<'a>, &'a [u8])> + 'a>
|
||||
{
|
||||
Box::new(input.map(|::jack::RawMidi { time, bytes }|(
|
||||
time as usize,
|
||||
LiveEvent::parse(bytes).unwrap(),
|
||||
bytes
|
||||
)))
|
||||
}
|
||||
|
||||
pub trait Gettable<T> {
|
||||
/// Returns current value
|
||||
fn get (&self) -> T;
|
||||
/// Add "all notes off" to the start of a buffer.
|
||||
pub fn all_notes_off (output: &mut [Vec<Vec<u8>>]) {
|
||||
let mut buf = vec![];
|
||||
let msg = MidiMessage::Controller { controller: 123.into(), value: 0.into() };
|
||||
let evt = LiveEvent::Midi { channel: 0.into(), message: msg };
|
||||
evt.write(&mut buf).unwrap();
|
||||
output[0].push(buf);
|
||||
}
|
||||
|
||||
pub trait Mutable<T>: Gettable<T> {
|
||||
/// Sets new value, returns old
|
||||
fn set (&mut self, value: T) -> T;
|
||||
/// Update notes_in array
|
||||
pub fn update_keys (keys: &mut[bool;128], message: &MidiMessage) {
|
||||
match message {
|
||||
MidiMessage::NoteOn { key, .. } => { keys[key.as_int() as usize] = true; }
|
||||
MidiMessage::NoteOff { key, .. } => { keys[key.as_int() as usize] = false; },
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait InteriorMutable<T>: Gettable<T> {
|
||||
/// Sets new value, returns old
|
||||
fn set (&self, value: T) -> T;
|
||||
/// Returns the next shorter length
|
||||
pub fn note_duration_prev (pulses: usize) -> usize {
|
||||
for (length, _) in NOTE_DURATIONS.iter().rev() { if *length < pulses { return *length } }
|
||||
pulses
|
||||
}
|
||||
|
||||
impl Gettable<bool> for AtomicBool {
|
||||
fn get (&self) -> bool { self.load(Relaxed) }
|
||||
/// Returns the next longer length
|
||||
pub fn note_duration_next (pulses: usize) -> usize {
|
||||
for (length, _) in NOTE_DURATIONS.iter() { if *length > pulses { return *length } }
|
||||
pulses
|
||||
}
|
||||
|
||||
impl InteriorMutable<bool> for AtomicBool {
|
||||
fn set (&self, value: bool) -> bool { self.swap(value, Relaxed) }
|
||||
pub fn note_duration_to_name (pulses: usize) -> &'static str {
|
||||
for (length, name) in NOTE_DURATIONS.iter() { if *length == pulses { return name } }
|
||||
""
|
||||
}
|
||||
|
||||
impl Gettable<usize> for AtomicUsize {
|
||||
fn get (&self) -> usize { self.load(Relaxed) }
|
||||
pub fn note_pitch_to_name (n: usize) -> &'static str {
|
||||
if n > 127 {
|
||||
panic!("to_note_name({n}): must be 0-127");
|
||||
}
|
||||
NOTE_NAMES[n]
|
||||
}
|
||||
|
||||
impl InteriorMutable<usize> for AtomicUsize {
|
||||
fn set (&self, value: usize) -> usize { self.swap(value, Relaxed) }
|
||||
}
|
||||
|
||||
#[cfg(test)] #[test] fn test_time () -> Usually<()> {
|
||||
// TODO!
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)] #[test] fn test_midi_range () {
|
||||
let model = MidiRangeModel::from((1, false));
|
||||
|
||||
let _ = model.get_time_len();
|
||||
let _ = model.get_time_zoom();
|
||||
let _ = model.get_time_lock();
|
||||
let _ = model.get_time_start();
|
||||
let _ = model.get_time_axis();
|
||||
let _ = model.get_time_end();
|
||||
|
||||
let _ = model.get_note_lo();
|
||||
let _ = model.get_note_axis();
|
||||
let _ = model.get_note_hi();
|
||||
}
|
||||
|
||||
//macro_rules! impl_port {
|
||||
//($Name:ident : $Spec:ident -> $Pair:ident |$jack:ident, $name:ident|$port:expr) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue