From 740868a10c3672e7c1845a8c3a7a431923707b22 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Tue, 1 Feb 2022 21:06:13 +0100 Subject: [PATCH] Move parameter ranges to their own module This module was too difficult to navigate with parameter types + ranges + implementation details. --- src/param.rs | 113 ++-------------------------------------- src/param/range.rs | 126 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 109 deletions(-) create mode 100644 src/param/range.rs diff --git a/src/param.rs b/src/param.rs index 1b6f9fd7..2648bc29 100644 --- a/src/param.rs +++ b/src/param.rs @@ -19,31 +19,16 @@ use std::fmt::Display; use std::sync::Arc; +use self::range::NormalizebleRange; + pub mod internals; +pub mod range; pub type FloatParam = PlainParam; pub type IntParam = PlainParam; pub use internals::Params; - -/// A distribution for a parameter's range. Probably need to add some forms of skewed ranges and -/// maybe a callback based implementation at some point. -#[derive(Debug)] -pub enum Range { - Linear { min: T, max: T }, -} - -/// A normalizable range for type `T`, where `self` is expected to be a type `R`. Higher kinded -/// types would have made this trait definition a lot clearer. -trait NormalizebleRange { - /// Normalize a plain, unnormalized value. Will be clamped to the bounds of the range if the - /// normalized value exceeds `[0, 1]`. - fn normalize(&self, plain: T) -> f32; - - /// Unnormalize a normalized value. Will be clamped to `[0, 1]` if the plain, unnormalized value - /// would exceed that range. - fn unnormalize(&self, normalized: f32) -> T; -} +pub use range::Range; /// Describes a single parmaetre of any type. pub trait Param { @@ -172,18 +157,6 @@ impl Default for BoolParam { } } -impl Default for Range { - fn default() -> Self { - Self::Linear { min: 0.0, max: 1.0 } - } -} - -impl Default for Range { - fn default() -> Self { - Self::Linear { min: 0, max: 1 } - } -} - macro_rules! impl_plainparam { ($ty:ident, $plain:ty) => { impl Param for $ty { @@ -336,81 +309,3 @@ impl Display for BoolParam { } } } - -impl NormalizebleRange for Range { - fn normalize(&self, plain: f32) -> f32 { - match &self { - Range::Linear { min, max } => (plain - min) / (max - min), - } - .clamp(0.0, 1.0) - } - - fn unnormalize(&self, normalized: f32) -> f32 { - let normalized = normalized.clamp(0.0, 1.0); - match &self { - Range::Linear { min, max } => (normalized * (max - min)) + min, - } - } -} - -impl NormalizebleRange for Range { - fn normalize(&self, plain: i32) -> f32 { - match &self { - Range::Linear { min, max } => (plain - min) as f32 / (max - min) as f32, - } - .clamp(0.0, 1.0) - } - - fn unnormalize(&self, normalized: f32) -> i32 { - let normalized = normalized.clamp(0.0, 1.0); - match &self { - Range::Linear { min, max } => (normalized * (max - min) as f32).round() as i32 + min, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - fn make_linear_float_range() -> Range { - Range::Linear { - min: 10.0, - max: 20.0, - } - } - - fn make_linear_int_range() -> Range { - Range::Linear { min: -10, max: 10 } - } - - #[test] - fn range_normalize_linear_float() { - let range = make_linear_float_range(); - assert_eq!(range.normalize(17.5), 0.75); - } - - #[test] - fn range_normalize_linear_int() { - let range = make_linear_int_range(); - assert_eq!(range.normalize(-5), 0.25); - } - - #[test] - fn range_unnormalize_linear_float() { - let range = make_linear_float_range(); - assert_eq!(range.unnormalize(0.25), 12.5); - } - - #[test] - fn range_unnormalize_linear_int() { - let range = make_linear_int_range(); - assert_eq!(range.unnormalize(0.75), 5); - } - - #[test] - fn range_unnormalize_linear_int_rounding() { - let range = make_linear_int_range(); - assert_eq!(range.unnormalize(0.73), 5); - } -} diff --git a/src/param/range.rs b/src/param/range.rs new file mode 100644 index 00000000..f5f2d002 --- /dev/null +++ b/src/param/range.rs @@ -0,0 +1,126 @@ +// nih-plug: plugins, but rewritten in Rust +// Copyright (C) 2022 Robbert van der Helm +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +//! Different ranges for numeric parameters. + +/// A distribution for a parameter's range. Probably need to add some forms of skewed ranges and +/// maybe a callback based implementation at some point. +#[derive(Debug)] +pub enum Range { + Linear { min: T, max: T }, +} + +/// A normalizable range for type `T`, where `self` is expected to be a type `R`. Higher kinded +/// types would have made this trait definition a lot clearer. +pub(crate) trait NormalizebleRange { + /// Normalize a plain, unnormalized value. Will be clamped to the bounds of the range if the + /// normalized value exceeds `[0, 1]`. + fn normalize(&self, plain: T) -> f32; + + /// Unnormalize a normalized value. Will be clamped to `[0, 1]` if the plain, unnormalized value + /// would exceed that range. + fn unnormalize(&self, normalized: f32) -> T; +} + +impl Default for Range { + fn default() -> Self { + Self::Linear { min: 0.0, max: 1.0 } + } +} + +impl Default for Range { + fn default() -> Self { + Self::Linear { min: 0, max: 1 } + } +} + +impl NormalizebleRange for Range { + fn normalize(&self, plain: f32) -> f32 { + match &self { + Range::Linear { min, max } => (plain - min) / (max - min), + } + .clamp(0.0, 1.0) + } + + fn unnormalize(&self, normalized: f32) -> f32 { + let normalized = normalized.clamp(0.0, 1.0); + match &self { + Range::Linear { min, max } => (normalized * (max - min)) + min, + } + } +} + +impl NormalizebleRange for Range { + fn normalize(&self, plain: i32) -> f32 { + match &self { + Range::Linear { min, max } => (plain - min) as f32 / (max - min) as f32, + } + .clamp(0.0, 1.0) + } + + fn unnormalize(&self, normalized: f32) -> i32 { + let normalized = normalized.clamp(0.0, 1.0); + match &self { + Range::Linear { min, max } => (normalized * (max - min) as f32).round() as i32 + min, + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_linear_float_range() -> Range { + Range::Linear { + min: 10.0, + max: 20.0, + } + } + + fn make_linear_int_range() -> Range { + Range::Linear { min: -10, max: 10 } + } + + #[test] + fn range_normalize_linear_float() { + let range = make_linear_float_range(); + assert_eq!(range.normalize(17.5), 0.75); + } + + #[test] + fn range_normalize_linear_int() { + let range = make_linear_int_range(); + assert_eq!(range.normalize(-5), 0.25); + } + + #[test] + fn range_unnormalize_linear_float() { + let range = make_linear_float_range(); + assert_eq!(range.unnormalize(0.25), 12.5); + } + + #[test] + fn range_unnormalize_linear_int() { + let range = make_linear_int_range(); + assert_eq!(range.unnormalize(0.75), 5); + } + + #[test] + fn range_unnormalize_linear_int_rounding() { + let range = make_linear_int_range(); + assert_eq!(range.unnormalize(0.73), 5); + } +}