mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
extract fn switchover
This commit is contained in:
parent
b2680914d7
commit
0c850913f9
1 changed files with 37 additions and 26 deletions
|
|
@ -17,7 +17,9 @@ impl Audio for PhrasePlayer {
|
||||||
// Clear output buffer(s)
|
// Clear output buffer(s)
|
||||||
self.clear(scope, false);
|
self.clear(scope, false);
|
||||||
// Write chunk of phrase to output, handle switchover
|
// Write chunk of phrase to output, handle switchover
|
||||||
self.play(scope);
|
if self.play(scope) {
|
||||||
|
self.switchover(scope);
|
||||||
|
}
|
||||||
if has_midi_inputs {
|
if has_midi_inputs {
|
||||||
if self.recording || self.monitoring {
|
if self.recording || self.monitoring {
|
||||||
// Record and/or monitor input
|
// Record and/or monitor input
|
||||||
|
|
@ -34,8 +36,15 @@ impl Audio for PhrasePlayer {
|
||||||
}
|
}
|
||||||
/// Methods used primarily by the process callback
|
/// Methods used primarily by the process callback
|
||||||
impl PhrasePlayer {
|
impl PhrasePlayer {
|
||||||
fn has_midi_inputs (&self) -> bool { self.midi_inputs.len() > 0 }
|
fn is_rolling (&self) -> bool {
|
||||||
fn has_midi_outputs (&self) -> bool { self.midi_outputs.len() > 0 }
|
*self.clock.playing.read().unwrap() == Some(TransportState::Rolling)
|
||||||
|
}
|
||||||
|
fn has_midi_inputs (&self) -> bool {
|
||||||
|
self.midi_inputs.len() > 0
|
||||||
|
}
|
||||||
|
fn has_midi_outputs (&self) -> bool {
|
||||||
|
self.midi_outputs.len() > 0
|
||||||
|
}
|
||||||
/// 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) {
|
||||||
|
|
@ -46,16 +55,14 @@ impl PhrasePlayer {
|
||||||
all_notes_off(&mut self.midi_out_buf); self.reset = false;
|
all_notes_off(&mut self.midi_out_buf); self.reset = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn is_rolling (&self) -> bool {
|
fn play (&mut self, scope: &ProcessScope) -> bool {
|
||||||
*self.clock.playing.read().unwrap() == Some(TransportState::Rolling)
|
|
||||||
}
|
|
||||||
fn play (&mut self, scope: &ProcessScope) {
|
|
||||||
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;
|
||||||
|
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() {
|
||||||
// If no phrase is playing, prepare for switchover immediately
|
// If no phrase is playing, prepare for switchover immediately
|
||||||
let mut next = self.phrase.is_none();
|
next = self.phrase.is_none();
|
||||||
if let Some((started, phrase)) = &self.phrase {
|
if let Some((started, phrase)) = &self.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.
|
||||||
|
|
@ -105,25 +112,29 @@ impl PhrasePlayer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If it's time for the next enqueued phrase, handle it here:
|
}
|
||||||
if next {
|
next
|
||||||
if let Some((start_at, phrase)) = &self.next_phrase {
|
}
|
||||||
let start = start_at.sample.get() as usize;
|
fn switchover (&mut self, scope: &ProcessScope) {
|
||||||
// If it's time to switch to the next phrase:
|
let sample0 = scope.last_frame_time() as usize;
|
||||||
if start <= sample0.saturating_sub(
|
let samples = scope.n_frames() as usize;
|
||||||
self.clock.started.read().unwrap().unwrap().0
|
if self.is_rolling() {
|
||||||
) {
|
if let Some((start_at, phrase)) = &self.next_phrase {
|
||||||
// Samples elapsed since phrase was supposed to start
|
let start = start_at.sample.get() as usize;
|
||||||
let skipped = sample0 - start;
|
// If it's time to switch to the next phrase:
|
||||||
// Switch over to enqueued phrase
|
if start <= sample0.saturating_sub(
|
||||||
let started = Instant::from_sample(&self.clock.timebase(), start as f64);
|
self.clock.started.read().unwrap().unwrap().0
|
||||||
self.phrase = Some((started, phrase.clone()));
|
) {
|
||||||
// Unset enqueuement (TODO: where to implement looping?)
|
// Samples elapsed since phrase was supposed to start
|
||||||
self.next_phrase = None
|
let skipped = sample0 - start;
|
||||||
}
|
// Switch over to enqueued phrase
|
||||||
// TODO fill in remaining ticks of chunk from next phrase.
|
let started = Instant::from_sample(&self.clock.timebase(), start as f64);
|
||||||
// ?? just call self.play(scope) again, since enqueuement is off ???
|
self.phrase = Some((started, phrase.clone()));
|
||||||
|
// Unset enqueuement (TODO: where to implement looping?)
|
||||||
|
self.next_phrase = None
|
||||||
}
|
}
|
||||||
|
// TODO fill in remaining ticks of chunk from next phrase.
|
||||||
|
// ?? just call self.play(scope) again, since enqueuement is off ???
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue