A ton of bug fixes
This commit is contained in:
@@ -28,6 +28,7 @@ pub struct StepContext {
|
||||
pub iter: usize,
|
||||
pub speed: f64,
|
||||
pub fill: bool,
|
||||
pub nudge_secs: f64,
|
||||
}
|
||||
|
||||
impl StepContext {
|
||||
|
||||
@@ -86,7 +86,7 @@ impl Forth {
|
||||
|
||||
// Resolve root scope at end of script
|
||||
if let Some(scope) = scope_stack.pop() {
|
||||
resolve_scope(&scope, ctx.step_duration(), &mut outputs);
|
||||
resolve_scope(&scope, ctx.step_duration(), ctx.nudge_secs, &mut outputs);
|
||||
}
|
||||
|
||||
Ok(outputs)
|
||||
@@ -281,10 +281,20 @@ impl Forth {
|
||||
Op::Add => binary_op(stack, |a, b| a + b)?,
|
||||
Op::Sub => binary_op(stack, |a, b| a - b)?,
|
||||
Op::Mul => binary_op(stack, |a, b| a * b)?,
|
||||
Op::Div => binary_op(stack, |a, b| a / b)?,
|
||||
Op::Div => {
|
||||
let b = stack.pop().ok_or("stack underflow")?;
|
||||
let a = stack.pop().ok_or("stack underflow")?;
|
||||
if b.as_float().map_or(true, |v| v == 0.0) {
|
||||
return Err("division by zero".into());
|
||||
}
|
||||
stack.push(lift_binary(a, b, |x, y| x / y)?);
|
||||
}
|
||||
Op::Mod => {
|
||||
let b = stack.pop().ok_or("stack underflow")?;
|
||||
let a = stack.pop().ok_or("stack underflow")?;
|
||||
if b.as_float().map_or(true, |v| v == 0.0) {
|
||||
return Err("modulo by zero".into());
|
||||
}
|
||||
let result = lift_binary(a, b, |x, y| (x as i64 % y as i64) as f64)?;
|
||||
stack.push(result);
|
||||
}
|
||||
@@ -448,17 +458,19 @@ impl Forth {
|
||||
}
|
||||
|
||||
Op::Rand => {
|
||||
let max = stack.pop().ok_or("stack underflow")?;
|
||||
let min = stack.pop().ok_or("stack underflow")?;
|
||||
match (&min, &max) {
|
||||
(Value::Int(min_i, _), Value::Int(max_i, _)) => {
|
||||
let val = self.rng.lock().unwrap().gen_range(*min_i..=*max_i);
|
||||
let b = stack.pop().ok_or("stack underflow")?;
|
||||
let a = stack.pop().ok_or("stack underflow")?;
|
||||
match (&a, &b) {
|
||||
(Value::Int(a_i, _), Value::Int(b_i, _)) => {
|
||||
let (lo, hi) = if a_i <= b_i { (*a_i, *b_i) } else { (*b_i, *a_i) };
|
||||
let val = self.rng.lock().unwrap().gen_range(lo..=hi);
|
||||
stack.push(Value::Int(val, None));
|
||||
}
|
||||
_ => {
|
||||
let min_f = min.as_float()?;
|
||||
let max_f = max.as_float()?;
|
||||
let val = self.rng.lock().unwrap().gen_range(min_f..max_f);
|
||||
let a_f = a.as_float()?;
|
||||
let b_f = b.as_float()?;
|
||||
let (lo, hi) = if a_f <= b_f { (a_f, b_f) } else { (b_f, a_f) };
|
||||
let val = self.rng.lock().unwrap().gen_range(lo..hi);
|
||||
stack.push(Value::Float(val, None));
|
||||
}
|
||||
}
|
||||
@@ -545,7 +557,11 @@ impl Forth {
|
||||
}
|
||||
|
||||
Op::Pick => {
|
||||
let idx = stack.pop().ok_or("stack underflow")?.as_int()? as usize;
|
||||
let idx_i = stack.pop().ok_or("stack underflow")?.as_int()?;
|
||||
if idx_i < 0 {
|
||||
return Err(format!("pick index must be >= 0, got {}", idx_i));
|
||||
}
|
||||
let idx = idx_i as usize;
|
||||
let mut quots: Vec<Value> = Vec::new();
|
||||
while let Some(val) = stack.pop() {
|
||||
match &val {
|
||||
@@ -580,6 +596,9 @@ impl Forth {
|
||||
}
|
||||
|
||||
Op::Degree(pattern) => {
|
||||
if pattern.is_empty() {
|
||||
return Err("empty scale pattern".into());
|
||||
}
|
||||
let val = stack.pop().ok_or("stack underflow")?;
|
||||
let len = pattern.len() as i64;
|
||||
let result = lift_unary_int(val, |degree| {
|
||||
@@ -623,6 +642,9 @@ impl Forth {
|
||||
|
||||
Op::Loop => {
|
||||
let beats = stack.pop().ok_or("stack underflow")?.as_float()?;
|
||||
if ctx.tempo == 0.0 || ctx.speed == 0.0 {
|
||||
return Err("tempo and speed must be non-zero".into());
|
||||
}
|
||||
let dur = beats * 60.0 / ctx.tempo / ctx.speed;
|
||||
cmd.set_param("fit".into(), Value::Float(dur, None));
|
||||
cmd.set_param("dur".into(), Value::Float(dur, None));
|
||||
@@ -726,7 +748,7 @@ impl Forth {
|
||||
let child = scope_stack.pop().unwrap();
|
||||
|
||||
if child.stacked {
|
||||
resolve_scope(&child, ctx.step_duration(), outputs);
|
||||
resolve_scope(&child, ctx.step_duration(), ctx.nudge_secs, outputs);
|
||||
} else {
|
||||
let parent = scope_stack.last_mut().ok_or("scope stack underflow")?;
|
||||
let parent_slot = parent.claim_slot();
|
||||
@@ -763,7 +785,12 @@ impl Forth {
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_scope(scope: &ScopeContext, step_duration: f64, outputs: &mut Vec<String>) {
|
||||
fn resolve_scope(
|
||||
scope: &ScopeContext,
|
||||
step_duration: f64,
|
||||
nudge_secs: f64,
|
||||
outputs: &mut Vec<String>,
|
||||
) {
|
||||
let slot_dur = if scope.slot_count == 0 {
|
||||
scope.duration * scope.weight
|
||||
} else {
|
||||
@@ -814,6 +841,7 @@ fn resolve_scope(scope: &ScopeContext, step_duration: f64, outputs: &mut Vec<Str
|
||||
em.delta,
|
||||
em.dur,
|
||||
step_duration,
|
||||
nudge_secs,
|
||||
outputs,
|
||||
);
|
||||
}
|
||||
@@ -889,12 +917,14 @@ fn emit_output(
|
||||
delta: f64,
|
||||
dur: f64,
|
||||
step_duration: f64,
|
||||
nudge_secs: f64,
|
||||
outputs: &mut Vec<String>,
|
||||
) {
|
||||
let nudged_delta = delta + nudge_secs;
|
||||
let mut pairs = vec![("sound".into(), sound.to_string())];
|
||||
pairs.extend(params.iter().cloned());
|
||||
if delta > 0.0 {
|
||||
pairs.push(("delta".into(), delta.to_string()));
|
||||
if nudged_delta > 0.0 {
|
||||
pairs.push(("delta".into(), nudged_delta.to_string()));
|
||||
}
|
||||
if !pairs.iter().any(|(k, _)| k == "dur") {
|
||||
pairs.push(("dur".into(), dur.to_string()));
|
||||
|
||||
Reference in New Issue
Block a user