move ClockModel to tek_api

This commit is contained in:
🪞👃🪞 2024-11-26 22:02:41 +01:00
parent 4fdc3911e4
commit a26a1f2967
13 changed files with 214 additions and 222 deletions

View file

@ -7,7 +7,7 @@ pub trait HasPlayer: JackApi {
pub trait MidiPlayerApi: MidiInputApi + MidiOutputApi + Send + Sync {}
pub trait HasPhrase: ClockApi {
pub trait HasPhrase: HasClock {
fn reset (&self) -> bool;
fn reset_mut (&mut self) -> &mut bool;
@ -21,23 +21,22 @@ pub trait HasPhrase: ClockApi {
fn next_phrase_mut (&mut self)
-> &mut Option<(Instant, Option<Arc<RwLock<Phrase>>>)>;
fn enqueue_next (&mut self, phrase: Option<&Arc<RwLock<Phrase>>>) {
let start = self.next_launch_pulse();
*self.next_phrase_mut() = Some((
Instant::from_pulse(self.timebase(), start as f64),
phrase.map(|p|p.clone())
));
let start = self.clock().next_launch_pulse() as f64;
let instant = Instant::from_pulse(&self.clock().timebase(), start);
let phrase = phrase.map(|p|p.clone());
*self.next_phrase_mut() = Some((instant, phrase));
*self.reset_mut() = true;
}
fn pulses_since_start (&self) -> Option<f64> {
if let Some((started, Some(_))) = self.play_phrase().as_ref() {
Some(self.current().pulse.get() - started.pulse.get())
Some(self.clock().current.pulse.get() - started.pulse.get())
} else {
None
}
}
}
pub trait MidiInputApi: ClockApi + HasPhrase {
pub trait MidiInputApi: HasPhrase {
fn midi_ins (&self) -> &Vec<Port<MidiIn>>;
fn midi_ins_mut (&mut self) -> &mut Vec<Port<MidiIn>>;
fn has_midi_ins (&self) -> bool {
@ -71,38 +70,40 @@ pub trait MidiInputApi: ClockApi + HasPhrase {
let sample0 = scope.last_frame_time() as usize;
// For highlighting keys and note repeat
let notes_in = self.notes_in().clone();
if let (true, Some((started, ref phrase))) = (self.is_rolling(), self.play_phrase().clone()) {
let start = started.sample.get() as usize;
let quant = self.quant().get();
let timebase = self.timebase().clone();
let monitoring = self.monitoring();
let recording = self.recording();
for input in self.midi_ins_mut().iter() {
for (sample, event, bytes) in parse_midi_input(input.iter(scope)) {
if let LiveEvent::Midi { message, .. } = event {
if monitoring {
midi_buf[sample].push(bytes.to_vec())
}
if recording {
if let Some(phrase) = phrase {
let mut phrase = phrase.write().unwrap();
let length = phrase.length;
phrase.record_event({
let sample = (sample0 + sample - start) as f64;
let pulse = timebase.samples_to_pulse(sample);
let quantized = (pulse / quant).round() * quant;
let looped = quantized as usize % length;
looped
}, message);
if self.clock().is_rolling() {
if let Some((started, ref phrase)) = self.play_phrase().clone() {
let start = started.sample.get() as usize;
let quant = self.clock().quant.get();
let timebase = self.clock().timebase().clone();
let monitoring = self.monitoring();
let recording = self.recording();
for input in self.midi_ins_mut().iter() {
for (sample, event, bytes) in parse_midi_input(input.iter(scope)) {
if let LiveEvent::Midi { message, .. } = event {
if monitoring {
midi_buf[sample].push(bytes.to_vec())
}
if recording {
if let Some(phrase) = phrase {
let mut phrase = phrase.write().unwrap();
let length = phrase.length;
phrase.record_event({
let sample = (sample0 + sample - start) as f64;
let pulse = timebase.samples_to_pulse(sample);
let quantized = (pulse / quant).round() * quant;
let looped = quantized as usize % length;
looped
}, message);
}
}
update_keys(&mut*notes_in.write().unwrap(), &message);
}
update_keys(&mut*notes_in.write().unwrap(), &message);
}
}
}
}
if let (true, Some((start_at, phrase))) = (self.is_rolling(), &self.next_phrase()) {
// TODO switch to next phrase and record into it
if let Some((start_at, phrase)) = &self.next_phrase() {
// TODO switch to next phrase and record into it
}
}
}
@ -125,7 +126,7 @@ pub trait MidiInputApi: ClockApi + HasPhrase {
}
pub trait MidiOutputApi: ClockApi + HasPhrase {
pub trait MidiOutputApi: HasPhrase {
fn midi_outs (&self) -> &Vec<Port<MidiOut>>;
fn midi_outs_mut (&mut self) -> &mut Vec<Port<MidiOut>>;
@ -162,14 +163,14 @@ pub trait MidiOutputApi: ClockApi + HasPhrase {
) -> bool {
let mut next = false;
// Write MIDI events from currently playing phrase (if any) to MIDI output buffer
if self.is_rolling() {
if self.clock().is_rolling() {
let sample0 = scope.last_frame_time() as usize;
let samples = scope.n_frames() as usize;
// If no phrase is playing, prepare for switchover immediately
next = self.play_phrase().is_none();
let phrase = self.play_phrase();
let started0 = self.transport_offset();
let timebase = self.timebase();
let started0 = &self.clock().started;
let timebase = self.clock().timebase();
let notes_out = self.notes_out();
let next_phrase = self.next_phrase();
if let Some((started, phrase)) = phrase {
@ -232,18 +233,18 @@ pub trait MidiOutputApi: ClockApi + HasPhrase {
note_buffer: &mut Vec<u8>,
output_buffer: &mut Vec<Vec<Vec<u8>>>
) {
if self.is_rolling() {
if self.clock().is_rolling() {
let sample0 = scope.last_frame_time() as usize;
//let samples = scope.n_frames() as usize;
if let Some((start_at, phrase)) = &self.next_phrase() {
let start = start_at.sample.get() as usize;
let sample = self.transport_offset().read().unwrap().unwrap().0;
let sample = self.clock().started.read().unwrap().unwrap().0;
// If it's time to switch to the next phrase:
if start <= sample0.saturating_sub(sample) {
// Samples elapsed since phrase was supposed to start
let skipped = sample0 - start;
// Switch over to enqueued phrase
let started = Instant::from_sample(&self.timebase(), start as f64);
let started = Instant::from_sample(&self.clock().timebase(), start as f64);
*self.play_phrase_mut() = Some((started, phrase.clone()));
// Unset enqueuement (TODO: where to implement looping?)
*self.next_phrase_mut() = None