A ton of bug fixes

This commit is contained in:
2026-01-28 01:09:23 +01:00
parent a9ce70d292
commit 322885b908
13 changed files with 400 additions and 130 deletions

View File

@@ -1,14 +1,15 @@
use arc_swap::ArcSwap;
use crossbeam_channel::{bounded, Receiver, Sender, TrySendError};
use std::collections::HashMap;
use std::sync::atomic::AtomicI64;
use std::sync::Arc;
use std::thread::{self, JoinHandle};
use std::time::Duration;
use thread_priority::{set_current_thread_priority, ThreadPriority};
use super::LinkState;
use crate::model::{LaunchQuantization, SyncMode, MAX_BANKS, MAX_PATTERNS};
use crate::model::{Dictionary, ExecutionTrace, Rng, ScriptEngine, StepContext, Value, Variables};
use crate::model::{LaunchQuantization, SyncMode, MAX_BANKS, MAX_PATTERNS};
use crate::state::LiveKeyState;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
@@ -203,6 +204,7 @@ pub fn spawn_sequencer(
rng: Rng,
quantum: f64,
live_keys: Arc<LiveKeyState>,
nudge_us: Arc<AtomicI64>,
) -> (SequencerHandle, Receiver<AudioCommand>) {
let (cmd_tx, cmd_rx) = bounded::<SeqCommand>(64);
let (audio_tx, audio_rx) = bounded::<AudioCommand>(256);
@@ -226,6 +228,7 @@ pub fn spawn_sequencer(
quantum,
shared_state_clone,
live_keys,
nudge_us,
);
})
.expect("Failed to spawn sequencer thread");
@@ -356,6 +359,7 @@ fn sequencer_loop(
quantum: f64,
shared_state: Arc<ArcSwap<SharedSequencerState>>,
live_keys: Arc<LiveKeyState>,
nudge_us: Arc<AtomicI64>,
) {
use std::sync::atomic::Ordering;
@@ -432,12 +436,8 @@ fn sequencer_loop(
// Process pending starts with per-pattern quantization
let mut started_ids: Vec<PatternId> = Vec::new();
for pending in &audio_state.pending_starts {
let should_start = check_quantization_boundary(
pending.quantization,
beat,
prev_beat,
quantum,
);
let should_start =
check_quantization_boundary(pending.quantization, beat, prev_beat, quantum);
if should_start {
let start_step = match pending.sync_mode {
SyncMode::Reset => 0,
@@ -462,17 +462,15 @@ fn sequencer_loop(
started_ids.push(pending.id);
}
}
audio_state.pending_starts.retain(|p| !started_ids.contains(&p.id));
audio_state
.pending_starts
.retain(|p| !started_ids.contains(&p.id));
// Process pending stops with per-pattern quantization
let mut stopped_ids: Vec<PatternId> = Vec::new();
for pending in &audio_state.pending_stops {
let should_stop = check_quantization_boundary(
pending.quantization,
beat,
prev_beat,
quantum,
);
let should_stop =
check_quantization_boundary(pending.quantization, beat, prev_beat, quantum);
if should_stop {
audio_state.active_patterns.remove(&pending.id);
step_traces.retain(|&(bank, pattern, _), _| {
@@ -485,7 +483,9 @@ fn sequencer_loop(
stopped_ids.push(pending.id);
}
}
audio_state.pending_stops.retain(|p| !stopped_ids.contains(&p.id));
audio_state
.pending_stops
.retain(|p| !stopped_ids.contains(&p.id));
let mut chain_transitions: Vec<(PatternId, PatternId)> = Vec::new();
let mut chain_keys_to_remove: Vec<String> = Vec::new();
@@ -513,6 +513,7 @@ fn sequencer_loop(
let source_idx = pattern.resolve_source(step_idx);
let runs =
runs_counter.get_and_increment(active.bank, active.pattern, source_idx);
let nudge_secs = nudge_us.load(Ordering::Relaxed) as f64 / 1_000_000.0;
let ctx = StepContext {
step: step_idx,
beat,
@@ -525,6 +526,7 @@ fn sequencer_loop(
iter: active.iter,
speed: speed_mult,
fill: live_keys.fill(),
nudge_secs,
};
if let Some(script) = resolved_script {
let mut trace = ExecutionTrace::default();
@@ -582,15 +584,25 @@ fn sequencer_loop(
if let Some(Value::Str(s, _)) = vars.get(key) {
let parts: Vec<&str> = s.split(':').collect();
if parts.len() == 2 {
if let (Ok(b), Ok(p)) = (parts[0].parse::<usize>(), parts[1].parse::<usize>()) {
let target = PatternId { bank: b, pattern: p };
if let (Ok(b), Ok(p)) =
(parts[0].parse::<usize>(), parts[1].parse::<usize>())
{
let target = PatternId {
bank: b,
pattern: p,
};
// Extract bank/pattern from key: "__chain_{bank}_{pattern}__"
if let Some(rest) = key.strip_prefix("__chain_") {
if let Some(rest) = rest.strip_suffix("__") {
let kparts: Vec<&str> = rest.split('_').collect();
if kparts.len() == 2 {
if let (Ok(sb), Ok(sp)) = (kparts[0].parse::<usize>(), kparts[1].parse::<usize>()) {
let source = PatternId { bank: sb, pattern: sp };
if let (Ok(sb), Ok(sp)) =
(kparts[0].parse::<usize>(), kparts[1].parse::<usize>())
{
let source = PatternId {
bank: sb,
pattern: sp,
};
chain_transitions.push((source, target));
}
}