Feat: UI/UX and ducking compressor

This commit is contained in:
2026-02-24 02:57:27 +01:00
parent 848d0e773f
commit 2de49bdeba
24 changed files with 402 additions and 71 deletions

View File

@@ -338,3 +338,59 @@ fn arp_mixed_cycle_and_arp() {
assert!(approx_eq(notes[4], 67.0));
assert!(approx_eq(notes[5], 67.0));
}
// --- every+ / except+ tests ---
#[test]
fn every_offset_fires_at_offset() {
for iter in 0..8 {
let ctx = ctx_with(|c| c.iter = iter);
let f = forth();
let outputs = f.evaluate(r#""kick" s { . } 4 2 every+"#, &ctx).unwrap();
if iter % 4 == 2 {
assert_eq!(outputs.len(), 1, "iter={}: should fire", iter);
} else {
assert_eq!(outputs.len(), 0, "iter={}: should not fire", iter);
}
}
}
#[test]
fn every_offset_wraps_large_offset() {
// offset 6 with n=4 → 6 % 4 = 2, same as offset 2
for iter in 0..8 {
let ctx = ctx_with(|c| c.iter = iter);
let f = forth();
let outputs = f.evaluate(r#""kick" s { . } 4 6 every+"#, &ctx).unwrap();
if iter % 4 == 2 {
assert_eq!(outputs.len(), 1, "iter={}: should fire (wrapped offset)", iter);
} else {
assert_eq!(outputs.len(), 0, "iter={}: should not fire", iter);
}
}
}
#[test]
fn except_offset_inverse() {
for iter in 0..8 {
let ctx = ctx_with(|c| c.iter = iter);
let f = forth();
let outputs = f.evaluate(r#""kick" s { . } 4 2 except+"#, &ctx).unwrap();
if iter % 4 != 2 {
assert_eq!(outputs.len(), 1, "iter={}: should fire", iter);
} else {
assert_eq!(outputs.len(), 0, "iter={}: should not fire", iter);
}
}
}
#[test]
fn every_offset_zero_is_same_as_every() {
for iter in 0..8 {
let ctx = ctx_with(|c| c.iter = iter);
let f = forth();
let a = f.evaluate(r#""kick" s { . } 3 every"#, &ctx).unwrap();
let b = f.evaluate(r#""kick" s { . } 3 0 every+"#, &ctx).unwrap();
assert_eq!(a.len(), b.len(), "iter={}: every and every+ 0 should match", iter);
}
}