wip: correct cycle timings (jitter eats notes)

This commit is contained in:
🪞👃🪞 2024-07-05 14:36:09 +03:00
parent e83802e1fd
commit 665885f6ff
5 changed files with 90 additions and 76 deletions

View file

@ -44,36 +44,78 @@ impl Phrase {
output: &mut MIDIChunk,
notes_on: &mut Vec<bool>,
timebase: &Arc<Timebase>,
frame0: usize,
frames: usize,
(usec0, usecs, _): (usize, usize, f64),
) {
let start = frame0 as f64;
let end = start + frames as f64;
let start = timebase.usecs_frames(usec0 as f64);
let end = timebase.usecs_frames((usec0 + usecs) as f64);
let repeat = timebase.pulses_frames(self.length as f64);
let ticks = timebase.frames_to_ticks(start, end, repeat);
//panic!("{start} {end} {repeat} {ticks:?}");
for (time, tick) in ticks.iter() {
let events = self.notes.get(&(*tick as usize));
if events.is_none() {
continue
}
for message in events.unwrap().iter() {
let mut buf = vec![];
let channel = 0.into();
let message = *message;
match message {
MidiMessage::NoteOn { key, .. } => notes_on[key.as_int() as usize] = true,
MidiMessage::NoteOff { key, .. } => notes_on[key.as_int() as usize] = false,
_ => {}
if let Some(events) = self.notes.get(&(*tick as usize)) {
for message in events.iter() {
let mut buf = vec![];
let channel = 0.into();
let message = *message;
match message {
MidiMessage::NoteOn { key, .. } => notes_on[key.as_int() as usize] = true,
MidiMessage::NoteOff { key, .. } => notes_on[key.as_int() as usize] = false,
_ => {}
}
LiveEvent::Midi { channel, message }.write(&mut buf).unwrap();
let t = *time as usize;
output[t].push(buf);
}
LiveEvent::Midi { channel, message }.write(&mut buf).unwrap();
let t = *time as usize;
output[t].push(buf);
}
}
}
}
impl Timebase {
pub fn frames_to_ticks (
&self,
start: f64,
end: f64,
repeat: f64,
) -> Vec<(usize, usize)> {
let start_frame = start % repeat;
let end_frame = end % repeat;
let fpt = self.pulse_frame();
//panic!("{start_frame} {end_frame} {fpt}");
let mut ticks = vec![];
let mut add_frame = |frame: f64|{
let jitter = frame.rem_euclid(fpt);
let last_jitter = (frame - 1.0).max(0.0) % fpt;
let next_jitter = frame + 1.0 % fpt;
if jitter <= last_jitter && jitter <= next_jitter {
ticks.push((frame as usize % (end as usize-start as usize), (frame / fpt) as usize));
};
};
if start_frame < end_frame {
for frame in start_frame as usize..end_frame as usize {
add_frame(frame as f64);
}
} else {
let mut frame = start_frame as usize;
loop {
add_frame(frame as f64);
frame = frame + 1;
if frame >= repeat as usize {
frame = 0;
loop {
add_frame(frame as f64);
frame = frame + 1;
if frame >= (end_frame as usize).saturating_sub(1) {
break
}
}
break
}
}
}
ticks
}
}
#[macro_export] macro_rules! phrase {
($($t:expr => $msg:expr),* $(,)?) => {{
let mut phrase = BTreeMap::new();