Fix: audio engine fixes

This commit is contained in:
2026-03-06 08:27:54 +01:00
parent b2a089fb0c
commit f273470eaf
7 changed files with 37 additions and 35 deletions

View File

@@ -279,8 +279,6 @@ impl Plugin for CagirePlugin {
}; };
let lookahead_end = beat + lookahead_beats; let lookahead_end = beat + lookahead_beats;
let engine_time = self.sample_pos as f64 / self.sample_rate as f64;
// Drain commands from the editor // Drain commands from the editor
let commands: Vec<SeqCommand> = self.bridge.cmd_rx.try_iter().collect(); let commands: Vec<SeqCommand> = self.bridge.cmd_rx.try_iter().collect();
@@ -294,7 +292,8 @@ impl Plugin for CagirePlugin {
fill: false, fill: false,
nudge_secs: 0.0, nudge_secs: 0.0,
current_time_us: 0, current_time_us: 0,
engine_time, audio_sample_pos: self.sample_pos,
sr: self.sample_rate as f64,
mouse_x: 0.5, mouse_x: 0.5,
mouse_y: 0.5, mouse_y: 0.5,
mouse_down: 0.0, mouse_down: 0.0,
@@ -310,12 +309,12 @@ impl Plugin for CagirePlugin {
// Drain audio commands from the editor (preview, hush, load samples, etc.) // Drain audio commands from the editor (preview, hush, load samples, etc.)
for audio_cmd in self.bridge.audio_cmd_rx.try_iter() { for audio_cmd in self.bridge.audio_cmd_rx.try_iter() {
match audio_cmd { match audio_cmd {
AudioCommand::Evaluate { ref cmd, time } => { AudioCommand::Evaluate { ref cmd, tick } => {
let cmd_ref = match time { let cmd_ref = match tick {
Some(t) => { Some(t) => {
self.cmd_buffer.clear(); self.cmd_buffer.clear();
use std::fmt::Write; 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() self.cmd_buffer.as_str()
} }
None => cmd.as_str(), None => cmd.as_str(),
@@ -419,11 +418,11 @@ impl Plugin for CagirePlugin {
} }
continue; continue;
} }
let cmd_ref = match tsc.time { let cmd_ref = match tsc.tick {
Some(t) => { Some(t) => {
self.cmd_buffer.clear(); self.cmd_buffer.clear();
use std::fmt::Write; 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() self.cmd_buffer.as_str()
} }
None => &tsc.cmd, None => &tsc.cmd,

View File

@@ -225,7 +225,7 @@ impl App {
} }
let _ = audio_tx let _ = audio_tx
.load() .load()
.send(crate::engine::AudioCommand::Evaluate { cmd, time: None }); .send(crate::engine::AudioCommand::Evaluate { cmd, tick: None });
} }
Ok(if print_output.is_empty() { Ok(if print_output.is_empty() {
None None

View File

@@ -454,12 +454,12 @@ pub fn build_stream(
while let Ok(cmd) = audio_rx.try_recv() { while let Ok(cmd) = audio_rx.try_recv() {
match cmd { match cmd {
AudioCommand::Evaluate { cmd, time } => { AudioCommand::Evaluate { cmd, tick } => {
let cmd_ref = match time { let cmd_ref = match tick {
Some(t) => { Some(t) => {
cmd_buffer.clear(); cmd_buffer.clear();
use std::fmt::Write; 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() cmd_buffer.as_str()
} }
None => &cmd, None => &cmd,

View File

@@ -49,7 +49,7 @@ impl PatternChange {
} }
pub enum AudioCommand { pub enum AudioCommand {
Evaluate { cmd: String, time: Option<f64> }, Evaluate { cmd: String, tick: Option<u64> },
Hush, Hush,
Panic, Panic,
LoadSamples(Vec<doux::sampling::SampleEntry>), LoadSamples(Vec<doux::sampling::SampleEntry>),
@@ -521,7 +521,8 @@ pub struct TickInput {
pub fill: bool, pub fill: bool,
pub nudge_secs: f64, pub nudge_secs: f64,
pub current_time_us: SyncTime, pub current_time_us: SyncTime,
pub engine_time: f64, pub audio_sample_pos: u64,
pub sr: f64,
pub mouse_x: f64, pub mouse_x: f64,
pub mouse_y: f64, pub mouse_y: f64,
pub mouse_down: f64, pub mouse_down: f64,
@@ -529,7 +530,7 @@ pub struct TickInput {
pub struct TimestampedCommand { pub struct TimestampedCommand {
pub cmd: String, pub cmd: String,
pub time: Option<f64>, pub tick: Option<u64>,
} }
pub struct TickOutput { pub struct TickOutput {
@@ -774,7 +775,8 @@ impl SequencerState {
input.fill, input.fill,
input.nudge_secs, input.nudge_secs,
input.current_time_us, input.current_time_us,
input.engine_time, input.audio_sample_pos,
input.sr,
input.mouse_x, input.mouse_x,
input.mouse_y, input.mouse_y,
input.mouse_down, input.mouse_down,
@@ -788,7 +790,8 @@ impl SequencerState {
input.quantum, input.quantum,
input.fill, input.fill,
input.nudge_secs, input.nudge_secs,
input.engine_time, input.audio_sample_pos,
input.sr,
input.mouse_x, input.mouse_x,
input.mouse_y, input.mouse_y,
input.mouse_down, input.mouse_down,
@@ -922,7 +925,8 @@ impl SequencerState {
fill: bool, fill: bool,
nudge_secs: f64, nudge_secs: f64,
_current_time_us: SyncTime, _current_time_us: SyncTime,
engine_time: f64, audio_sample_pos: u64,
sr: f64,
mouse_x: f64, mouse_x: f64,
mouse_y: f64, mouse_y: f64,
mouse_down: f64, mouse_down: f64,
@@ -969,7 +973,7 @@ impl SequencerState {
} else { } else {
0.0 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) { if let Some(step) = pattern.steps.get(step_idx) {
let resolved_script = pattern.resolve_script(step_idx); let resolved_script = pattern.resolve_script(step_idx);
@@ -1037,7 +1041,7 @@ impl SequencerState {
self.event_count += 1; self.event_count += 1;
self.buf_audio_commands.push(TimestampedCommand { self.buf_audio_commands.push(TimestampedCommand {
cmd, cmd,
time: event_time, tick: event_tick,
}); });
} }
} }
@@ -1080,7 +1084,8 @@ impl SequencerState {
quantum: f64, quantum: f64,
fill: bool, fill: bool,
nudge_secs: f64, nudge_secs: f64,
engine_time: f64, audio_sample_pos: u64,
sr: f64,
mouse_x: f64, mouse_x: f64,
mouse_y: f64, mouse_y: f64,
mouse_down: f64, mouse_down: f64,
@@ -1105,7 +1110,7 @@ impl SequencerState {
} else { } else {
0.0 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; let step_in_cycle = self.script_step % self.script_length;
@@ -1149,7 +1154,7 @@ impl SequencerState {
self.event_count += 1; self.event_count += 1;
self.buf_audio_commands.push(TimestampedCommand { self.buf_audio_commands.push(TimestampedCommand {
cmd, cmd,
time: event_time, tick: event_tick,
}); });
} }
} }
@@ -1305,11 +1310,6 @@ fn sequencer_loop(
let sr = sample_rate.load(Ordering::Relaxed) as f64; let sr = sample_rate.load(Ordering::Relaxed) as f64;
let audio_samples = audio_sample_pos.load(Ordering::Acquire); 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 { let input = TickInput {
commands, commands,
playing: playing.load(Ordering::Relaxed), playing: playing.load(Ordering::Relaxed),
@@ -1320,7 +1320,8 @@ fn sequencer_loop(
fill: live_keys.fill(), fill: live_keys.fill(),
nudge_secs: nudge_us.load(Ordering::Relaxed) as f64 / 1_000_000.0, nudge_secs: nudge_us.load(Ordering::Relaxed) as f64 / 1_000_000.0,
current_time_us, current_time_us,
engine_time, audio_sample_pos: audio_samples,
sr,
#[cfg(feature = "desktop")] #[cfg(feature = "desktop")]
mouse_x: f32::from_bits(mouse_x.load(Ordering::Relaxed)) as f64, mouse_x: f32::from_bits(mouse_x.load(Ordering::Relaxed)) as f64,
#[cfg(not(feature = "desktop"))] #[cfg(not(feature = "desktop"))]
@@ -1370,7 +1371,7 @@ fn sequencer_loop(
} else { } else {
let _ = audio_tx.load().send(AudioCommand::Evaluate { let _ = audio_tx.load().send(AudioCommand::Evaluate {
cmd: tsc.cmd, cmd: tsc.cmd,
time: tsc.time, tick: tsc.tick,
}); });
} }
} }
@@ -1542,7 +1543,8 @@ mod tests {
fill: false, fill: false,
nudge_secs: 0.0, nudge_secs: 0.0,
current_time_us: 0, current_time_us: 0,
engine_time: 0.0, audio_sample_pos: 0,
sr: 48000.0,
mouse_x: 0.5, mouse_x: 0.5,
mouse_y: 0.5, mouse_y: 0.5,
mouse_down: 0.0, mouse_down: 0.0,
@@ -1560,7 +1562,8 @@ mod tests {
fill: false, fill: false,
nudge_secs: 0.0, nudge_secs: 0.0,
current_time_us: 0, current_time_us: 0,
engine_time: 0.0, audio_sample_pos: 0,
sr: 48000.0,
mouse_x: 0.5, mouse_x: 0.5,
mouse_y: 0.5, mouse_y: 0.5,
mouse_down: 0.0, mouse_down: 0.0,

View File

@@ -300,7 +300,7 @@ pub(super) fn handle_engine_page(ctx: &mut InputContext, key: KeyEvent) -> Input
KeyCode::Char('t') if !ctx.app.plugin_mode => { KeyCode::Char('t') if !ctx.app.plugin_mode => {
let _ = ctx.audio_tx.load().send(AudioCommand::Evaluate { let _ = ctx.audio_tx.load().send(AudioCommand::Evaluate {
cmd: "/sound/sine/dur/0.5/decay/0.2".into(), cmd: "/sound/sine/dur/0.5/decay/0.2".into(),
time: None, tick: None,
}); });
} }
KeyCode::Char('s') => super::open_save(ctx), KeyCode::Char('s') => super::open_save(ctx),

View File

@@ -796,7 +796,7 @@ fn execute_palette_entry(
.load() .load()
.send(crate::engine::AudioCommand::Evaluate { .send(crate::engine::AudioCommand::Evaluate {
cmd: "/sound/sine/dur/0.5/decay/0.2".into(), cmd: "/sound/sine/dur/0.5/decay/0.2".into(),
time: None, tick: None,
}); });
} }
None => {} None => {}

View File

@@ -70,7 +70,7 @@ pub(super) fn handle_sample_explorer(ctx: &mut InputContext, key: KeyEvent) -> I
let _ = ctx let _ = ctx
.audio_tx .audio_tx
.load() .load()
.send(AudioCommand::Evaluate { cmd, time: None }); .send(AudioCommand::Evaluate { cmd, tick: None });
ctx.dispatch(AppCommand::SetStatus(format!( ctx.dispatch(AppCommand::SetStatus(format!(
"\u{25B8} {}/{}", "\u{25B8} {}/{}",
folder, entry.label folder, entry.label