From f5da2e6dadfdba95e8a6e51ef2b66f4f710d60ec Mon Sep 17 00:00:00 2001 From: unspeaker Date: Tue, 2 Jul 2024 19:59:43 +0300 Subject: [PATCH] refactor: contains_note_on --- src/device/sequencer/horizontal.rs | 4 +-- src/device/sequencer/mod.rs | 54 +++++++++--------------------- src/device/sequencer/phrase.rs | 20 +++++++++-- src/device/sequencer/vertical.rs | 10 +++--- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/device/sequencer/horizontal.rs b/src/device/sequencer/horizontal.rs index 826f267b..97731873 100644 --- a/src/device/sequencer/horizontal.rs +++ b/src/device/sequencer/horizontal.rs @@ -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), diff --git a/src/device/sequencer/mod.rs b/src/device/sequencer/mod.rs index a4e276cb..eb7de416 100644 --- a/src/device/sequencer/mod.rs +++ b/src/device/sequencer/mod.rs @@ -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>>> = 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> { Ok(vec![self.midi_in.name()?]) } fn midi_outs (&self) -> Usually> { Ok(vec![self.midi_out.name()?]) } @@ -204,21 +186,6 @@ pub fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually } 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:?}")); + } + } + } +} diff --git a/src/device/sequencer/phrase.rs b/src/device/sequencer/phrase.rs index af1e495b..a6949552 100644 --- a/src/device/sequencer/phrase.rs +++ b/src/device/sequencer/phrase.rs @@ -16,7 +16,23 @@ impl Phrase { pub fn new (name: &str, length: usize, notes: Option) -> 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, diff --git a/src/device/sequencer/vertical.rs b/src/device/sequencer/vertical.rs index c5dc5099..a6933487 100644 --- a/src/device/sequencer/vertical.rs +++ b/src/device/sequencer/vertical.rs @@ -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(); }