A ton of bug fixes
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user