diff --git a/plugins/crisp/src/lib.rs b/plugins/crisp/src/lib.rs index 09ce56e9..18774d7d 100644 --- a/plugins/crisp/src/lib.rs +++ b/plugins/crisp/src/lib.rs @@ -142,15 +142,15 @@ impl Default for Crisp { impl Default for CrispParams { #[allow(clippy::derivable_impls)] fn default() -> Self { - let f32_hz_then_khz = formatters::f32_hz_then_khz(0); - let from_f32_hz_then_khz = formatters::from_f32_hz_then_khz(); + let f32_hz_then_khz = formatters::v2s_f32_hz_then_khz(0); + let from_f32_hz_then_khz = formatters::s2v_f32_hz_then_khz(); Self { amount: FloatParam::new("Amount", 0.35, FloatRange::Linear { min: 0.0, max: 1.0 }) .with_smoother(SmoothingStyle::Linear(10.0)) .with_unit("%") - .with_value_to_string(formatters::f32_percentage(0)) - .with_string_to_value(formatters::from_f32_percentage()), + .with_value_to_string(formatters::v2s_f32_percentage(0)) + .with_string_to_value(formatters::s2v_f32_percentage()), mode: EnumParam::new("Mode", Mode::Crispy), stereo_mode: EnumParam::new("Stereo Mode", StereoMode::Stereo), @@ -190,7 +190,7 @@ impl Default for CrispParams { }, ) .with_smoother(SmoothingStyle::Logarithmic(100.0)) - .with_value_to_string(formatters::f32_rounded(2)), + .with_value_to_string(formatters::v2s_f32_rounded(2)), noise_hpf_freq: FloatParam::new( "Noise HP Frequency", MIN_FILTER_FREQUENCY, @@ -232,7 +232,7 @@ impl Default for CrispParams { }, ) .with_smoother(SmoothingStyle::Logarithmic(100.0)) - .with_value_to_string(formatters::f32_rounded(2)), + .with_value_to_string(formatters::v2s_f32_rounded(2)), noise_lpf_freq: FloatParam::new( "Noise LP Frequency", MAX_FILTER_FREQUENCY, @@ -268,7 +268,7 @@ impl Default for CrispParams { }, ) .with_smoother(SmoothingStyle::Logarithmic(100.0)) - .with_value_to_string(formatters::f32_rounded(2)), + .with_value_to_string(formatters::v2s_f32_rounded(2)), output_gain: FloatParam::new( "Output", diff --git a/plugins/diopser/src/lib.rs b/plugins/diopser/src/lib.rs index 2062a9f1..804ea310 100644 --- a/plugins/diopser/src/lib.rs +++ b/plugins/diopser/src/lib.rs @@ -171,8 +171,8 @@ impl DiopserParams { // This needs quite a bit of smoothing to avoid artifacts .with_smoother(SmoothingStyle::Logarithmic(100.0)) // This includes the unit - .with_value_to_string(formatters::f32_hz_then_khz(0)) - .with_string_to_value(formatters::from_f32_hz_then_khz()), + .with_value_to_string(formatters::v2s_f32_hz_then_khz(0)) + .with_string_to_value(formatters::s2v_f32_hz_then_khz()), filter_resonance: FloatParam::new( "Filter Resonance", // The actual default neutral Q-value would be `sqrt(2) / 2`, but this value @@ -185,7 +185,7 @@ impl DiopserParams { }, ) .with_smoother(SmoothingStyle::Logarithmic(100.0)) - .with_value_to_string(formatters::f32_rounded(2)), + .with_value_to_string(formatters::v2s_f32_rounded(2)), filter_spread_octaves: FloatParam::new( "Filter Spread Octaves", 0.0, @@ -215,8 +215,8 @@ impl DiopserParams { FloatRange::Linear { min: 0.0, max: 1.0 }, ) .with_unit("%") - .with_value_to_string(formatters::f32_percentage(0)) - .with_string_to_value(formatters::from_f32_percentage()), + .with_value_to_string(formatters::v2s_f32_percentage(0)) + .with_string_to_value(formatters::s2v_f32_percentage()), } } } diff --git a/plugins/examples/gain/src/lib.rs b/plugins/examples/gain/src/lib.rs index 1f56862a..6d77cc83 100644 --- a/plugins/examples/gain/src/lib.rs +++ b/plugins/examples/gain/src/lib.rs @@ -69,7 +69,7 @@ impl Default for GainParams { .with_unit(" dB") // This is actually redundant, because a step size of two decimal places already // causes the parameter to shown rounded - .with_value_to_string(formatters::f32_rounded(2)), + .with_value_to_string(formatters::v2s_f32_rounded(2)), // Persisted fields can be intialized like any other fields, and they'll keep their when // restoring the plugin's state. random_data: RwLock::new(Vec::new()), @@ -83,7 +83,7 @@ impl Default for GainParams { factor: FloatRange::skew_factor(2.0), }, ) - .with_value_to_string(formatters::f32_rounded(2)), + .with_value_to_string(formatters::v2s_f32_rounded(2)), sub_sub_params: SubSubParams { nope: FloatParam::new("Nope", 0.5, FloatRange::Linear { min: 1.0, max: 2.0 }), }, diff --git a/plugins/examples/sine/src/lib.rs b/plugins/examples/sine/src/lib.rs index 3414dfe1..1a51b5a9 100644 --- a/plugins/examples/sine/src/lib.rs +++ b/plugins/examples/sine/src/lib.rs @@ -71,8 +71,8 @@ impl Default for SineParams { .with_smoother(SmoothingStyle::Linear(10.0)) // We purposely don't specify a step size here, but the parameter should still be // displayed as if it were rounded. This formatter also includes the unit. - .with_value_to_string(formatters::f32_hz_then_khz(0)) - .with_string_to_value(formatters::from_f32_hz_then_khz()), + .with_value_to_string(formatters::v2s_f32_hz_then_khz(0)) + .with_string_to_value(formatters::s2v_f32_hz_then_khz()), use_midi: BoolParam::new("Use MIDI", false), } } diff --git a/plugins/puberty_simulator/src/lib.rs b/plugins/puberty_simulator/src/lib.rs index 518a2421..2f18d9c2 100644 --- a/plugins/puberty_simulator/src/lib.rs +++ b/plugins/puberty_simulator/src/lib.rs @@ -98,8 +98,8 @@ impl Default for PubertySimulator { impl Default for PubertySimulatorParams { fn default() -> Self { - let power_of_two_val2str = formatters::i32_power_of_two(); - let power_of_two_str2val = formatters::from_i32_power_of_two(); + let power_of_two_val2str = formatters::v2s_i32_power_of_two(); + let power_of_two_str2val = formatters::s2v_i32_power_of_two(); Self { pitch_octaves: FloatParam::new( @@ -116,7 +116,7 @@ impl Default for PubertySimulatorParams { // overlap-add, but sounds kind of slick .with_smoother(SmoothingStyle::Linear(100.0)) .with_unit(" Octaves") - .with_value_to_string(formatters::f32_rounded(2)), + .with_value_to_string(formatters::v2s_f32_rounded(2)), window_size_order: IntParam::new( "Window Size", diff --git a/src/formatters.rs b/src/formatters.rs index 75ef608e..30ef1b3b 100644 --- a/src/formatters.rs +++ b/src/formatters.rs @@ -1,24 +1,32 @@ -//! Convenience functions for formatting and parsing parameter values in common formats. +//! Convenience functions for formatting and parsing parameter values in various common formats. +//! +//! Functions prefixed with `v2s_` are meant to be used with the `.value_to_string()` parameter +//! fucntions, while the `s2v_` functions are meant to be used wit the `.string_to_value()`. +//! functions. Most of these formatters come as a pair. Check each formatter's documentation for any +//! additional usage information. use std::cmp::Ordering; use std::sync::Arc; use crate::util; +// TODO: The v2s and s2v naming convention isn't ideal, but at least it's unambiguous. Is there a +// better way to name these functions? Should we just split this up into two modules? + /// Round an `f32` value to always have a specific number of decimal digits. -pub fn f32_rounded(digits: usize) -> Arc String + Send + Sync> { +pub fn v2s_f32_rounded(digits: usize) -> Arc String + Send + Sync> { Arc::new(move |value| format!("{:.digits$}", value)) } /// Format a `[0, 1]` number as a percentage. Does not include the percent sign, you should specify /// this as the parameter's unit. -pub fn f32_percentage(digits: usize) -> Arc String + Send + Sync> { +pub fn v2s_f32_percentage(digits: usize) -> Arc String + Send + Sync> { Arc::new(move |value| format!("{:.digits$}", value * 100.0)) } /// Parse a `[0, 100]` percentage to a `[0, 1]` number. Handles the percentage unit for you. Used in -/// conjunction with [`f32_percentage`]. -pub fn from_f32_percentage() -> Arc Option + Send + Sync> { +/// conjunction with [`v2s_f32_percentage()`]. +pub fn s2v_f32_percentage() -> Arc Option + Send + Sync> { Arc::new(|string| { string .trim_end_matches(&[' ', '%']) @@ -29,14 +37,14 @@ pub fn from_f32_percentage() -> Arc Option + Send + Sync> { } /// Turn an `f32` value from voltage gain to decibels using the semantics described in -/// [`util::gain_to_db`]. You should use either `" dB"` or `" dBFS"` for the parameter's unit. -pub fn f32_gain_to_db(digits: usize) -> Arc String + Send + Sync> { +/// [`util::gain_to_db()]. You should use either `" dB"` or `" dBFS"` for the parameter's unit. +pub fn v2s_f32_gain_to_db(digits: usize) -> Arc String + Send + Sync> { Arc::new(move |value| format!("{:.digits$}", util::gain_to_db(value))) } /// Parse a decibel value to a linear voltage gain ratio. Handles the `dB` or `dBFS` units for you. -/// Used in conjunction with [`f32_gain_to_db()`]. -pub fn from_f32_gain_to_db() -> Arc Option + Send + Sync> { +/// Used in conjunction with [`v2s_f32_gain_to_db()`]. +pub fn s2v_f32_gain_to_db() -> Arc Option + Send + Sync> { Arc::new(|string| { string .trim_end_matches(&[' ', 'd', 'D', 'b', 'B', 'f', 'F', 's', 'S']) @@ -48,7 +56,7 @@ pub fn from_f32_gain_to_db() -> Arc Option + Send + Sync> { /// Turn an `f32` `[-1, 1]` value to a panning value where negative values are represented by /// `[100L, 1L]`, 0 gets turned into `C`, and positive values become `[1R, 100R]` values. -pub fn f32_panning() -> Arc String + Send + Sync> { +pub fn v2s_f32_panning() -> Arc String + Send + Sync> { Arc::new(move |value| match value.partial_cmp(&0.0) { Some(Ordering::Less) => format!("{:.0}L", value * -100.0), Some(Ordering::Equal) => String::from("C"), @@ -57,8 +65,9 @@ pub fn f32_panning() -> Arc String + Send + Sync> { }) } -/// Parse a pan value in the format of [`f32_panning`] to a linear value in the range `[-1, 1]`. -pub fn from_f32_panning() -> Arc Option + Send + Sync> { +/// Parse a pan value in the format of [`v2s_f32_panning()] to a linear value in the range `[-1, +/// 1]`. +pub fn s2v_f32_panning() -> Arc Option + Send + Sync> { Arc::new(|string| { let string = string.trim(); let cleaned_string = string.trim_end_matches(&[' ', 'l', 'L']).parse().ok(); @@ -73,7 +82,7 @@ pub fn from_f32_panning() -> Arc Option + Send + Sync> { /// Format a `f32` Hertz value as a rounded `Hz` below 1000 Hz, and as a rounded `kHz` value above /// 1000 Hz. This already includes the unit. -pub fn f32_hz_then_khz(digits: usize) -> Arc String + Send + Sync> { +pub fn v2s_f32_hz_then_khz(digits: usize) -> Arc String + Send + Sync> { Arc::new(move |value| { if value < 1000.0 { format!("{:.digits$} Hz", value) @@ -83,8 +92,8 @@ pub fn f32_hz_then_khz(digits: usize) -> Arc String + Send + Sync }) } -/// Convert an input in the same format at that of [`f32_hz_then_khz`] to a Hertz value. -pub fn from_f32_hz_then_khz() -> Arc Option + Send + Sync> { +/// Convert an input in the same format at that of [`v2s_f32_hz_then_khz()] to a Hertz value. +pub fn s2v_f32_hz_then_khz() -> Arc Option + Send + Sync> { Arc::new(move |string| { let string = string.trim(); let cleaned_string = string @@ -99,21 +108,21 @@ pub fn from_f32_hz_then_khz() -> Arc Option + Send + Sync> }) } -/// Format an order/power of two. Useful in conjunction with [`from_i32_power_of_two()`] to limit +/// Format an order/power of two. Useful in conjunction with [`s2v_i32_power_of_two()`] to limit /// integer parameter ranges to be only powers of two. -pub fn i32_power_of_two() -> Arc String + Send + Sync> { +pub fn v2s_i32_power_of_two() -> Arc String + Send + Sync> { Arc::new(|value| format!("{}", 1 << value)) } /// Parse a parameter input string to a power of two. Useful in conjunction with -/// [`i32_power_of_two()`] to limit integer parameter ranges to be only powers of two. -pub fn from_i32_power_of_two() -> Arc Option + Send + Sync> { +/// [`v2s_i32_power_of_two()`] to limit integer parameter ranges to be only powers of two. +pub fn s2v_i32_power_of_two() -> Arc Option + Send + Sync> { Arc::new(|string| string.parse().ok().map(|n: i32| (n as f32).log2() as i32)) } /// Turns an integer MIDI note number (usually in the range [0, 127]) into a note name, where 60 is /// C4 and 69 is A4 (nice). -pub fn i32_note_formatter() -> Arc String + Send + Sync> { +pub fn v2s_i32_note_formatter() -> Arc String + Send + Sync> { Arc::new(move |value| { let note_name = util::NOTES[value as usize % 12]; let octave = (value / 12) - 1; @@ -121,8 +130,8 @@ pub fn i32_note_formatter() -> Arc String + Send + Sync> { }) } -/// Parse a note name to a MIDI number using the inverse mapping from [`i32_note_formatter`]. -pub fn from_i32_note_formatter() -> Arc Option + Send + Sync> { +/// Parse a note name to a MIDI number using the inverse mapping from [`v2s_i32_note_formatter()]. +pub fn s2v_i32_note_formatter() -> Arc Option + Send + Sync> { Arc::new(|string| { let (note_name, octave) = string .trim() @@ -140,7 +149,7 @@ pub fn from_i32_note_formatter() -> Arc Option + Send + Syn /// Display 'Bypassed' or 'Not Bypassed' depending on whether the parameter is true or false. /// 'Enabled' would have also been a possibilty here, but that could be a bit confusing. -pub fn bool_bypass() -> Arc String + Send + Sync> { +pub fn v2s_bool_bypass() -> Arc String + Send + Sync> { Arc::new(move |value| { if value { String::from("Bypassed") @@ -150,8 +159,8 @@ pub fn bool_bypass() -> Arc String + Send + Sync> { }) } -/// Parse a string in the same format as [`bool_bypass`]. -pub fn from_bool_bypass() -> Arc Option + Send + Sync> { +/// Parse a string in the same format as [`v2s_bool_bypass()]. +pub fn s2v_bool_bypass() -> Arc Option + Send + Sync> { Arc::new(|string| { let string = string.trim(); if string.eq_ignore_ascii_case("bypass") {