Another round of optimization
This commit is contained in:
@@ -281,6 +281,8 @@ pub fn build_stream(
|
||||
|
||||
let (mut fft_producer, analysis_handle) = spawn_analysis_thread(sample_rate, spectrum_buffer);
|
||||
|
||||
let mut cmd_buffer = String::with_capacity(256);
|
||||
|
||||
let stream = device
|
||||
.build_output_stream(
|
||||
&stream_config,
|
||||
@@ -291,11 +293,16 @@ pub fn build_stream(
|
||||
while let Ok(cmd) = audio_rx.try_recv() {
|
||||
match cmd {
|
||||
AudioCommand::Evaluate { cmd, time } => {
|
||||
let cmd_with_time = match time {
|
||||
Some(t) => format!("{cmd}/time/{t:.6}"),
|
||||
None => cmd,
|
||||
let cmd_ref = match time {
|
||||
Some(t) => {
|
||||
cmd_buffer.clear();
|
||||
use std::fmt::Write;
|
||||
let _ = write!(&mut cmd_buffer, "{cmd}/time/{t:.6}");
|
||||
cmd_buffer.as_str()
|
||||
}
|
||||
None => &cmd,
|
||||
};
|
||||
engine.evaluate(&cmd_with_time);
|
||||
engine.evaluate(cmd_ref);
|
||||
}
|
||||
AudioCommand::Hush => {
|
||||
engine.hush();
|
||||
|
||||
@@ -555,6 +555,8 @@ pub(crate) struct SequencerState {
|
||||
speed_overrides: HashMap<(usize, usize), f64>,
|
||||
key_cache: KeyCache,
|
||||
buf_audio_commands: Vec<TimestampedCommand>,
|
||||
buf_activated: Vec<PatternId>,
|
||||
buf_stopped: Vec<PatternId>,
|
||||
cc_access: Option<Arc<dyn CcAccess>>,
|
||||
active_notes: HashMap<(u8, u8, u8), ActiveNote>,
|
||||
muted: std::collections::HashSet<(usize, usize)>,
|
||||
@@ -580,7 +582,9 @@ impl SequencerState {
|
||||
variables,
|
||||
speed_overrides: HashMap::new(),
|
||||
key_cache: KeyCache::new(),
|
||||
buf_audio_commands: Vec::new(),
|
||||
buf_audio_commands: Vec::with_capacity(32),
|
||||
buf_activated: Vec::with_capacity(16),
|
||||
buf_stopped: Vec::with_capacity(16),
|
||||
cc_access,
|
||||
active_notes: HashMap::new(),
|
||||
muted: std::collections::HashSet::new(),
|
||||
@@ -685,15 +689,8 @@ impl SequencerState {
|
||||
let beat = input.beat;
|
||||
let prev_beat = self.audio_state.prev_beat;
|
||||
|
||||
let activated = self.activate_pending(beat, prev_beat, input.quantum);
|
||||
self.audio_state
|
||||
.pending_starts
|
||||
.retain(|p| !activated.contains(&p.id));
|
||||
|
||||
let stopped = self.deactivate_pending(beat, prev_beat, input.quantum);
|
||||
self.audio_state
|
||||
.pending_stops
|
||||
.retain(|p| !stopped.contains(&p.id));
|
||||
self.activate_pending(beat, prev_beat, input.quantum);
|
||||
self.deactivate_pending(beat, prev_beat, input.quantum);
|
||||
|
||||
let steps = self.execute_steps(
|
||||
beat,
|
||||
@@ -713,7 +710,7 @@ impl SequencerState {
|
||||
input.mouse_down,
|
||||
);
|
||||
|
||||
let vars = self.read_variables(&steps.completed_iterations, &stopped, steps.any_step_fired);
|
||||
let vars = self.read_variables(&steps.completed_iterations, steps.any_step_fired);
|
||||
self.apply_chain_transitions(vars.chain_transitions);
|
||||
|
||||
self.audio_state.prev_beat = beat;
|
||||
@@ -746,8 +743,8 @@ impl SequencerState {
|
||||
}
|
||||
}
|
||||
|
||||
fn activate_pending(&mut self, beat: f64, prev_beat: f64, quantum: f64) -> Vec<PatternId> {
|
||||
let mut activated = Vec::new();
|
||||
fn activate_pending(&mut self, beat: f64, prev_beat: f64, quantum: f64) {
|
||||
self.buf_activated.clear();
|
||||
for pending in &self.audio_state.pending_starts {
|
||||
if check_quantization_boundary(pending.quantization, beat, prev_beat, quantum) {
|
||||
let start_step = match pending.sync_mode {
|
||||
@@ -773,24 +770,30 @@ impl SequencerState {
|
||||
iter: 0,
|
||||
},
|
||||
);
|
||||
activated.push(pending.id);
|
||||
self.buf_activated.push(pending.id);
|
||||
}
|
||||
}
|
||||
activated
|
||||
let activated = &self.buf_activated;
|
||||
self.audio_state
|
||||
.pending_starts
|
||||
.retain(|p| !activated.contains(&p.id));
|
||||
}
|
||||
|
||||
fn deactivate_pending(&mut self, beat: f64, prev_beat: f64, quantum: f64) -> Vec<PatternId> {
|
||||
let mut stopped = Vec::new();
|
||||
fn deactivate_pending(&mut self, beat: f64, prev_beat: f64, quantum: f64) {
|
||||
self.buf_stopped.clear();
|
||||
for pending in &self.audio_state.pending_stops {
|
||||
if check_quantization_boundary(pending.quantization, beat, prev_beat, quantum) {
|
||||
self.audio_state.active_patterns.remove(&pending.id);
|
||||
Arc::make_mut(&mut self.step_traces).retain(|&(bank, pattern, _), _| {
|
||||
bank != pending.id.bank || pattern != pending.id.pattern
|
||||
});
|
||||
stopped.push(pending.id);
|
||||
self.buf_stopped.push(pending.id);
|
||||
}
|
||||
}
|
||||
stopped
|
||||
let stopped = &self.buf_stopped;
|
||||
self.audio_state
|
||||
.pending_stops
|
||||
.retain(|p| !stopped.contains(&p.id));
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -876,6 +879,8 @@ impl SequencerState {
|
||||
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),
|
||||
#[cfg(feature = "desktop")]
|
||||
mouse_x,
|
||||
#[cfg(feature = "desktop")]
|
||||
@@ -931,9 +936,9 @@ impl SequencerState {
|
||||
fn read_variables(
|
||||
&self,
|
||||
completed: &[PatternId],
|
||||
stopped: &[PatternId],
|
||||
any_step_fired: bool,
|
||||
) -> VariableReads {
|
||||
let stopped = &self.buf_stopped;
|
||||
let needs_access = !completed.is_empty() || !stopped.is_empty() || any_step_fired;
|
||||
if !needs_access {
|
||||
return VariableReads {
|
||||
@@ -1208,10 +1213,18 @@ fn parse_midi_command(cmd: &str) -> Option<(MidiCommand, Option<f64>)> {
|
||||
if !cmd.starts_with("/midi/") {
|
||||
return None;
|
||||
}
|
||||
let parts: Vec<&str> = cmd.split('/').filter(|s| !s.is_empty()).collect();
|
||||
if parts.len() < 2 {
|
||||
let mut parts: [&str; 16] = [""; 16];
|
||||
let mut count = 0;
|
||||
for part in cmd.split('/').filter(|s| !s.is_empty()) {
|
||||
if count < 16 {
|
||||
parts[count] = part;
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
if count < 2 {
|
||||
return None;
|
||||
}
|
||||
let parts = &parts[..count];
|
||||
|
||||
let find_param = |key: &str| -> Option<&str> {
|
||||
parts
|
||||
|
||||
Reference in New Issue
Block a user