add const PPQ = 96

This commit is contained in:
🪞👃🪞 2024-10-06 02:47:55 +03:00
parent 0da54db5e0
commit 11a66ee415
5 changed files with 28 additions and 20 deletions

View file

@ -10,9 +10,6 @@ pub struct ArrangerCli {
/// Name of JACK client
#[arg(short, long)]
name: Option<String>,
/// Pulses per quarter note (arruencer resolution; default: 96)
#[arg(short, long)]
ppq: Option<usize>,
/// Whether to include a transport toolbar (default: true)
#[arg(short, long, default_value_t = true)]
transport: bool,
@ -40,7 +37,7 @@ impl ArrangerCli {
let track = arranger.track_add(None)?;
for _ in 0..self.scenes {
track.phrases.push(
Arc::new(RwLock::new(Phrase::new("", 96 * 4, None)))
Arc::new(RwLock::new(Phrase::new("", true, PPQ * 4, None)))
);
}
}

View file

@ -133,15 +133,14 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
let Self(state, factor) = self;
let ppq = 96;
let (cols, rows) = if *factor == 0 {(
track_clip_name_lengths(state.tracks.as_slice()),
scene_ppqs(state.tracks.as_slice(), state.scenes.as_slice()),
)} else {(
track_clip_name_lengths(state.tracks.as_slice()),
(0..=state.scenes.len()).map(|i|(factor*ppq, factor*ppq*i)).collect::<Vec<_>>(),
(0..=state.scenes.len()).map(|i|(factor*PPQ, factor*PPQ*i)).collect::<Vec<_>>(),
)};
//let height = rows.last().map(|(w,y)|(y+w)/ppq).unwrap_or(16);
//let height = rows.last().map(|(w,y)|(y+w)/PPQ).unwrap_or(16);
let tracks: &[Sequencer<Tui>] = state.tracks.as_ref();
let scenes: &[Scene] = state.scenes.as_ref();
let offset = 4 + scene_name_max_len(scenes) as u16;
@ -181,7 +180,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
}).fixed_xy(w, h);
let tracks_clips = col!((scene, (pulses, _)) in scenes.iter().zip(rows) => {
let height = 1.max((pulses / 96) as u16);
let height = 1.max((pulses / PPQ) as u16);
let playing = scene.is_playing(tracks);
Stack::right(move |add| {
add(&scene_name(scene, playing, height))?;
@ -222,7 +221,7 @@ pub fn track_clip_name_lengths <E: Engine> (tracks: &[Sequencer<E>]) -> Vec<(usi
pub fn scene_ppqs <E: Engine> (tracks: &[Sequencer<E>], scenes: &[Scene]) -> Vec<(usize, usize)> {
let mut total = 0;
let mut scenes: Vec<(usize, usize)> = scenes.iter().map(|scene|{
let pulses = scene.pulses(tracks).max(96);
let pulses = scene.pulses(tracks).max(PPQ);
total = total + pulses;
(pulses, total - pulses)
}).collect();
@ -249,7 +248,7 @@ impl<'a> Widget for VerticalArrangerGrid<'a> {
}
}
for (_, y) in rows.iter() {
let y = area.y() + (*y / 96) as u16 + 1;
let y = area.y() + (*y / PPQ) as u16 + 1;
if y >= to.buffer.area.height {
break
}
@ -278,15 +277,15 @@ impl<'a> Widget for VerticalArrangerCursor<'a> {
];
let get_scene_area = |s: usize| [
area.x(),
2 + area.y() + (rows[s].1 / 96) as u16,
2 + area.y() + (rows[s].1 / PPQ) as u16,
area.w(),
(rows[s].0 / 96) as u16
(rows[s].0 / PPQ) as u16
];
let get_clip_area = |t: usize, s: usize| [
offset + area.x() + cols[t].1 as u16 - 1,
2 + area.y() + (rows[s].1 / 96) as u16,
2 + area.y() + (rows[s].1 / PPQ) as u16,
cols[t].0 as u16,
(rows[s].0 / 96) as u16
(rows[s].0 / PPQ) as u16
];
let mut track_area: Option<[u16;4]> = None;
let mut scene_area: Option<[u16;4]> = None;

View file

@ -12,6 +12,8 @@ submod! {
transport transport_tui
}
pub const PPQ: usize = 96;
pub const CORNERS: CornersTall = CornersTall(NOT_DIM_GREEN);
tui_style!(GRAY_DIM =

View file

@ -10,10 +10,20 @@ pub type MIDIMessage = Vec<u8>;
pub type MIDIChunk = [Vec<MIDIMessage>];
/// Contains all phrases in the project
pub struct PhrasePool {
pub struct PhrasePool<E: Engine> {
_engine: PhantomData<E>,
pub phrases: Vec<Arc<RwLock<Option<Phrase>>>>,
}
impl<E: Engine> PhrasePool<E> {
pub fn new () -> Self {
Self {
_engine: Default::default(),
phrases: vec![Arc::new(RwLock::new(Some(Phrase::default())))]
}
}
}
/// Contains state for viewing and editing a phrase
pub struct PhraseEditor<E: Engine> {
_engine: PhantomData<E>,
@ -52,16 +62,16 @@ pub struct Phrase {
}
impl Default for Phrase {
fn default () -> Self { Self::new("", 0, None) }
fn default () -> Self { Self::new("", false, 0, None) }
}
impl Phrase {
pub fn new (name: &str, length: usize, notes: Option<PhraseData>) -> Self {
pub fn new (name: &str, loop_on: bool, length: usize, notes: Option<PhraseData>) -> Self {
Self {
name: Arc::new(RwLock::new(name.into())),
length,
notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]),
loop_on: true,
loop_on,
loop_start: 0,
loop_length: length,
percussive: true,
@ -246,7 +256,7 @@ impl<E: Engine> Sequencer<E> {
keys_in: [false;128],
keys_out: [false;128],
now: 0,
ppq: 96,
ppq: PPQ,
transport: None,
note_axis: FixedAxis { start: 12, point: Some(36) },
time_axis: ScaledAxis { start: 0, scale: 24, point: Some(0) },

View file

@ -130,7 +130,7 @@ impl Content for Sequencer<Tui> {
.flatten()
{
let phrase = phrase.read().unwrap();
let length = format!("{}q{}p", phrase.length / 96, phrase.length % 96);
let length = format!("{}q{}p", phrase.length / PPQ, phrase.length % PPQ);
let length = format!("{:>9}", &length);
let loop_on = format!("{:>9}", if phrase.loop_on { "on" } else { "off" });
let loop_start = format!("{:>9}", phrase.loop_start);