mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-27 12:06:51 -06:00
Reject missing or non-numeric values in mix.pan and mix.trim
Found while testing crates/engine/src/cmd/mix.rs:237 (pan); same pattern at mix.rs:76 (mix.trim) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
f3a19480d8
commit
4a4e82daba
@@ -73,7 +73,8 @@ pub fn specs() -> Vec<CommandSpec> {
|
||||
)),
|
||||
cmd!("mix.trim", "Input Trim", [], None, "{tracks?, db}", has_selection, |e, p| {
|
||||
let tracks = tracks_required(e, "mix.trim", p)?;
|
||||
let db = f32_or(p, "db", 0.0).clamp(-144.0, 24.0);
|
||||
let db = (p.get("db").and_then(Value::as_f64).filter(|v| v.is_finite()).ok_or_else(|| bad("mix.trim", "`db` (number) required"))? as f32)
|
||||
.clamp(-144.0, 24.0);
|
||||
let s = e.session_mut();
|
||||
for t in tracks {
|
||||
if let Some(tr) = s.track_mut(t) {
|
||||
@@ -234,7 +235,8 @@ fn volume(e: &mut Engine, p: &Value) -> Result<Value> {
|
||||
|
||||
fn pan(e: &mut Engine, p: &Value) -> Result<Value> {
|
||||
let tracks = tracks_required(e, "mix.pan", p)?;
|
||||
let v = f32_or(p, "pan", 0.0).clamp(-1.0, 1.0);
|
||||
let v = (p.get("pan").and_then(Value::as_f64).filter(|v| v.is_finite()).ok_or_else(|| bad("mix.pan", "`pan` (number) required"))? as f32)
|
||||
.clamp(-1.0, 1.0);
|
||||
let idx = i64_or(p, "index", 0).clamp(0, 1) as usize;
|
||||
let s = e.session_mut();
|
||||
for t in &tracks {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
use serde_json::json;
|
||||
use soundcraft_engine::{Engine, EngineError};
|
||||
|
||||
fn engine_with_kick() -> Engine {
|
||||
let mut e = Engine::default();
|
||||
e.execute("track.new", &json!({"name": "Kick", "format": "stereo"})).unwrap();
|
||||
e
|
||||
}
|
||||
|
||||
fn kick_pan(e: &Engine) -> Vec<f32> {
|
||||
e.session().tracks.iter().find(|t| t.name == "Kick").unwrap().mixer.pan.to_vec()
|
||||
}
|
||||
|
||||
fn kick_trim(e: &Engine) -> f32 {
|
||||
e.session().tracks.iter().find(|t| t.name == "Kick").unwrap().mixer.trim_db
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mix_pan_rejects_a_missing_or_non_numeric_pan_and_keeps_the_pan() {
|
||||
let mut e = engine_with_kick();
|
||||
e.execute("mix.pan", &json!({"tracks": ["Kick"], "pan": -1.0})).unwrap();
|
||||
assert_eq!(kick_pan(&e)[0], -1.0);
|
||||
|
||||
for params in [json!({"tracks": ["Kick"]}), json!({"tracks": ["Kick"], "pan": "left"}), json!({"tracks": ["Kick"], "pan": null})] {
|
||||
let r = e.execute("mix.pan", ¶ms);
|
||||
assert!(matches!(r, Err(EngineError::BadParams(..))), "{params}: expected BadParams, got {r:?}");
|
||||
assert_eq!(kick_pan(&e)[0], -1.0, "{params}: the pan must be untouched");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mix_trim_rejects_a_missing_or_non_numeric_db_and_keeps_the_trim() {
|
||||
let mut e = engine_with_kick();
|
||||
e.execute("mix.trim", &json!({"tracks": ["Kick"], "db": -6.0})).unwrap();
|
||||
assert_eq!(kick_trim(&e), -6.0);
|
||||
|
||||
for params in [json!({"tracks": ["Kick"]}), json!({"tracks": ["Kick"], "db": "loud"}), json!({"tracks": ["Kick"], "db": null})] {
|
||||
let r = e.execute("mix.trim", ¶ms);
|
||||
assert!(matches!(r, Err(EngineError::BadParams(..))), "{params}: expected BadParams, got {r:?}");
|
||||
assert_eq!(kick_trim(&e), -6.0, "{params}: the trim must be untouched");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user