diff --git a/crates/tek_sequencer/src/arranger_tui.rs b/crates/tek_sequencer/src/arranger_tui.rs index 32e2d359..ed72783b 100644 --- a/crates/tek_sequencer/src/arranger_tui.rs +++ b/crates/tek_sequencer/src/arranger_tui.rs @@ -179,7 +179,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { .map(|port|port.short_name()) .transpose()? .unwrap_or("(none)".into()); - let input = format!("▎i {}", input_name); + let input = format!("▎>{}", input_name); col!(name, input) .min_xy(w as u16, track_title_h) .bg(track.color) @@ -201,7 +201,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> { .map(|port|port.short_name()) .transpose()? .unwrap_or("(none)".into()); - let output = format!("▎o {}", output_name); + let output = format!("▎<{}", output_name); col!(until_next, elapsed, output) .min_xy(w as u16, tracks_footer) .bg(track.color) diff --git a/crates/tek_sequencer/src/sequencer.rs b/crates/tek_sequencer/src/sequencer.rs index 4b069b00..be6cf235 100644 --- a/crates/tek_sequencer/src/sequencer.rs +++ b/crates/tek_sequencer/src/sequencer.rs @@ -423,7 +423,7 @@ impl PhrasePlayer { pub fn toggle_monitor (&mut self) { self.monitoring = !self.monitoring; } pub fn toggle_record (&mut self) { self.recording = !self.recording; } pub fn toggle_overdub (&mut self) { self.overdub = !self.overdub; } - pub fn enqueue_next (&mut self, phrase: Option<&Arc>>) { + pub fn enqueue_next (&mut self, phrase: Option<&Arc>>) { let start = self.clock.next_launch_pulse(); self.next_phrase = Some((start.into(), phrase.map(|p|p.clone()))); self.reset = true; @@ -433,6 +433,21 @@ impl PhrasePlayer { .map(|(started,_)|started.load(Ordering::Relaxed)) .map(|started|started - self.clock.sample()) } + pub fn playing_phrase (&self) -> Option<(usize, Arc>)> { + if let ( + Some(TransportState::Rolling), + Some((start_frame, _)), + Some((_started, Some(ref phrase))) + ) = ( + *self.clock.playing.read().unwrap(), + self.started, + &self.phrase + ) { + Some((start_frame, phrase.clone())) + } else { + None + } + } } /// Displays and edits phrase length pub struct PhraseLength { diff --git a/crates/tek_sequencer/src/sequencer_snd.rs b/crates/tek_sequencer/src/sequencer_snd.rs index f1ba8d8e..62c26651 100644 --- a/crates/tek_sequencer/src/sequencer_snd.rs +++ b/crates/tek_sequencer/src/sequencer_snd.rs @@ -10,47 +10,37 @@ impl Audio for Sequencer { impl PhrasePlayer { pub fn process ( &mut self, - input: Option, scope: &ProcessScope, (frame0, frames): (usize, usize), (_usec0, _usecs): (usize, usize), period: f64, ) { - let has_midi_inputs = self.has_midi_inputs(); let has_midi_outputs = self.has_midi_outputs(); - let quant = self.clock.quant(); if has_midi_outputs { self.clear_midi_out_buf(frames); self.reset_midi_out_buf(false /* FIXME where did force-reset come from? */); } - if let ( - Some(TransportState::Rolling), - Some((start_frame, _)), - Some((_started, Some(ref phrase))) - ) = ( - *self.clock.playing.read().unwrap(), - self.started, - &self.phrase - ) { + let has_midi_inputs = self.has_midi_inputs(); + let quant = self.clock.quant(); + if let Some((start_frame, phrase)) = self.playing_phrase() { phrase.read().map(|phrase|{ if has_midi_outputs { phrase.process_out( - &mut self.midi_out_buf, - &mut self.notes_out.write().unwrap(), - &self.clock.timebase, - (frame0.saturating_sub(start_frame), frames, period) + &mut self.midi_out_buf, &mut self.notes_out.write().unwrap(), + &self.clock.timebase, (frame0.saturating_sub(start_frame), frames, period) ); } }).unwrap(); let mut phrase = phrase.write().unwrap(); let length = phrase.length; // Monitor and record input - if input.is_some() && (self.recording || self.monitoring) { + if has_midi_inputs && (self.recording || self.monitoring) { // For highlighting keys and note repeat let mut notes_in = self.notes_in.write().unwrap(); - for (frame, event, bytes) in parse_midi_input(input.unwrap()) { - match event { - LiveEvent::Midi { message, .. } => { + // Record from each input + for input in self.midi_inputs.iter() { + for (frame, event, bytes) in parse_midi_input(input.iter(scope)) { + if let LiveEvent::Midi { message, .. } = event { if self.monitoring { self.midi_out_buf[frame].push(bytes.to_vec()) } @@ -66,37 +56,20 @@ impl PhrasePlayer { looped }, message); } - match message { - MidiMessage::NoteOn { key, .. } => { - notes_in[key.as_int() as usize] = true; - } - MidiMessage::NoteOff { key, .. } => { - notes_in[key.as_int() as usize] = false; - }, - _ => {} - } - }, - _ => {} + update_keys(&mut notes_in, &message); + } } } } - } else if input.is_some() && has_midi_outputs && self.monitoring { + } else if has_midi_inputs && has_midi_outputs && self.monitoring { let mut notes_in = self.notes_in.write().unwrap(); - for (frame, event, bytes) in parse_midi_input(input.unwrap()) { - match event { - LiveEvent::Midi { message, .. } => { + for input in self.midi_inputs.iter() { + // Monitor each input + for (frame, event, bytes) in parse_midi_input(input.iter(scope)) { + if let LiveEvent::Midi { message, .. } = event { self.midi_out_buf[frame].push(bytes.to_vec()); - match message { - MidiMessage::NoteOn { key, .. } => { - notes_in[key.as_int() as usize] = true; - } - MidiMessage::NoteOff { key, .. } => { - notes_in[key.as_int() as usize] = false; - }, - _ => {} - } - }, - _ => {} + update_keys(&mut notes_in, &message); + } } } } @@ -112,17 +85,11 @@ impl PhrasePlayer { } } } - pub fn has_midi_inputs (&self) -> bool { - self.midi_inputs.len() > 0 - } - pub fn has_midi_outputs (&self) -> bool { - self.midi_outputs.len() > 0 - } + pub fn has_midi_inputs (&self) -> bool { self.midi_inputs.len() > 0 } + pub fn has_midi_outputs (&self) -> bool { self.midi_outputs.len() > 0 } /// Clear the section of the output buffer that we will be using pub fn clear_midi_out_buf (&mut self, frames: usize) { - for frame in &mut self.midi_out_buf[0..frames] { - frame.clear(); - } + for frame in &mut self.midi_out_buf[0..frames] { frame.clear(); } } /// Emit "all notes off" at start of buffer if requested pub fn reset_midi_out_buf (&mut self, force_reset: bool) { @@ -144,9 +111,8 @@ impl Phrase { (frame0, frames, _): (usize, usize, f64), ) { let mut buf = Vec::with_capacity(8); - for (time, tick) in Ticks(timebase.pulses_per_sample()).between_samples( - frame0, frame0 + frames - ) { + let ticks = Ticks(timebase.pulses_per_sample()).between_samples(frame0, frame0 + frames); + for (time, tick) in ticks { let tick = tick % self.length; for message in self.notes[tick].iter() { buf.clear(); @@ -154,11 +120,7 @@ impl Phrase { let message = *message; LiveEvent::Midi { channel, message }.write(&mut buf).unwrap(); output[time as usize].push(buf.clone()); - match message { - MidiMessage::NoteOn { key, .. } => notes_on[key.as_int() as usize] = true, - MidiMessage::NoteOff { key, .. } => notes_on[key.as_int() as usize] = false, - _ => {} - } + update_keys(notes_on, &message); } } } @@ -179,3 +141,11 @@ pub fn parse_midi_input (input: MidiIter) -> Box { keys[key.as_int() as usize] = true; } + MidiMessage::NoteOff { key, .. } => { keys[key.as_int() as usize] = false; }, + _ => {} + } +}