Open sessions whose plugin parameters were saved as null
JSON has no NaN or infinity, so serde writes them as null, and loading null into a plugin parameter failed the whole session with "not a SoundCraft session: invalid type: null, expected f32". One plugin reporting a non-finite value, or a value like 1e39 that overflows f32 in an edited file (it loads as infinity), made the session and every later save and autosave of it unopenable. Insert and instrument parameters that are null or overflow f32 are now dropped on load, so they keep the plugin's default and the rest of the session opens.
This commit is contained in:
parent
153381e03b
commit
54e3761d62
|
|
@ -425,7 +425,7 @@ pub enum Route {
|
|||
pub struct Insert {
|
||||
/// Registry id from `soundcraft-dsp` (e.g. `eq7`, `comp`).
|
||||
pub plugin: String,
|
||||
#[serde(default)]
|
||||
#[serde(default, deserialize_with = "finite_params")]
|
||||
pub params: BTreeMap<String, f32>,
|
||||
#[serde(default)]
|
||||
pub bypass: bool,
|
||||
|
|
@ -577,6 +577,13 @@ pub(crate) fn finite_or(v: f32, d: f32) -> f32 {
|
|||
if v.is_finite() { v } else { d }
|
||||
}
|
||||
|
||||
/// Parameters saved as `null` (how JSON writes NaN and infinity) or beyond `f32` are dropped, so
|
||||
/// they keep their defaults instead of failing the whole session.
|
||||
fn finite_params<'de, D: serde::Deserializer<'de>>(d: D) -> Result<BTreeMap<String, f32>, D::Error> {
|
||||
let params: BTreeMap<String, Option<f64>> = serde::Deserialize::deserialize(d)?;
|
||||
Ok(params.into_iter().filter_map(|(k, v)| Some((k, v.map(|v| v as f32).filter(|v| v.is_finite())?))).collect())
|
||||
}
|
||||
|
||||
/// Fader taper used by Pro Tools-style faders: position 0..1 ↔ dB (-inf..+12).
|
||||
pub fn fader_pos_to_db(pos: f32) -> f32 {
|
||||
let p = finite_or(pos, 0.0).clamp(0.0, 1.0);
|
||||
|
|
@ -624,6 +631,16 @@ mod tests {
|
|||
assert_eq!(bad.state_bytes(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn params_saved_as_null_or_out_of_range_are_dropped() {
|
||||
let mut i = Insert::new("eq_7band");
|
||||
i.params.extend([("gain".to_string(), f32::NAN), ("q".to_string(), 0.7)]);
|
||||
let back: Insert = serde_json::from_str(&serde_json::to_string(&i).unwrap()).unwrap();
|
||||
assert_eq!(back.params, BTreeMap::from([("q".to_string(), 0.7)]));
|
||||
let big: Insert = serde_json::from_str(r#"{"plugin":"x","params":{"gain":1e39,"q":0.5}}"#).unwrap();
|
||||
assert_eq!(big.params, BTreeMap::from([("q".to_string(), 0.5)]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fader_taper_round_trips() {
|
||||
for db in [-100.0f32, -60.0, -24.0, -10.0, 0.0, 6.0, 12.0] {
|
||||
|
|
|
|||
Loading…
Reference in New Issue