sequencer: extract get_sample_offset, get_pulses
Some checks are pending
/ build (push) Waiting to run

This commit is contained in:
🪞👃🪞 2025-05-11 01:56:02 +03:00
parent 329da026d7
commit 997d67a487

View file

@ -163,9 +163,64 @@ pub trait MidiPlayer: HasPlayClip + HasClock + HasMidiOuts {
}
// If a clip is playing, write a chunk of MIDI events from it to the output buffer.
// If no clip is playing, prepare for switchover immediately.
self.play_clip().as_ref().map_or(true, |(started, clip)|{
if let Some((started, clip)) = self.play_clip() {
self.play_chunk(scope, note_buf, out, started, clip)
})
} else {
true
}
}
fn play_chunk (
&self,
scope: &ProcessScope,
note_buf: &mut Vec<u8>,
out: &mut [Vec<Vec<u8>>],
started: &Moment,
clip: &Option<Arc<RwLock<MidiClip>>>
) -> bool {
// Index of first sample to populate.
let offset = self.get_sample_offset(scope, started);
// Notes active during current chunk.
let notes = &mut self.notes_out().write().unwrap();
// Length of clip.
let length = clip.as_ref().map_or(0, |p|p.read().unwrap().length);
// Write MIDI events from clip at sample offsets corresponding to pulses.
for (sample, pulse) in self.get_pulses(scope, offset) {
// If a next clip is enqueued, and we're past the end of the current one,
// break the loop here (FIXME count pulse correctly)
let past_end = if clip.is_some() { pulse >= length } else { true };
// Is it time for switchover?
if self.next_clip().is_some() && past_end {
return true
}
// If there's a currently playing clip, output notes from it to buffer:
if let Some(ref clip) = clip {
Self::play_pulse(clip, pulse, sample, note_buf, out, notes)
}
}
false
}
/// Get index of first sample to populate.
///
/// Greater than 0 means that the first pulse of the clip
/// falls somewhere in the middle of the chunk.
fn get_sample_offset (&self, scope: &ProcessScope, started: &Moment) -> usize{
(scope.last_frame_time() as usize).saturating_sub(
started.sample.get() as usize +
self.clock().started.read().unwrap().as_ref().unwrap().sample.get() as usize
)
}
// Get iterator that emits sample paired with pulse.
//
// * Sample: index into output buffer at which to write MIDI event
// * Pulse: index into clip from which to take the MIDI event
//
// Emitted for each sample of the output buffer that corresponds to a MIDI pulse.
fn get_pulses (&self, scope: &ProcessScope, offset: usize) -> TicksIterator {
self.clock().timebase().pulses_between_samples(
offset, offset + scope.n_frames() as usize)
}
/// Handle switchover from current to next playing clip.
@ -197,42 +252,6 @@ pub trait MidiPlayer: HasPlayClip + HasClock + HasMidiOuts {
}
}
fn play_chunk (
&self,
scope: &ProcessScope,
note_buf: &mut Vec<u8>,
out: &mut [Vec<Vec<u8>>],
started: &Moment,
clip: &Option<Arc<RwLock<MidiClip>>>
) -> bool {
// First sample to populate. Greater than 0 means that the first
// pulse of the clip falls somewhere in the middle of the chunk.
let sample = (scope.last_frame_time() as usize).saturating_sub(
started.sample.get() as usize +
self.clock().started.read().unwrap().as_ref().unwrap().sample.get() as usize
);
// Iterator that emits sample (index into output buffer at which to write MIDI event)
// paired with pulse (index into clip from which to take the MIDI event) for each
// sample of the output buffer that corresponds to a MIDI pulse.
let pulses = self.clock().timebase().pulses_between_samples(sample, sample + scope.n_frames() as usize);
// Notes active during current chunk.
let notes = &mut self.notes_out().write().unwrap();
let length = clip.as_ref().map_or(0, |p|p.read().unwrap().length);
for (sample, pulse) in pulses {
// If a next clip is enqueued, and we're past the end of the current one,
// break the loop here (FIXME count pulse correctly)
let past_end = if clip.is_some() { pulse >= length } else { true };
if self.next_clip().is_some() && past_end {
return true
}
// If there's a currently playing clip, output notes from it to buffer:
if let Some(ref clip) = clip {
Self::play_pulse(clip, pulse, sample, note_buf, out, notes)
}
}
false
}
fn play_pulse (
clip: &RwLock<MidiClip>,
pulse: usize,