Feat: optimizations

This commit is contained in:
2026-02-05 23:15:46 +01:00
parent 2c98a915fa
commit 51f52be4ce
22 changed files with 175 additions and 215 deletions

View File

@@ -140,7 +140,7 @@ pub struct PatternSnapshot {
pub struct StepSnapshot {
pub active: bool,
pub script: String,
pub source: Option<usize>,
pub source: Option<u8>,
}
#[derive(Clone, Copy, Default, Debug)]
@@ -392,7 +392,7 @@ impl PatternSnapshot {
for _ in 0..self.steps.len() {
if let Some(step) = self.steps.get(current) {
if let Some(source) = step.source {
current = source;
current = source as usize;
} else {
return current;
}
@@ -500,30 +500,32 @@ fn parse_chain_target(s: &str) -> Option<PatternId> {
})
}
struct KeyCache {
speed_keys: [[String; MAX_PATTERNS]; MAX_BANKS],
chain_keys: [[String; MAX_PATTERNS]; MAX_BANKS],
struct KeyBuf {
speed: String,
chain: String,
}
impl KeyCache {
impl KeyBuf {
fn new() -> Self {
Self {
speed_keys: std::array::from_fn(|bank| {
std::array::from_fn(|pattern| format!("__speed_{bank}_{pattern}__"))
}),
chain_keys: std::array::from_fn(|bank| {
std::array::from_fn(|pattern| format!("__chain_{bank}_{pattern}__"))
}),
speed: String::with_capacity(24),
chain: String::with_capacity(24),
}
}
}
fn speed_key(&self, bank: usize, pattern: usize) -> &str {
&self.speed_keys[bank][pattern]
}
fn format_speed_key(buf: &mut String, bank: usize, pattern: usize) -> &str {
use std::fmt::Write;
buf.clear();
write!(buf, "__speed_{bank}_{pattern}__").unwrap();
buf
}
fn chain_key(&self, bank: usize, pattern: usize) -> &str {
&self.chain_keys[bank][pattern]
}
fn format_chain_key(buf: &mut String, bank: usize, pattern: usize) -> &str {
use std::fmt::Write;
buf.clear();
write!(buf, "__chain_{bank}_{pattern}__").unwrap();
buf
}
pub(crate) struct SequencerState {
@@ -537,7 +539,7 @@ pub(crate) struct SequencerState {
variables: Variables,
dict: Dictionary,
speed_overrides: HashMap<(usize, usize), f64>,
key_cache: KeyCache,
key_buf: KeyBuf,
buf_audio_commands: Vec<TimestampedCommand>,
buf_activated: Vec<PatternId>,
buf_stopped: Vec<PatternId>,
@@ -566,7 +568,7 @@ impl SequencerState {
variables,
dict,
speed_overrides: HashMap::with_capacity(MAX_PATTERNS),
key_cache: KeyCache::new(),
key_buf: KeyBuf::new(),
buf_audio_commands: Vec::with_capacity(32),
buf_activated: Vec::with_capacity(16),
buf_stopped: Vec::with_capacity(16),
@@ -834,7 +836,7 @@ impl SequencerState {
{
let vars = self.variables.load();
for id in self.audio_state.active_patterns.keys() {
let key = self.key_cache.speed_key(id.bank, id.pattern);
let key = format_speed_key(&mut self.key_buf.speed, id.bank, id.pattern);
if let Some(v) = vars.get(key).and_then(|v: &Value| v.as_float().ok()) {
self.speed_overrides.insert((id.bank, id.pattern), v);
}
@@ -884,6 +886,8 @@ impl SequencerState {
active.pattern,
source_idx,
);
let speed_key = format_speed_key(&mut self.key_buf.speed, active.bank, active.pattern);
let chain_key = format_chain_key(&mut self.key_buf.chain, active.bank, active.pattern);
let ctx = StepContext {
step: step_idx,
beat: step_beat,
@@ -897,9 +901,9 @@ impl SequencerState {
speed: speed_mult,
fill,
nudge_secs,
cc_access: self.cc_access.clone(),
speed_key: self.key_cache.speed_key(active.bank, active.pattern),
chain_key: self.key_cache.chain_key(active.bank, active.pattern),
cc_access: self.cc_access.as_deref(),
speed_key,
chain_key,
#[cfg(feature = "desktop")]
mouse_x,
#[cfg(feature = "desktop")]
@@ -970,8 +974,9 @@ impl SequencerState {
.and_then(|v: &Value| v.as_float().ok());
let mut chain_transitions = Vec::new();
let mut buf = String::with_capacity(24);
for id in completed {
let chain_key = self.key_cache.chain_key(id.bank, id.pattern);
let chain_key = format_chain_key(&mut buf, id.bank, id.pattern);
if let Some(Value::Str(s, _)) = vars.get(chain_key) {
if let Some(target) = parse_chain_target(s) {
chain_transitions.push((*id, target));
@@ -980,24 +985,24 @@ impl SequencerState {
}
// Remove consumed variables (tempo and chain keys)
let needs_removal = new_tempo.is_some()
|| completed.iter().any(|id| {
let chain_key = self.key_cache.chain_key(id.bank, id.pattern);
vars.contains_key(chain_key)
})
|| stopped.iter().any(|id| {
let chain_key = self.key_cache.chain_key(id.bank, id.pattern);
vars.contains_key(chain_key)
});
let mut needs_removal = new_tempo.is_some();
if !needs_removal {
for id in completed.iter().chain(stopped.iter()) {
if vars.contains_key(format_chain_key(&mut buf, id.bank, id.pattern)) {
needs_removal = true;
break;
}
}
}
if needs_removal {
let mut new_vars = (**vars).clone();
new_vars.remove("__tempo__");
for id in completed {
new_vars.remove(self.key_cache.chain_key(id.bank, id.pattern));
new_vars.remove(format_chain_key(&mut buf, id.bank, id.pattern));
}
for id in stopped {
new_vars.remove(self.key_cache.chain_key(id.bank, id.pattern));
new_vars.remove(format_chain_key(&mut buf, id.bank, id.pattern));
}
self.variables.store(Arc::new(new_vars));
}