mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
launch countdown/switchover, pt.2
This commit is contained in:
parent
3df8e87840
commit
97a7bf5b1d
3 changed files with 31 additions and 12 deletions
|
|
@ -236,12 +236,20 @@ impl<E: Engine> Arrangement<E> {
|
|||
size: Measure::new(),
|
||||
}
|
||||
}
|
||||
fn is_stopped (&self) -> bool {
|
||||
*self.clock.playing.read().unwrap() == Some(TransportState::Stopped)
|
||||
}
|
||||
pub fn activate (&mut self) {
|
||||
match self.selected {
|
||||
ArrangementFocus::Scene(s) => {
|
||||
for (t, track) in self.tracks.iter_mut().enumerate() {
|
||||
track.player.enqueue_next(self.scenes[s].clips[t].as_ref());
|
||||
}
|
||||
// TODO make transport available here, so that
|
||||
// activating a scene when stopped starts playback
|
||||
//if self.is_stopped() {
|
||||
//self.transport.toggle_play()
|
||||
//}
|
||||
},
|
||||
ArrangementFocus::Clip(t, s) => {
|
||||
self.tracks[t].player.enqueue_next(self.scenes[s].clips[t].as_ref());
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl<E: Engine> Audio for Sequencer<E> {
|
|||
impl Audio for PhrasePlayer {
|
||||
fn process (&mut self, _: &Client, scope: &ProcessScope) -> Control {
|
||||
let has_midi_outputs = self.has_midi_outputs();
|
||||
let has_midi_inputs = self.has_midi_inputs();
|
||||
let has_midi_inputs = self.has_midi_inputs();
|
||||
if has_midi_outputs {
|
||||
// Clear output buffer(s)
|
||||
self.clear(scope, false);
|
||||
|
|
@ -45,11 +45,12 @@ impl PhrasePlayer {
|
|||
all_notes_off(&mut self.midi_out_buf); self.reset = false;
|
||||
}
|
||||
}
|
||||
fn is_rolling (&self) -> bool {
|
||||
*self.clock.playing.read().unwrap() == Some(TransportState::Rolling)
|
||||
}
|
||||
/// Return playing phrase with starting point
|
||||
fn playing (&self) -> Option<(usize, Arc<RwLock<Phrase>>)> {
|
||||
if let (
|
||||
Some(TransportState::Rolling), Some((started, Some(ref phrase)))
|
||||
) = (*self.clock.playing.read().unwrap(), &self.phrase) {
|
||||
if let (true, Some((started, Some(ref phrase)))) = (self.is_rolling(), &self.phrase) {
|
||||
Some((started.sample().get() as usize, phrase.clone()))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -57,9 +58,7 @@ impl PhrasePlayer {
|
|||
}
|
||||
/// Return next phrase with starting point
|
||||
fn enqueued (&self) -> Option<(usize, Arc<RwLock<Phrase>>)> {
|
||||
if let (
|
||||
Some(TransportState::Rolling), Some((start_at, Some(ref phrase)))
|
||||
) = (*self.clock.playing.read().unwrap(), &self.next_phrase) {
|
||||
if let (true, Some((start_at, Some(ref phrase)))) = (self.is_rolling(), &self.next_phrase) {
|
||||
Some((start_at.sample().get() as usize, phrase.clone()))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -76,6 +75,10 @@ impl PhrasePlayer {
|
|||
let notes_on = &mut self.notes_out.write().unwrap();
|
||||
let mut buf = Vec::with_capacity(8);
|
||||
for (sample, tick) in ticks {
|
||||
// If a next phrase is enqueued, and we're past the end of the current one,
|
||||
// break the loop here (FIXME count tick correctly)
|
||||
if self.next_phrase.is_some() && tick >= phrase.length { break }
|
||||
// Output events from phrase at appropriate frames of output buffer
|
||||
let tick = tick % phrase.length;
|
||||
for message in phrase.notes[tick].iter() {
|
||||
buf.clear();
|
||||
|
|
@ -88,6 +91,9 @@ impl PhrasePlayer {
|
|||
}
|
||||
}).unwrap()
|
||||
}
|
||||
if let Some((start, ref phrase)) = self.enqueued() {
|
||||
// TODO switch to next phrase and fill in remaining ticks from it
|
||||
}
|
||||
}
|
||||
fn record (&mut self, scope: &ProcessScope) {
|
||||
let sample0 = scope.last_frame_time() as usize;
|
||||
|
|
@ -101,7 +107,9 @@ impl PhrasePlayer {
|
|||
for input in self.midi_inputs.iter() {
|
||||
for (sample, event, bytes) in parse_midi_input(input.iter(scope)) {
|
||||
if let LiveEvent::Midi { message, .. } = event {
|
||||
if self.monitoring { self.midi_out_buf[sample].push(bytes.to_vec()) }
|
||||
if self.monitoring {
|
||||
self.midi_out_buf[sample].push(bytes.to_vec())
|
||||
}
|
||||
if self.recording {
|
||||
phrase.record_event({
|
||||
let pulse = self.clock.timebase().samples_to_pulse(
|
||||
|
|
@ -117,6 +125,9 @@ impl PhrasePlayer {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let Some((start, ref phrase)) = self.enqueued() {
|
||||
// TODO switch to next phrase and record into it
|
||||
}
|
||||
}
|
||||
fn monitor (&mut self, scope: &ProcessScope) {
|
||||
let mut notes_in = self.notes_in.write().unwrap();
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@ use crate::*;
|
|||
#[derive(Debug, Default)]
|
||||
pub struct TransportTime {
|
||||
/// Current moment in time
|
||||
pub instant: Instant,
|
||||
pub instant: Instant,
|
||||
/// Note quantization factor
|
||||
pub quant: TimeUnit,
|
||||
pub quant: TimeUnit,
|
||||
/// Launch quantization factor
|
||||
pub sync: TimeUnit,
|
||||
pub sync: TimeUnit,
|
||||
/// Playback state
|
||||
pub playing: RwLock<Option<TransportState>>,
|
||||
pub playing: RwLock<Option<TransportState>>,
|
||||
}
|
||||
impl TransportTime {
|
||||
pub fn timebase (&self) -> &Arc<Timebase> { &self.instant.timebase }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue