diff --git a/plugins/cagire-plugins/src/lib.rs b/plugins/cagire-plugins/src/lib.rs index d55cd5c..0b206dc 100644 --- a/plugins/cagire-plugins/src/lib.rs +++ b/plugins/cagire-plugins/src/lib.rs @@ -279,8 +279,6 @@ impl Plugin for CagirePlugin { }; let lookahead_end = beat + lookahead_beats; - let engine_time = self.sample_pos as f64 / self.sample_rate as f64; - // Drain commands from the editor let commands: Vec = self.bridge.cmd_rx.try_iter().collect(); @@ -294,7 +292,8 @@ impl Plugin for CagirePlugin { fill: false, nudge_secs: 0.0, current_time_us: 0, - engine_time, + audio_sample_pos: self.sample_pos, + sr: self.sample_rate as f64, mouse_x: 0.5, mouse_y: 0.5, mouse_down: 0.0, @@ -310,12 +309,12 @@ impl Plugin for CagirePlugin { // Drain audio commands from the editor (preview, hush, load samples, etc.) for audio_cmd in self.bridge.audio_cmd_rx.try_iter() { match audio_cmd { - AudioCommand::Evaluate { ref cmd, time } => { - let cmd_ref = match time { + AudioCommand::Evaluate { ref cmd, tick } => { + let cmd_ref = match tick { Some(t) => { self.cmd_buffer.clear(); use std::fmt::Write; - let _ = write!(&mut self.cmd_buffer, "{cmd}/time/{t:.6}"); + let _ = write!(&mut self.cmd_buffer, "{cmd}/tick/{t}"); self.cmd_buffer.as_str() } None => cmd.as_str(), @@ -419,11 +418,11 @@ impl Plugin for CagirePlugin { } continue; } - let cmd_ref = match tsc.time { + let cmd_ref = match tsc.tick { Some(t) => { self.cmd_buffer.clear(); use std::fmt::Write; - let _ = write!(&mut self.cmd_buffer, "{}/time/{t:.6}", tsc.cmd); + let _ = write!(&mut self.cmd_buffer, "{}/tick/{t}", tsc.cmd); self.cmd_buffer.as_str() } None => &tsc.cmd, diff --git a/src/app/scripting.rs b/src/app/scripting.rs index 9652557..3352f1f 100644 --- a/src/app/scripting.rs +++ b/src/app/scripting.rs @@ -225,7 +225,7 @@ impl App { } let _ = audio_tx .load() - .send(crate::engine::AudioCommand::Evaluate { cmd, time: None }); + .send(crate::engine::AudioCommand::Evaluate { cmd, tick: None }); } Ok(if print_output.is_empty() { None diff --git a/src/engine/audio.rs b/src/engine/audio.rs index 9c5a512..48c4aa9 100644 --- a/src/engine/audio.rs +++ b/src/engine/audio.rs @@ -454,12 +454,12 @@ pub fn build_stream( while let Ok(cmd) = audio_rx.try_recv() { match cmd { - AudioCommand::Evaluate { cmd, time } => { - let cmd_ref = match time { + AudioCommand::Evaluate { cmd, tick } => { + let cmd_ref = match tick { Some(t) => { cmd_buffer.clear(); use std::fmt::Write; - let _ = write!(&mut cmd_buffer, "{cmd}/time/{t:.6}"); + let _ = write!(&mut cmd_buffer, "{cmd}/tick/{t}"); cmd_buffer.as_str() } None => &cmd, diff --git a/src/engine/sequencer.rs b/src/engine/sequencer.rs index be4a12b..15af231 100644 --- a/src/engine/sequencer.rs +++ b/src/engine/sequencer.rs @@ -49,7 +49,7 @@ impl PatternChange { } pub enum AudioCommand { - Evaluate { cmd: String, time: Option }, + Evaluate { cmd: String, tick: Option }, Hush, Panic, LoadSamples(Vec), @@ -521,7 +521,8 @@ pub struct TickInput { pub fill: bool, pub nudge_secs: f64, pub current_time_us: SyncTime, - pub engine_time: f64, + pub audio_sample_pos: u64, + pub sr: f64, pub mouse_x: f64, pub mouse_y: f64, pub mouse_down: f64, @@ -529,7 +530,7 @@ pub struct TickInput { pub struct TimestampedCommand { pub cmd: String, - pub time: Option, + pub tick: Option, } pub struct TickOutput { @@ -774,7 +775,8 @@ impl SequencerState { input.fill, input.nudge_secs, input.current_time_us, - input.engine_time, + input.audio_sample_pos, + input.sr, input.mouse_x, input.mouse_y, input.mouse_down, @@ -788,7 +790,8 @@ impl SequencerState { input.quantum, input.fill, input.nudge_secs, - input.engine_time, + input.audio_sample_pos, + input.sr, input.mouse_x, input.mouse_y, input.mouse_down, @@ -922,7 +925,8 @@ impl SequencerState { fill: bool, nudge_secs: f64, _current_time_us: SyncTime, - engine_time: f64, + audio_sample_pos: u64, + sr: f64, mouse_x: f64, mouse_y: f64, mouse_down: f64, @@ -969,7 +973,7 @@ impl SequencerState { } else { 0.0 }; - let event_time = Some(engine_time + time_delta); + let event_tick = Some(audio_sample_pos + (time_delta * sr).round() as u64); if let Some(step) = pattern.steps.get(step_idx) { let resolved_script = pattern.resolve_script(step_idx); @@ -1037,7 +1041,7 @@ impl SequencerState { self.event_count += 1; self.buf_audio_commands.push(TimestampedCommand { cmd, - time: event_time, + tick: event_tick, }); } } @@ -1080,7 +1084,8 @@ impl SequencerState { quantum: f64, fill: bool, nudge_secs: f64, - engine_time: f64, + audio_sample_pos: u64, + sr: f64, mouse_x: f64, mouse_y: f64, mouse_down: f64, @@ -1105,7 +1110,7 @@ impl SequencerState { } else { 0.0 }; - let event_time = Some(engine_time + time_delta); + let event_tick = Some(audio_sample_pos + (time_delta * sr).round() as u64); let step_in_cycle = self.script_step % self.script_length; @@ -1149,7 +1154,7 @@ impl SequencerState { self.event_count += 1; self.buf_audio_commands.push(TimestampedCommand { cmd, - time: event_time, + tick: event_tick, }); } } @@ -1305,11 +1310,6 @@ fn sequencer_loop( let sr = sample_rate.load(Ordering::Relaxed) as f64; let audio_samples = audio_sample_pos.load(Ordering::Acquire); - let engine_time = if sr > 0.0 { - audio_samples as f64 / sr - } else { - 0.0 - }; let input = TickInput { commands, playing: playing.load(Ordering::Relaxed), @@ -1320,7 +1320,8 @@ fn sequencer_loop( fill: live_keys.fill(), nudge_secs: nudge_us.load(Ordering::Relaxed) as f64 / 1_000_000.0, current_time_us, - engine_time, + audio_sample_pos: audio_samples, + sr, #[cfg(feature = "desktop")] mouse_x: f32::from_bits(mouse_x.load(Ordering::Relaxed)) as f64, #[cfg(not(feature = "desktop"))] @@ -1370,7 +1371,7 @@ fn sequencer_loop( } else { let _ = audio_tx.load().send(AudioCommand::Evaluate { cmd: tsc.cmd, - time: tsc.time, + tick: tsc.tick, }); } } @@ -1542,7 +1543,8 @@ mod tests { fill: false, nudge_secs: 0.0, current_time_us: 0, - engine_time: 0.0, + audio_sample_pos: 0, + sr: 48000.0, mouse_x: 0.5, mouse_y: 0.5, mouse_down: 0.0, @@ -1560,7 +1562,8 @@ mod tests { fill: false, nudge_secs: 0.0, current_time_us: 0, - engine_time: 0.0, + audio_sample_pos: 0, + sr: 48000.0, mouse_x: 0.5, mouse_y: 0.5, mouse_down: 0.0, diff --git a/src/input/engine_page.rs b/src/input/engine_page.rs index aee636f..b56d96a 100644 --- a/src/input/engine_page.rs +++ b/src/input/engine_page.rs @@ -300,7 +300,7 @@ pub(super) fn handle_engine_page(ctx: &mut InputContext, key: KeyEvent) -> Input KeyCode::Char('t') if !ctx.app.plugin_mode => { let _ = ctx.audio_tx.load().send(AudioCommand::Evaluate { cmd: "/sound/sine/dur/0.5/decay/0.2".into(), - time: None, + tick: None, }); } KeyCode::Char('s') => super::open_save(ctx), diff --git a/src/input/modal.rs b/src/input/modal.rs index 2ed41c7..051a0d4 100644 --- a/src/input/modal.rs +++ b/src/input/modal.rs @@ -796,7 +796,7 @@ fn execute_palette_entry( .load() .send(crate::engine::AudioCommand::Evaluate { cmd: "/sound/sine/dur/0.5/decay/0.2".into(), - time: None, + tick: None, }); } None => {} diff --git a/src/input/sample_explorer.rs b/src/input/sample_explorer.rs index 9ebcfa8..0770ff7 100644 --- a/src/input/sample_explorer.rs +++ b/src/input/sample_explorer.rs @@ -70,7 +70,7 @@ pub(super) fn handle_sample_explorer(ctx: &mut InputContext, key: KeyEvent) -> I let _ = ctx .audio_tx .load() - .send(AudioCommand::Evaluate { cmd, time: None }); + .send(AudioCommand::Evaluate { cmd, tick: None }); ctx.dispatch(AppCommand::SetStatus(format!( "\u{25B8} {}/{}", folder, entry.label