mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
add const PPQ = 96
This commit is contained in:
parent
0da54db5e0
commit
11a66ee415
5 changed files with 28 additions and 20 deletions
|
|
@ -10,9 +10,6 @@ pub struct ArrangerCli {
|
||||||
/// Name of JACK client
|
/// Name of JACK client
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
name: Option<String>,
|
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)
|
/// Whether to include a transport toolbar (default: true)
|
||||||
#[arg(short, long, default_value_t = true)]
|
#[arg(short, long, default_value_t = true)]
|
||||||
transport: bool,
|
transport: bool,
|
||||||
|
|
@ -40,7 +37,7 @@ impl ArrangerCli {
|
||||||
let track = arranger.track_add(None)?;
|
let track = arranger.track_add(None)?;
|
||||||
for _ in 0..self.scenes {
|
for _ in 0..self.scenes {
|
||||||
track.phrases.push(
|
track.phrases.push(
|
||||||
Arc::new(RwLock::new(Phrase::new("", 96 * 4, None)))
|
Arc::new(RwLock::new(Phrase::new("", true, PPQ * 4, None)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -133,15 +133,14 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
let Self(state, factor) = self;
|
let Self(state, factor) = self;
|
||||||
let ppq = 96;
|
|
||||||
let (cols, rows) = if *factor == 0 {(
|
let (cols, rows) = if *factor == 0 {(
|
||||||
track_clip_name_lengths(state.tracks.as_slice()),
|
track_clip_name_lengths(state.tracks.as_slice()),
|
||||||
scene_ppqs(state.tracks.as_slice(), state.scenes.as_slice()),
|
scene_ppqs(state.tracks.as_slice(), state.scenes.as_slice()),
|
||||||
)} else {(
|
)} else {(
|
||||||
track_clip_name_lengths(state.tracks.as_slice()),
|
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 tracks: &[Sequencer<Tui>] = state.tracks.as_ref();
|
||||||
let scenes: &[Scene] = state.scenes.as_ref();
|
let scenes: &[Scene] = state.scenes.as_ref();
|
||||||
let offset = 4 + scene_name_max_len(scenes) as u16;
|
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);
|
}).fixed_xy(w, h);
|
||||||
|
|
||||||
let tracks_clips = col!((scene, (pulses, _)) in scenes.iter().zip(rows) => {
|
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);
|
let playing = scene.is_playing(tracks);
|
||||||
Stack::right(move |add| {
|
Stack::right(move |add| {
|
||||||
add(&scene_name(scene, playing, height))?;
|
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)> {
|
pub fn scene_ppqs <E: Engine> (tracks: &[Sequencer<E>], scenes: &[Scene]) -> Vec<(usize, usize)> {
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
let mut scenes: Vec<(usize, usize)> = scenes.iter().map(|scene|{
|
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;
|
total = total + pulses;
|
||||||
(pulses, total - pulses)
|
(pulses, total - pulses)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
@ -249,7 +248,7 @@ impl<'a> Widget for VerticalArrangerGrid<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (_, y) in rows.iter() {
|
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 {
|
if y >= to.buffer.area.height {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -278,15 +277,15 @@ impl<'a> Widget for VerticalArrangerCursor<'a> {
|
||||||
];
|
];
|
||||||
let get_scene_area = |s: usize| [
|
let get_scene_area = |s: usize| [
|
||||||
area.x(),
|
area.x(),
|
||||||
2 + area.y() + (rows[s].1 / 96) as u16,
|
2 + area.y() + (rows[s].1 / PPQ) as u16,
|
||||||
area.w(),
|
area.w(),
|
||||||
(rows[s].0 / 96) as u16
|
(rows[s].0 / PPQ) as u16
|
||||||
];
|
];
|
||||||
let get_clip_area = |t: usize, s: usize| [
|
let get_clip_area = |t: usize, s: usize| [
|
||||||
offset + area.x() + cols[t].1 as u16 - 1,
|
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,
|
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 track_area: Option<[u16;4]> = None;
|
||||||
let mut scene_area: Option<[u16;4]> = None;
|
let mut scene_area: Option<[u16;4]> = None;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ submod! {
|
||||||
transport transport_tui
|
transport transport_tui
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const PPQ: usize = 96;
|
||||||
|
|
||||||
pub const CORNERS: CornersTall = CornersTall(NOT_DIM_GREEN);
|
pub const CORNERS: CornersTall = CornersTall(NOT_DIM_GREEN);
|
||||||
|
|
||||||
tui_style!(GRAY_DIM =
|
tui_style!(GRAY_DIM =
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,20 @@ pub type MIDIMessage = Vec<u8>;
|
||||||
pub type MIDIChunk = [Vec<MIDIMessage>];
|
pub type MIDIChunk = [Vec<MIDIMessage>];
|
||||||
|
|
||||||
/// Contains all phrases in the project
|
/// Contains all phrases in the project
|
||||||
pub struct PhrasePool {
|
pub struct PhrasePool<E: Engine> {
|
||||||
|
_engine: PhantomData<E>,
|
||||||
pub phrases: Vec<Arc<RwLock<Option<Phrase>>>>,
|
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
|
/// Contains state for viewing and editing a phrase
|
||||||
pub struct PhraseEditor<E: Engine> {
|
pub struct PhraseEditor<E: Engine> {
|
||||||
_engine: PhantomData<E>,
|
_engine: PhantomData<E>,
|
||||||
|
|
@ -52,16 +62,16 @@ pub struct Phrase {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Phrase {
|
impl Default for Phrase {
|
||||||
fn default () -> Self { Self::new("", 0, None) }
|
fn default () -> Self { Self::new("", false, 0, None) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Phrase {
|
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 {
|
Self {
|
||||||
name: Arc::new(RwLock::new(name.into())),
|
name: Arc::new(RwLock::new(name.into())),
|
||||||
length,
|
length,
|
||||||
notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]),
|
notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]),
|
||||||
loop_on: true,
|
loop_on,
|
||||||
loop_start: 0,
|
loop_start: 0,
|
||||||
loop_length: length,
|
loop_length: length,
|
||||||
percussive: true,
|
percussive: true,
|
||||||
|
|
@ -246,7 +256,7 @@ impl<E: Engine> Sequencer<E> {
|
||||||
keys_in: [false;128],
|
keys_in: [false;128],
|
||||||
keys_out: [false;128],
|
keys_out: [false;128],
|
||||||
now: 0,
|
now: 0,
|
||||||
ppq: 96,
|
ppq: PPQ,
|
||||||
transport: None,
|
transport: None,
|
||||||
note_axis: FixedAxis { start: 12, point: Some(36) },
|
note_axis: FixedAxis { start: 12, point: Some(36) },
|
||||||
time_axis: ScaledAxis { start: 0, scale: 24, point: Some(0) },
|
time_axis: ScaledAxis { start: 0, scale: 24, point: Some(0) },
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ impl Content for Sequencer<Tui> {
|
||||||
.flatten()
|
.flatten()
|
||||||
{
|
{
|
||||||
let phrase = phrase.read().unwrap();
|
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 length = format!("{:>9}", &length);
|
||||||
let loop_on = format!("{:>9}", if phrase.loop_on { "on" } else { "off" });
|
let loop_on = format!("{:>9}", if phrase.loop_on { "on" } else { "off" });
|
||||||
let loop_start = format!("{:>9}", phrase.loop_start);
|
let loop_start = format!("{:>9}", phrase.loop_start);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue