refactor: contains_note_on

This commit is contained in:
🪞👃🪞 2024-07-02 19:59:43 +03:00
parent edadfde1a4
commit f5da2e6dad
4 changed files with 42 additions and 46 deletions

View file

@ -123,8 +123,8 @@ pub fn lanes (
let note_a = note0 + index as usize * 2; let note_a = note0 + index as usize * 2;
let note_b = note0 + index as usize * 2 + 1; let note_b = note0 + index as usize * 2 + 1;
let (character, style) = match ( let (character, style) = match (
contains_note_on(phrase, u7::from_int_lossy(note_a as u8), a, b), phrase.contains_note_on(u7::from_int_lossy(note_a as u8), a, b),
contains_note_on(phrase, u7::from_int_lossy(note_b as u8), a, b), phrase.contains_note_on(u7::from_int_lossy(note_b as u8), a, b),
) { ) {
(true, true) => ("", wh), (true, true) => ("", wh),
(false, true) => ("", wh), (false, true) => ("", wh),

View file

@ -86,20 +86,13 @@ impl Sequencer {
} }
pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control { pub fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
// Get currently playing phrase if self.sequence.is_none() { return Control::Continue }
if self.sequence.is_none() {
return Control::Continue
}
let phrase = self.phrases.get_mut(self.sequence.unwrap()); let phrase = self.phrases.get_mut(self.sequence.unwrap());
if phrase.is_none() { if phrase.is_none() { return Control::Continue }
return Control::Continue
}
let phrase = phrase.unwrap(); let phrase = phrase.unwrap();
// Prepare output buffer and transport let frame = scope.last_frame_time() as usize;
let frame = scope.last_frame_time() as usize;//transport.pos.frame() as usize;
let frames = scope.n_frames() as usize; let frames = scope.n_frames() as usize;
let mut output: Vec<Option<Vec<Vec<u8>>>> = vec![None;frames]; let mut output: Vec<Option<Vec<Vec<u8>>>> = vec![None;frames];
// Check transport self. If starting or stopping, send "all notes off":
let transport = self.transport.query().unwrap(); let transport = self.transport.query().unwrap();
if transport.state != self.playing { if transport.state != self.playing {
all_notes_off(&mut output); all_notes_off(&mut output);
@ -124,22 +117,11 @@ impl Sequencer {
&self.timebase, &self.timebase,
frame, frame,
); );
// Write to port from output buffer write_output(&mut self.midi_out.writer(scope), &mut output, frames);
// (containing notes from sequence and/or monitor)
let mut writer = self.midi_out.writer(scope);
for time in 0..scope.n_frames() {
if let Some(Some(frame)) = output.get_mut(time as usize) {
for event in frame.iter() {
writer.write(&::jack::RawMidi { time, bytes: &event })
.expect(&format!("{event:?}"));
}
}
}
Control::Continue Control::Continue
} }
} }
impl PortList for Sequencer { impl PortList for Sequencer {
fn midi_ins (&self) -> Usually<Vec<String>> { Ok(vec![self.midi_in.name()?]) } fn midi_ins (&self) -> Usually<Vec<String>> { Ok(vec![self.midi_in.name()?]) }
fn midi_outs (&self) -> Usually<Vec<String>> { Ok(vec![self.midi_out.name()?]) } fn midi_outs (&self) -> Usually<Vec<String>> { Ok(vec![self.midi_out.name()?]) }
@ -204,21 +186,6 @@ pub fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect>
} }
Ok(Rect { x, y, width: 14, height: 14 }) Ok(Rect { x, y, width: 14, height: 14 })
} }
pub fn contains_note_on (sequence: &Phrase, k: u7, start: usize, end: usize) -> bool {
for (_, (_, events)) in sequence.notes.range(start..end).enumerate() {
for event in events.iter() {
match event {
MidiMessage::NoteOn {key,..} => {
if *key == k {
return true
}
}
_ => {}
}
}
}
return false
}
/// Add "all notes off" to the start of a buffer. /// Add "all notes off" to the start of a buffer.
pub fn all_notes_off (output: &mut MIDIChunk) { pub fn all_notes_off (output: &mut MIDIChunk) {
output[0] = Some(vec![]); output[0] = Some(vec![]);
@ -230,3 +197,14 @@ pub fn all_notes_off (output: &mut MIDIChunk) {
frame.push(buf); frame.push(buf);
} }
} }
/// Write to JACK port from output buffer (containing notes from sequence and/or monitor)
fn write_output (writer: &mut ::jack::MidiWriter, output: &mut MIDIChunk, frames: usize) {
for time in 0..frames {
if let Some(Some(frame)) = output.get_mut(time ) {
for event in frame.iter() {
writer.write(&::jack::RawMidi { time: time as u32, bytes: &event })
.expect(&format!("{event:?}"));
}
}
}
}

View file

@ -16,7 +16,23 @@ impl Phrase {
pub fn new (name: &str, length: usize, notes: Option<PhraseData>) -> Self { pub fn new (name: &str, length: usize, notes: Option<PhraseData>) -> Self {
Self { name: name.to_string(), length, notes: notes.unwrap_or(BTreeMap::new()) } Self { name: name.to_string(), length, notes: notes.unwrap_or(BTreeMap::new()) }
} }
/** Write a chunk of MIDI events to an output port. */ /// Check if a range `start..end` contains MIDI Note On `k`
pub fn contains_note_on (&self, k: u7, start: usize, end: usize) -> bool {
for (_, (_, events)) in self.notes.range(start..end).enumerate() {
for event in events.iter() {
match event {
MidiMessage::NoteOn {key,..} => {
if *key == k {
return true
}
}
_ => {}
}
}
}
return false
}
/// Write a chunk of MIDI events to an output port.
pub fn process_out ( pub fn process_out (
&self, &self,
output: &mut MIDIChunk, output: &mut MIDIChunk,
@ -55,7 +71,7 @@ impl Phrase {
} }
} }
} }
/** Read a chunk of MIDI events from an input port. */ /// Read a chunk of MIDI events from an input port.
pub fn process_in ( pub fn process_in (
&mut self, &mut self,
input: ::jack::MidiIter, input: ::jack::MidiIter,

View file

@ -37,9 +37,10 @@ pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
(step + 1) as usize * ppq / s.time_zoom as usize, (step + 1) as usize * ppq / s.time_zoom as usize,
(step + 2) as usize * ppq / s.time_zoom as usize, (step + 2) as usize * ppq / s.time_zoom as usize,
); );
let phrase = &s.phrases[s.sequence.unwrap()];
let (character, style) = match ( let (character, style) = match (
contains_note_on(&s.phrases[s.sequence.unwrap()], key, a, b), phrase.contains_note_on(key, a, b),
contains_note_on(&s.phrases[s.sequence.unwrap()], key, b, c), phrase.contains_note_on(key, b, c),
) { ) {
(true, true) => ("", wh), (true, true) => ("", wh),
(true, false) => ("", wh), (true, false) => ("", wh),
@ -87,8 +88,9 @@ pub fn keys (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
(step + 2) as usize * ppq / s.time_zoom as usize, (step + 2) as usize * ppq / s.time_zoom as usize,
); );
let key = ::midly::num::u7::from(key as u8); let key = ::midly::num::u7::from(key as u8);
is_on = is_on || contains_note_on(&s.phrases[s.sequence.unwrap()], key, a, b); let phrase = &s.phrases[s.sequence.unwrap()];
is_on = is_on || contains_note_on(&s.phrases[s.sequence.unwrap()], key, b, c); is_on = is_on || phrase.contains_note_on(key, a, b);
is_on = is_on || phrase.contains_note_on(key, b, c);
if is_on { if is_on {
color = Style::default().red(); color = Style::default().red();
} }