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_b = note0 + index as usize * 2 + 1;
let (character, style) = match (
contains_note_on(phrase, 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_a as u8), a, b),
phrase.contains_note_on(u7::from_int_lossy(note_b as u8), a, b),
) {
(true, true) => ("", wh),
(false, true) => ("", wh),

View file

@ -86,20 +86,13 @@ impl Sequencer {
}
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());
if phrase.is_none() {
return Control::Continue
}
if phrase.is_none() { return Control::Continue }
let phrase = phrase.unwrap();
// Prepare output buffer and transport
let frame = scope.last_frame_time() as usize;//transport.pos.frame() as usize;
let frame = scope.last_frame_time() as usize;
let frames = scope.n_frames() as usize;
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();
if transport.state != self.playing {
all_notes_off(&mut output);
@ -124,22 +117,11 @@ impl Sequencer {
&self.timebase,
frame,
);
// Write to port from output buffer
// (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:?}"));
}
}
}
write_output(&mut self.midi_out.writer(scope), &mut output, frames);
Control::Continue
}
}
impl PortList for Sequencer {
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()?]) }
@ -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 })
}
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.
pub fn all_notes_off (output: &mut MIDIChunk) {
output[0] = Some(vec![]);
@ -230,3 +197,14 @@ pub fn all_notes_off (output: &mut MIDIChunk) {
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 {
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 (
&self,
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 (
&mut self,
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 + 2) as usize * ppq / s.time_zoom as usize,
);
let phrase = &s.phrases[s.sequence.unwrap()];
let (character, style) = match (
contains_note_on(&s.phrases[s.sequence.unwrap()], key, a, b),
contains_note_on(&s.phrases[s.sequence.unwrap()], key, b, c),
phrase.contains_note_on(key, a, b),
phrase.contains_note_on(key, b, c),
) {
(true, true) => ("", 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,
);
let key = ::midly::num::u7::from(key as u8);
is_on = is_on || contains_note_on(&s.phrases[s.sequence.unwrap()], key, a, b);
is_on = is_on || contains_note_on(&s.phrases[s.sequence.unwrap()], key, b, c);
let phrase = &s.phrases[s.sequence.unwrap()];
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 {
color = Style::default().red();
}