mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: refactor pt.38 (27e) pass midi out bufs from outside
This commit is contained in:
parent
4b2f8935d3
commit
c875d87c33
1 changed files with 29 additions and 21 deletions
|
|
@ -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:?}"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue