wip: long awaited fixes to main sequencer

This commit is contained in:
🪞👃🪞 2024-07-01 04:20:41 +03:00
parent 2837ffff4a
commit 78e5469b32
17 changed files with 391 additions and 563 deletions

View file

@ -19,9 +19,6 @@ pub struct Sequencer {
pub midi_out: Port<MidiOut>,
/// Holds info about tempo
pub timebase: Arc<Timebase>,
/// Steps in sequence, e.g. 64 16ths = 4 beat loop.
/// FIXME: play start / end / loop in ppm
pub steps: usize,
/// Phrase selector
pub sequence: Option<usize>,
/// Map: tick -> MIDI events at tick
@ -42,9 +39,8 @@ pub struct Sequencer {
pub note_axis: (u16, u16),
/// Position of cursor within note range
pub note_cursor: u16,
/// Sequencer resolution, e.g. 16 steps per beat.
/// FIXME: grid in ppm will simplify calculations
pub resolution: usize,
/// PPM per display unit
pub time_zoom: usize,
/// Range of time steps to display
pub time_axis: (u16, u16),
/// Position of cursor within time range
@ -68,8 +64,6 @@ impl Sequencer {
midi_out: client.register_port("out", MidiOut::default())?,
timebase: timebase.clone(),
steps: 16,
resolution: 4,
sequence: Some(0),
phrases: phrases.unwrap_or(vec![
Phrase::new("Phrase0", 4*timebase.ppq() as u32, None)
@ -85,13 +79,14 @@ impl Sequencer {
mode: SequencerView::Horizontal,
note_axis: (36, 68),
note_cursor: 0,
time_zoom: 24,
time_axis: (0, 64),
time_cursor: 0,
}).activate(client)
}
pub fn phrase <'a> (&'a self) -> Option<&'a Phrase> {
self.sequence.map(|s|self.phrases.get(s))?
self.phrases.get(self.sequence?)
}
}
@ -111,7 +106,7 @@ fn render (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let pos = s.transport.query().unwrap().pos;
let frame = pos.frame();
let usecs = s.timebase.frame_to_usec(frame as usize);
let ustep = s.timebase.usec_per_step(s.resolution as usize);
let ustep = s.timebase.usec_per_step(s.time_zoom as usize);
let steps = usecs / ustep;
let header = draw_header(s, buf, area, steps)?;
let piano = match s.mode {
@ -141,12 +136,12 @@ fn render (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
}
pub fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) -> Usually<Rect> {
let Rect { x, y, width, .. } = area;
let rep = beat / s.steps;
let step = beat % s.steps;
let reps = s.steps / s.resolution;
let steps = s.steps % s.resolution;
draw_timer(buf, x + width - 2, y + 1, &format!("{rep}.{step:02} / {reps}.{steps}"));
let Rect { x, y, .. } = area;
//let rep = beat / s.steps;
//let step = beat % s.steps;
//let reps = s.steps / s.time_zoom;
//let steps = s.steps % s.time_zoom;
//draw_timer(buf, x + width - 2, y + 1, &format!("{rep}.{step:02} / {reps}.{steps}"));
let style = Style::default().gray();
crate::device::transport::draw_play_stop(buf, x + 2, y + 1, &s.playing);
let separator = format!("{}", "-".repeat((area.width - 2).into()));