What's wrong
NormalizedParameter<T>.Normalize (Semantics.Quantities/AudioEngineering/NormalizedParameter.cs ~L150-166) computes shaped as either:
Math.Log(v / lo) / Math.Log(hi / lo) for a logarithmic taper, or
(v - lo) / (hi - lo) for a linear taper.
It then relies on Math.Clamp(shaped, 0, 1), and the XML doc says "results outside [0, 1] are clamped". But Math.Clamp(NaN, …) returns NaN, and T.CreateChecked(NaN) throws for decimal.
Linear(min, max) doesn't validate that min != max, so a zero-width linear range reaches the same NaN path.
Reproduction
NormalizedParameter<double>.Logarithmic(20, 20000).Normalize(-5) -> NaN (Normalize(0) gives 0)
NormalizedParameter<double>.Linear(1, 1).Normalize(1) -> NaN
NormalizedParameter<decimal>.Logarithmic(20m, 20000m).Normalize(-5m) -> OverflowException
The type exists to give a plugin host a [0, 1] position, and NaN is exactly what an automation lane must not receive.
Suggested fix / acceptance criteria
- With a log taper, map a value where
v / lo <= 0 to the nearer end (0).
- Map a NaN
shaped to 0.
- For a degenerate range, either reject
min == max in Linear/Skewed, or return 0.
- Add tests for the three cases above.
What's wrong
NormalizedParameter<T>.Normalize(Semantics.Quantities/AudioEngineering/NormalizedParameter.cs~L150-166) computesshapedas either:Math.Log(v / lo) / Math.Log(hi / lo)for a logarithmic taper, or(v - lo) / (hi - lo)for a linear taper.It then relies on
Math.Clamp(shaped, 0, 1), and the XML doc says "results outside [0, 1] are clamped". ButMath.Clamp(NaN, …)returns NaN, andT.CreateChecked(NaN)throws fordecimal.Linear(min, max)doesn't validate thatmin != max, so a zero-width linear range reaches the same NaN path.Reproduction
The type exists to give a plugin host a
[0, 1]position, and NaN is exactly what an automation lane must not receive.Suggested fix / acceptance criteria
v / lo <= 0to the nearer end (0).shapedto 0.min == maxinLinear/Skewed, or return 0.