|
|
|
|
@@ -0,0 +1,193 @@
|
|
|
|
|
use super::harness::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ramp_at_beat_zero() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 0.0);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 2.0 ramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 0.0).abs() < 1e-9, "expected 0.0, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ramp_linear() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 0.5);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 1.0 ramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 0.5).abs() < 1e-9, "expected 0.5, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ramp_quadratic() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 0.5);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 2.0 ramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 0.25).abs() < 1e-9, "expected 0.25, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ramp_sqrt() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 0.25);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 0.5 ramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 0.5).abs() < 1e-9, "expected 0.5, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ramp_wraps() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 1.5);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 1.0 ramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 0.5).abs() < 1e-9, "expected 0.5, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ramp_freq_half() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 1.0);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("0.5 1.0 ramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 0.5).abs() < 1e-9, "expected 0.5, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ramp_underflow() {
|
|
|
|
|
expect_error("1.0 ramp", "stack underflow");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn range_mid() {
|
|
|
|
|
let ctx = default_ctx();
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("0.5 100.0 200.0 range", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 150.0).abs() < 1e-9, "expected 150.0, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn range_at_zero() {
|
|
|
|
|
let ctx = default_ctx();
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("0.0 100.0 200.0 range", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 100.0).abs() < 1e-9, "expected 100.0, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn range_at_one() {
|
|
|
|
|
let ctx = default_ctx();
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 100.0 200.0 range", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 200.0).abs() < 1e-9, "expected 200.0, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn range_underflow() {
|
|
|
|
|
expect_error("0.5 100.0 range", "stack underflow");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn linramp() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 0.5);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 linramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 0.5).abs() < 1e-9, "expected 0.5, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn expramp() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 0.5);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 expramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
let expected = 0.5_f64.powf(3.0);
|
|
|
|
|
assert!((val - expected).abs() < 1e-9, "expected {}, got {}", expected, val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn logramp() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 0.5);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 logramp", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
let expected = 0.5_f64.powf(0.3);
|
|
|
|
|
assert!((val - expected).abs() < 1e-9, "expected {}, got {}", expected, val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn ramp_with_range() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 0.5);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 1.0 ramp 200.0 800.0 range", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!((val - 500.0).abs() < 1e-9, "expected 500.0, got {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn noise_deterministic() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 2.7);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 noise", &ctx).unwrap();
|
|
|
|
|
let val1 = stack_float(&f);
|
|
|
|
|
f.evaluate("1.0 noise", &ctx).unwrap();
|
|
|
|
|
let val2 = stack_float(&f);
|
|
|
|
|
assert!((val1 - val2).abs() < 1e-9, "noise should be deterministic");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn noise_in_range() {
|
|
|
|
|
for i in 0..100 {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = i as f64 * 0.1);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 noise", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!(val >= 0.0 && val <= 1.0, "noise out of range: {}", val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn noise_varies() {
|
|
|
|
|
let ctx1 = ctx_with(|c| c.beat = 0.5);
|
|
|
|
|
let ctx2 = ctx_with(|c| c.beat = 1.5);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 noise", &ctx1).unwrap();
|
|
|
|
|
let val1 = stack_float(&f);
|
|
|
|
|
f.evaluate("1.0 noise", &ctx2).unwrap();
|
|
|
|
|
let val2 = stack_float(&f);
|
|
|
|
|
assert!((val1 - val2).abs() > 1e-9, "noise should vary with beat");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn noise_smooth() {
|
|
|
|
|
let f = forth();
|
|
|
|
|
let mut prev = 0.0;
|
|
|
|
|
for i in 0..100 {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = i as f64 * 0.01);
|
|
|
|
|
f.evaluate("1.0 noise", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
if i > 0 {
|
|
|
|
|
assert!((val - prev).abs() < 0.2, "noise not smooth: jump {} at step {}", (val - prev).abs(), i);
|
|
|
|
|
}
|
|
|
|
|
prev = val;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn noise_with_range() {
|
|
|
|
|
let ctx = ctx_with(|c| c.beat = 1.3);
|
|
|
|
|
let f = forth();
|
|
|
|
|
f.evaluate("1.0 noise 200.0 800.0 range", &ctx).unwrap();
|
|
|
|
|
let val = stack_float(&f);
|
|
|
|
|
assert!(val >= 200.0 && val <= 800.0, "noise+range out of bounds: {}", val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn noise_underflow() {
|
|
|
|
|
expect_error("noise", "stack underflow");
|
|
|
|
|
}
|