WIP: optimizations for linux

This commit is contained in:
2026-02-03 00:16:31 +01:00
parent 4235862d86
commit c283887ada
11 changed files with 64 additions and 54 deletions

View File

@@ -494,7 +494,6 @@ pub(crate) struct TickOutput {
}
struct StepResult {
completed_iterations: Vec<PatternId>,
any_step_fired: bool,
}
@@ -557,6 +556,7 @@ pub(crate) struct SequencerState {
buf_audio_commands: Vec<TimestampedCommand>,
buf_activated: Vec<PatternId>,
buf_stopped: Vec<PatternId>,
buf_completed_iterations: Vec<PatternId>,
cc_access: Option<Arc<dyn CcAccess>>,
active_notes: HashMap<(u8, u8, u8), ActiveNote>,
muted: std::collections::HashSet<(usize, usize)>,
@@ -580,11 +580,12 @@ impl SequencerState {
dropped_events: 0,
script_engine,
variables,
speed_overrides: HashMap::new(),
speed_overrides: HashMap::with_capacity(MAX_PATTERNS),
key_cache: KeyCache::new(),
buf_audio_commands: Vec::with_capacity(32),
buf_activated: Vec::with_capacity(16),
buf_stopped: Vec::with_capacity(16),
buf_completed_iterations: Vec::with_capacity(16),
cc_access,
active_notes: HashMap::new(),
muted: std::collections::HashSet::new(),
@@ -710,7 +711,7 @@ impl SequencerState {
input.mouse_down,
);
let vars = self.read_variables(&steps.completed_iterations, steps.any_step_fired);
let vars = self.read_variables(&self.buf_completed_iterations, steps.any_step_fired);
self.apply_chain_transitions(vars.chain_transitions);
self.audio_state.prev_beat = beat;
@@ -813,14 +814,14 @@ impl SequencerState {
#[cfg(feature = "desktop")] mouse_down: f64,
) -> StepResult {
self.buf_audio_commands.clear();
self.buf_completed_iterations.clear();
let mut result = StepResult {
completed_iterations: Vec::new(),
any_step_fired: false,
};
self.speed_overrides.clear();
{
let vars = self.variables.lock().unwrap();
let vars = self.variables.lock();
for id in self.audio_state.active_patterns.keys() {
let key = self.key_cache.speed_key(id.bank, id.pattern);
if let Some(v) = vars.get(key).and_then(|v| v.as_float().ok()) {
@@ -921,7 +922,7 @@ impl SequencerState {
let next_step = active.step_index + 1;
if next_step >= pattern.length {
active.iter += 1;
result.completed_iterations.push(PatternId {
self.buf_completed_iterations.push(PatternId {
bank: active.bank,
pattern: active.pattern,
});
@@ -947,7 +948,7 @@ impl SequencerState {
};
}
let mut vars = self.variables.lock().unwrap();
let mut vars = self.variables.lock();
let new_tempo = vars.remove("__tempo__").and_then(|v| v.as_float().ok());
let mut chain_transitions = Vec::new();
@@ -1073,7 +1074,7 @@ fn sequencer_loop(
let mut seq_state = SequencerState::new(variables, dict, rng, cc_access);
loop {
let mut commands = Vec::new();
let mut commands = Vec::with_capacity(8);
while let Ok(cmd) = cmd_rx.try_recv() {
if matches!(cmd, SeqCommand::Shutdown) {
return;
@@ -1205,7 +1206,16 @@ fn sequencer_loop(
shared_state.store(Arc::new(output.shared_state));
thread::sleep(Duration::from_micros(200));
// Adaptive sleep: calculate time until next substep boundary
// At max speed (8x), substeps occur every beat/32
// Sleep for most of that time, leaving 500μs margin for processing
let beats_per_sec = tempo / 60.0;
let max_speed = 8.0; // Maximum speed multiplier from speed.clamp()
let secs_per_substep = 1.0 / (beats_per_sec * 4.0 * max_speed);
let substep_us = (secs_per_substep * 1_000_000.0) as u64;
// Sleep for most of the substep duration, clamped to reasonable bounds
let sleep_us = substep_us.saturating_sub(500).clamp(50, 2000);
thread::sleep(Duration::from_micros(sleep_us));
}
}
@@ -1317,7 +1327,7 @@ fn parse_midi_command(cmd: &str) -> Option<(MidiCommand, Option<f64>)> {
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Mutex;
use parking_lot::Mutex;
fn make_state() -> SequencerState {
let variables: Variables = Arc::new(Mutex::new(HashMap::new()));
@@ -1497,7 +1507,7 @@ mod tests {
// Set chain variable
{
let mut vars = state.variables.lock().unwrap();
let mut vars = state.variables.lock();
vars.insert(
"__chain_0_0__".to_string(),
Value::Str(std::sync::Arc::from("0:1"), None),
@@ -1736,7 +1746,7 @@ mod tests {
// Set chain: 0:0 -> 0:1
{
let mut vars = state.variables.lock().unwrap();
let mut vars = state.variables.lock();
vars.insert(
"__chain_0_0__".to_string(),
Value::Str(std::sync::Arc::from("0:1"), None),
@@ -1979,7 +1989,7 @@ mod tests {
// Script fires at beat 1.0 (step 0). Set __tempo__ as if the script did.
{
let mut vars = state.variables.lock().unwrap();
let mut vars = state.variables.lock();
vars.insert("__tempo__".to_string(), Value::Float(140.0, None));
}