mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
refactor: contains_note_on
This commit is contained in:
parent
edadfde1a4
commit
f5da2e6dad
4 changed files with 42 additions and 46 deletions
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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:?}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue