wip: refactor pt.38 (27e) pass midi out bufs from outside

This commit is contained in:
🪞👃🪞 2024-11-15 13:36:06 +01:00
parent 4b2f8935d3
commit c875d87c33

View file

@ -8,7 +8,8 @@ pub trait HasPlayer: HasJack {
pub trait PlayerApi: MidiInputApi + MidiOutputApi {} pub trait PlayerApi: MidiInputApi + MidiOutputApi {}
pub trait HasMidiBuffer { pub trait HasMidiBuffer {
fn midi_buffer (&self) -> &mut Vec<Vec<Vec<u8>>>; fn midi_buffer (&self) -> &Vec<Vec<Vec<u8>>>;
fn midi_buffer_mut (&self) -> &mut Vec<Vec<Vec<u8>>>;
fn reset (&self) -> bool; fn reset (&self) -> bool;
@ -17,11 +18,11 @@ pub trait HasMidiBuffer {
/// Clear the section of the output buffer that we will be using, /// Clear the section of the output buffer that we will be using,
/// emitting "all notes off" at start of buffer if requested. /// emitting "all notes off" at start of buffer if requested.
fn clear (&mut self, scope: &ProcessScope, force_reset: bool) { fn clear (&mut self, scope: &ProcessScope, force_reset: bool) {
for frame in &mut self.midi_buffer()[0..scope.n_frames() as usize] { for frame in &mut self.midi_buffer_mut()[0..scope.n_frames() as usize] {
frame.clear(); frame.clear();
} }
if self.reset() || force_reset { if self.reset() || force_reset {
all_notes_off(&mut self.midi_buffer()); all_notes_off(&mut self.midi_buffer_mut());
*self.reset_mut() = false; *self.reset_mut() = false;
} }
} }
@ -92,7 +93,7 @@ pub trait MidiInputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
for (sample, event, bytes) in parse_midi_input(input.iter(scope)) { for (sample, event, bytes) in parse_midi_input(input.iter(scope)) {
if let LiveEvent::Midi { message, .. } = event { if let LiveEvent::Midi { message, .. } = event {
if self.monitoring() { if self.monitoring() {
self.midi_buffer()[sample].push(bytes.to_vec()) self.midi_buffer_mut()[sample].push(bytes.to_vec())
} }
if self.recording() { if self.recording() {
if let Some(phrase) = phrase { if let Some(phrase) = phrase {
@ -122,7 +123,7 @@ pub trait MidiInputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
for input in self.midi_ins_mut().iter() { for input in self.midi_ins_mut().iter() {
for (sample, event, bytes) in parse_midi_input(input.iter(scope)) { for (sample, event, bytes) in parse_midi_input(input.iter(scope)) {
if let LiveEvent::Midi { message, .. } = event { if let LiveEvent::Midi { message, .. } = event {
self.midi_buffer()[sample].push(bytes.to_vec()); self.midi_buffer_mut()[sample].push(bytes.to_vec());
update_keys(&mut notes_in, &message); update_keys(&mut notes_in, &message);
} }
} }
@ -144,7 +145,12 @@ pub trait MidiOutputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
self.midi_outs().len() > 0 self.midi_outs().len() > 0
} }
fn play (&mut self, scope: &ProcessScope) -> bool { fn play (
&mut self,
scope: &ProcessScope,
note_buffer: &mut Vec<u8>,
output_buffer: &mut Vec<Vec<Vec<u8>>>
) -> bool {
let mut next = false; let mut next = false;
// Write MIDI events from currently playing phrase (if any) to MIDI output buffer // Write MIDI events from currently playing phrase (if any) to MIDI output buffer
if self.is_rolling() { if self.is_rolling() {
@ -152,13 +158,11 @@ pub trait MidiOutputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
let samples = scope.n_frames() as usize; let samples = scope.n_frames() as usize;
// If no phrase is playing, prepare for switchover immediately // If no phrase is playing, prepare for switchover immediately
next = self.phrase().is_none(); next = self.phrase().is_none();
let mut midi_note = self.midi_note(); let phrase = self.phrase();
let ref phrase = self.phrase(); let started0 = self.started();
let ref started0 = self.started(); let timebase = self.timebase();
let ref timebase = self.timebase(); let notes_out = self.notes_out();
let ref notes_out = self.notes_out(); let next_phrase = self.next_phrase();
let ref next_phrase = self.next_phrase();
let ref midi_buffer = self.midi_buffer();
if let Some((started, phrase)) = phrase { if let Some((started, phrase)) = phrase {
// First sample to populate. Greater than 0 means that the first // First sample to populate. Greater than 0 means that the first
// pulse of the phrase falls somewhere in the middle of the chunk. // pulse of the phrase falls somewhere in the middle of the chunk.
@ -191,15 +195,15 @@ pub trait MidiOutputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
// Output each MIDI event from phrase at appropriate frames of output buffer: // Output each MIDI event from phrase at appropriate frames of output buffer:
for message in phrase.notes[pulse].iter() { for message in phrase.notes[pulse].iter() {
// Clear output buffer for this MIDI event. // Clear output buffer for this MIDI event.
midi_note.clear(); note_buffer.clear();
// TODO: support MIDI channels other than CH1. // TODO: support MIDI channels other than CH1.
let channel = 0.into(); let channel = 0.into();
// Serialize MIDI event into message buffer. // Serialize MIDI event into message buffer.
LiveEvent::Midi { channel, message: *message } LiveEvent::Midi { channel, message: *message }
.write(&mut midi_note) .write(note_buffer)
.unwrap(); .unwrap();
// Append serialized message to output buffer. // Append serialized message to output buffer.
midi_buffer[sample].push(midi_note.clone()); output_buffer[sample].push(note_buffer.clone());
// Update the list of currently held notes. // Update the list of currently held notes.
update_keys(&mut*notes, &message); update_keys(&mut*notes, &message);
} }
@ -210,7 +214,12 @@ pub trait MidiOutputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
next next
} }
fn switchover (&mut self, scope: &ProcessScope) { fn switchover (
&mut self,
scope: &ProcessScope,
note_buffer: &mut Vec<u8>,
output_buffer: &mut Vec<Vec<Vec<u8>>>
) {
if self.is_rolling() { if self.is_rolling() {
let sample0 = scope.last_frame_time() as usize; let sample0 = scope.last_frame_time() as usize;
//let samples = scope.n_frames() as usize; //let samples = scope.n_frames() as usize;
@ -229,20 +238,19 @@ pub trait MidiOutputApi: PlayheadApi + HasMidiBuffer + HasPhrase {
} }
// TODO fill in remaining ticks of chunk from next phrase. // TODO fill in remaining ticks of chunk from next phrase.
// ?? just call self.play(scope) again, since enqueuement is off ??? // ?? just call self.play(scope) again, since enqueuement is off ???
self.play(scope); self.play(scope, note_buffer, output_buffer);
// ?? or must it be with modified scope ?? // ?? or must it be with modified scope ??
// likely not because start time etc // likely not because start time etc
} }
} }
} }
fn write (&mut self, scope: &ProcessScope) { fn write (&mut self, scope: &ProcessScope, output_buffer: &Vec<Vec<Vec<u8>>>) {
let samples = scope.n_frames() as usize; let samples = scope.n_frames() as usize;
for port in self.midi_outs_mut().iter_mut() { for port in self.midi_outs_mut().iter_mut() {
let writer = &mut port.writer(scope); let writer = &mut port.writer(scope);
let output = &self.midi_buffer();
for time in 0..samples { for time in 0..samples {
for event in output[time].iter() { for event in output_buffer[time].iter() {
writer.write(&RawMidi { time: time as u32, bytes: &event }) writer.write(&RawMidi { time: time as u32, bytes: &event })
.expect(&format!("{event:?}")); .expect(&format!("{event:?}"));
} }