271 lines
7.8 KiB
Rust
271 lines
7.8 KiB
Rust
use super::harness::*;
|
|
|
|
#[test]
|
|
fn basic_emit() {
|
|
let outputs = expect_outputs(r#""kick" sound ."#, 1);
|
|
assert!(outputs[0].contains("sound/kick"));
|
|
}
|
|
|
|
#[test]
|
|
fn alias_s() {
|
|
let outputs = expect_outputs(r#""snare" snd ."#, 1);
|
|
assert!(outputs[0].contains("sound/snare"));
|
|
}
|
|
|
|
#[test]
|
|
fn with_params() {
|
|
let outputs = expect_outputs(r#""kick" snd 440 freq 0.5 gain ."#, 1);
|
|
assert!(outputs[0].contains("sound/kick"));
|
|
assert!(outputs[0].contains("freq/440"));
|
|
assert!(outputs[0].contains("gain/0.5"));
|
|
}
|
|
|
|
#[test]
|
|
fn auto_gate() {
|
|
let outputs = expect_outputs(r#""kick" snd ."#, 1);
|
|
assert!(outputs[0].contains("gate/"));
|
|
}
|
|
|
|
#[test]
|
|
fn auto_delaytime() {
|
|
let outputs = expect_outputs(r#""kick" snd ."#, 1);
|
|
assert!(outputs[0].contains("delaytime/"));
|
|
}
|
|
|
|
#[test]
|
|
fn emit_no_sound() {
|
|
expect_error(".", "nothing to emit");
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_emits() {
|
|
let outputs = expect_outputs(r#""kick" snd . "snare" snd ."#, 2);
|
|
assert!(outputs[0].contains("sound/kick"));
|
|
assert!(outputs[1].contains("sound/snare"));
|
|
}
|
|
|
|
#[test]
|
|
fn envelope_params() {
|
|
// Values are tempo-scaled: 0.01 * step_duration(0.125) = 0.00125, etc.
|
|
let outputs = expect_outputs(
|
|
r#""synth" snd 0.01 attack 0.1 decay 0.7 sustain 0.3 release ."#,
|
|
1,
|
|
);
|
|
assert!(outputs[0].contains("attack/0.00125"));
|
|
assert!(outputs[0].contains("decay/0.0125"));
|
|
assert!(outputs[0].contains("sustain/0.7"));
|
|
assert!(outputs[0].contains("release/0.0375"));
|
|
}
|
|
|
|
#[test]
|
|
fn filter_params() {
|
|
let outputs = expect_outputs(r#""synth" snd 2000 lpf 0.5 lpq ."#, 1);
|
|
assert!(outputs[0].contains("lpf/2000"));
|
|
assert!(outputs[0].contains("lpq/0.5"));
|
|
}
|
|
|
|
#[test]
|
|
fn adsr_sets_all_envelope_params() {
|
|
let outputs = expect_outputs(r#""synth" snd 0.01 0.1 0.5 0.3 adsr ."#, 1);
|
|
assert!(outputs[0].contains("attack/0.00125"));
|
|
assert!(outputs[0].contains("decay/0.0125"));
|
|
assert!(outputs[0].contains("sustain/0.5"));
|
|
assert!(outputs[0].contains("release/0.0375"));
|
|
}
|
|
|
|
#[test]
|
|
fn ad_sets_attack_decay_sustain_zero() {
|
|
let outputs = expect_outputs(r#""synth" snd 0.01 0.1 ad ."#, 1);
|
|
assert!(outputs[0].contains("attack/0.00125"));
|
|
assert!(outputs[0].contains("decay/0.0125"));
|
|
assert!(outputs[0].contains("sustain/0"));
|
|
}
|
|
|
|
#[test]
|
|
fn bank_param() {
|
|
let outputs = expect_outputs(r#""loop" snd "a" bank ."#, 1);
|
|
assert!(outputs[0].contains("sound/loop"));
|
|
assert!(outputs[0].contains("bank/a"));
|
|
}
|
|
|
|
#[test]
|
|
fn param_only_emit() {
|
|
let outputs = expect_outputs(r#"0 voice 880 freq ."#, 1);
|
|
assert!(outputs[0].contains("voice/0"));
|
|
assert!(outputs[0].contains("freq/880"));
|
|
assert!(!outputs[0].contains("sound/"));
|
|
assert!(outputs[0].contains("gate/"));
|
|
assert!(!outputs[0].contains("delaytime/"));
|
|
}
|
|
|
|
#[test]
|
|
fn param_only_multiple_params() {
|
|
let outputs = expect_outputs(r#"0 voice 440 freq 0.5 gain ."#, 1);
|
|
assert!(outputs[0].contains("voice/0"));
|
|
assert!(outputs[0].contains("freq/440"));
|
|
assert!(outputs[0].contains("gain/0.5"));
|
|
assert!(!outputs[0].contains("sound/"));
|
|
}
|
|
|
|
#[test]
|
|
fn polyphonic_notes() {
|
|
let outputs = expect_outputs(r#"60 64 67 note sine snd ."#, 3);
|
|
assert!(outputs[0].contains("note/60"));
|
|
assert!(outputs[1].contains("note/64"));
|
|
assert!(outputs[2].contains("note/67"));
|
|
}
|
|
|
|
#[test]
|
|
fn polyphonic_sounds() {
|
|
let outputs = expect_outputs(r#"440 freq kick hat snd ."#, 2);
|
|
assert!(outputs[0].contains("sound/kick"));
|
|
assert!(outputs[1].contains("sound/hat"));
|
|
}
|
|
|
|
#[test]
|
|
fn polyphonic_cycling() {
|
|
let outputs = expect_outputs(r#"60 64 67 note 0.5 1.0 gain sine snd ."#, 3);
|
|
assert!(outputs[0].contains("note/60"));
|
|
assert!(outputs[0].contains("gain/0.5"));
|
|
assert!(outputs[1].contains("note/64"));
|
|
assert!(outputs[1].contains("gain/1"));
|
|
assert!(outputs[2].contains("note/67"));
|
|
assert!(outputs[2].contains("gain/0.5"));
|
|
}
|
|
|
|
#[test]
|
|
fn polyphonic_with_at() {
|
|
let outputs = expect_outputs(r#"0 0.5 at 60 64 note sine snd ."#, 4);
|
|
assert_eq!(outputs.len(), 4);
|
|
}
|
|
|
|
#[test]
|
|
fn explicit_dur_zero_is_infinite() {
|
|
let outputs = expect_outputs("880 freq 0 gate .", 1);
|
|
assert!(outputs[0].contains("gate/0"));
|
|
}
|
|
|
|
#[test]
|
|
fn all_before_sounds() {
|
|
let outputs = expect_outputs(
|
|
r#"500 lpf 0.5 verb all "kick" snd 60 note . "hat" snd 70 note ."#,
|
|
2,
|
|
);
|
|
assert!(outputs[0].contains("sound/kick"));
|
|
assert!(outputs[0].contains("lpf/500"));
|
|
assert!(outputs[0].contains("verb/0.5"));
|
|
assert!(outputs[1].contains("sound/hat"));
|
|
assert!(outputs[1].contains("lpf/500"));
|
|
assert!(outputs[1].contains("verb/0.5"));
|
|
}
|
|
|
|
#[test]
|
|
fn all_after_sounds() {
|
|
let outputs = expect_outputs(
|
|
r#""kick" snd 60 note . "hat" snd 70 note . 500 lpf 0.5 verb all"#,
|
|
2,
|
|
);
|
|
assert!(outputs[0].contains("sound/kick"));
|
|
assert!(outputs[0].contains("lpf/500"));
|
|
assert!(outputs[0].contains("verb/0.5"));
|
|
assert!(outputs[1].contains("sound/hat"));
|
|
assert!(outputs[1].contains("lpf/500"));
|
|
assert!(outputs[1].contains("verb/0.5"));
|
|
}
|
|
|
|
#[test]
|
|
fn noall_clears_global_params() {
|
|
let outputs = expect_outputs(
|
|
r#"500 lpf all "kick" snd 60 note . noall "hat" snd 70 note ."#,
|
|
2,
|
|
);
|
|
assert!(outputs[0].contains("lpf/500"));
|
|
assert!(!outputs[1].contains("lpf/500"));
|
|
}
|
|
|
|
#[test]
|
|
fn all_with_tempo_scaled_params() {
|
|
// attack is tempo-scaled: 0.01 * step_duration(0.125) = 0.00125
|
|
let outputs = expect_outputs(
|
|
r#"0.01 attack all "kick" snd 60 note ."#,
|
|
1,
|
|
);
|
|
assert!(outputs[0].contains("attack/0.00125"));
|
|
}
|
|
|
|
#[test]
|
|
fn all_per_sound_override() {
|
|
let outputs = expect_outputs(
|
|
r#"500 lpf all "kick" snd 2000 lpf . "hat" snd ."#,
|
|
2,
|
|
);
|
|
// kick has both global lpf=500 and per-sound lpf=2000; per-sound wins (comes last)
|
|
assert!(outputs[0].contains("lpf/2000"));
|
|
// hat only has global lpf=500
|
|
assert!(outputs[1].contains("lpf/500"));
|
|
}
|
|
|
|
#[test]
|
|
fn all_persists_across_evaluations() {
|
|
let f = forth();
|
|
let ctx = default_ctx();
|
|
f.evaluate(r#"500 lpf 0.5 verb all"#, &ctx).unwrap();
|
|
let outputs = f.evaluate(r#""kick" snd 60 note ."#, &ctx).unwrap();
|
|
assert_eq!(outputs.len(), 1);
|
|
assert!(outputs[0].contains("lpf/500"), "global lpf missing: {}", outputs[0]);
|
|
assert!(outputs[0].contains("verb/0.5"), "global verb missing: {}", outputs[0]);
|
|
}
|
|
|
|
#[test]
|
|
fn noall_clears_across_evaluations() {
|
|
let f = forth();
|
|
let ctx = default_ctx();
|
|
f.evaluate(r#"500 lpf all"#, &ctx).unwrap();
|
|
f.evaluate(r#"noall"#, &ctx).unwrap();
|
|
let outputs = f.evaluate(r#""kick" snd 60 note ."#, &ctx).unwrap();
|
|
assert_eq!(outputs.len(), 1);
|
|
assert!(!outputs[0].contains("lpf"), "lpf should be cleared: {}", outputs[0]);
|
|
}
|
|
|
|
#[test]
|
|
fn rec() {
|
|
let outputs = expect_outputs(r#""loop1" rec"#, 1);
|
|
assert_eq!(outputs[0], "/doux/rec/loop1");
|
|
}
|
|
|
|
#[test]
|
|
fn overdub() {
|
|
let outputs = expect_outputs(r#""loop1" overdub"#, 1);
|
|
assert_eq!(outputs[0], "/doux/rec/loop1/overdub/1");
|
|
}
|
|
|
|
#[test]
|
|
fn overdub_alias_dub() {
|
|
let outputs = expect_outputs(r#""loop1" dub"#, 1);
|
|
assert_eq!(outputs[0], "/doux/rec/loop1/overdub/1");
|
|
}
|
|
|
|
#[test]
|
|
fn all_replaces_previous_global() {
|
|
let f = forth();
|
|
let ctx = default_ctx();
|
|
f.evaluate(r#"500 lpf 0.5 verb all"#, &ctx).unwrap();
|
|
f.evaluate(r#"2000 lpf all"#, &ctx).unwrap();
|
|
let outputs = f.evaluate(r#""kick" snd ."#, &ctx).unwrap();
|
|
assert_eq!(outputs.len(), 1);
|
|
assert!(outputs[0].contains("lpf/2000"), "latest lpf should be 2000: {}", outputs[0]);
|
|
}
|
|
|
|
#[test]
|
|
fn slice_param() {
|
|
let outputs = expect_outputs(r#""break" snd 8 slice ."#, 1);
|
|
assert!(outputs[0].contains("slice/8"));
|
|
}
|
|
|
|
#[test]
|
|
fn pick_param() {
|
|
let outputs = expect_outputs(r#""break" snd 8 slice 3 pick ."#, 1);
|
|
assert!(outputs[0].contains("slice/8"));
|
|
assert!(outputs[0].contains("pick/3"));
|
|
}
|