Store normalized values on the param structs
This will be necessary to implement CLAP modulation later.
This commit is contained in:
parent
54d2a4cd2c
commit
cd628e80ee
5 changed files with 100 additions and 39 deletions
|
@ -60,10 +60,7 @@ pub trait Param: Display {
|
||||||
fn plain_value(&self) -> Self::Plain;
|
fn plain_value(&self) -> Self::Plain;
|
||||||
|
|
||||||
/// Get the normalized `[0, 1]` value for this parameter.
|
/// Get the normalized `[0, 1]` value for this parameter.
|
||||||
#[inline]
|
fn normalized_value(&self) -> f32;
|
||||||
fn normalized_value(&self) -> f32 {
|
|
||||||
self.preview_normalized(self.plain_value())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the unnormalized default value for this parameter.
|
/// Get the unnormalized default value for this parameter.
|
||||||
fn default_plain_value(&self) -> Self::Plain;
|
fn default_plain_value(&self) -> Self::Plain;
|
||||||
|
@ -112,9 +109,7 @@ pub trait Param: Display {
|
||||||
/// continuous parameters (i.e. [`FloatParam`]).
|
/// continuous parameters (i.e. [`FloatParam`]).
|
||||||
///
|
///
|
||||||
/// This does **not** update the smoother.
|
/// This does **not** update the smoother.
|
||||||
fn set_normalized_value(&mut self, normalized: f32) {
|
fn set_normalized_value(&mut self, normalized: f32);
|
||||||
self.set_plain_value(self.preview_plain(normalized))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the string representation for a normalized value. Used as part of the wrappers. Most
|
/// Get the string representation for a normalized value. Used as part of the wrappers. Most
|
||||||
/// plugin formats already have support for units, in which case it shouldn't be part of this
|
/// plugin formats already have support for units, in which case it shouldn't be part of this
|
||||||
|
|
|
@ -9,8 +9,10 @@ use super::{Param, ParamFlags};
|
||||||
/// A simple boolean parameter.
|
/// A simple boolean parameter.
|
||||||
#[repr(C, align(4))]
|
#[repr(C, align(4))]
|
||||||
pub struct BoolParam {
|
pub struct BoolParam {
|
||||||
/// The field's current value. Should be initialized with the default value.
|
/// The field's current value.
|
||||||
pub value: bool,
|
pub value: bool,
|
||||||
|
/// The field's current value normalized to the `[0, 1]` range.
|
||||||
|
normalized_value: f32,
|
||||||
/// The field's default value.
|
/// The field's default value.
|
||||||
default: bool,
|
default: bool,
|
||||||
|
|
||||||
|
@ -37,6 +39,7 @@ impl Default for BoolParam {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: false,
|
value: false,
|
||||||
|
normalized_value: 0.0,
|
||||||
default: false,
|
default: false,
|
||||||
flags: ParamFlags::default(),
|
flags: ParamFlags::default(),
|
||||||
value_changed: None,
|
value_changed: None,
|
||||||
|
@ -73,6 +76,10 @@ impl Param for BoolParam {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn normalized_value(&self) -> f32 {
|
||||||
|
self.normalized_value
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default_plain_value(&self) -> Self::Plain {
|
fn default_plain_value(&self) -> Self::Plain {
|
||||||
self.default
|
self.default
|
||||||
|
@ -92,8 +99,17 @@ impl Param for BoolParam {
|
||||||
|
|
||||||
fn set_plain_value(&mut self, plain: Self::Plain) {
|
fn set_plain_value(&mut self, plain: Self::Plain) {
|
||||||
self.value = plain;
|
self.value = plain;
|
||||||
|
self.normalized_value = self.preview_normalized(plain);
|
||||||
if let Some(f) = &self.value_changed {
|
if let Some(f) = &self.value_changed {
|
||||||
f(plain);
|
f(self.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_normalized_value(&mut self, normalized: f32) {
|
||||||
|
self.value = self.preview_plain(normalized);
|
||||||
|
self.normalized_value = normalized;
|
||||||
|
if let Some(f) = &self.value_changed {
|
||||||
|
f(self.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,15 +71,14 @@ impl<T: Enum + PartialEq + Default> Default for EnumParam<T> {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: EnumParamInner {
|
inner: EnumParamInner {
|
||||||
inner: IntParam {
|
inner: IntParam::new(
|
||||||
value: T::default().to_index() as i32,
|
"",
|
||||||
default: T::default().to_index() as i32,
|
T::default().to_index() as i32,
|
||||||
range: IntRange::Linear {
|
IntRange::Linear {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: variants.len() as i32 - 1,
|
max: variants.len() as i32 - 1,
|
||||||
},
|
},
|
||||||
..Default::default()
|
),
|
||||||
},
|
|
||||||
variants,
|
variants,
|
||||||
},
|
},
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
|
@ -115,6 +114,11 @@ impl<T: Enum + PartialEq> Param for EnumParam<T> {
|
||||||
T::from_index(self.inner.plain_value() as usize)
|
T::from_index(self.inner.plain_value() as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalized_value(&self) -> f32 {
|
||||||
|
self.inner.normalized_value()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default_plain_value(&self) -> Self::Plain {
|
fn default_plain_value(&self) -> Self::Plain {
|
||||||
T::from_index(self.inner.default_plain_value() as usize)
|
T::from_index(self.inner.default_plain_value() as usize)
|
||||||
|
@ -136,6 +140,10 @@ impl<T: Enum + PartialEq> Param for EnumParam<T> {
|
||||||
self.inner.set_plain_value(T::to_index(plain) as i32)
|
self.inner.set_plain_value(T::to_index(plain) as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_normalized_value(&mut self, normalized: f32) {
|
||||||
|
self.inner.set_normalized_value(normalized)
|
||||||
|
}
|
||||||
|
|
||||||
fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String {
|
fn normalized_value_to_string(&self, normalized: f32, include_unit: bool) -> String {
|
||||||
self.inner
|
self.inner
|
||||||
.normalized_value_to_string(normalized, include_unit)
|
.normalized_value_to_string(normalized, include_unit)
|
||||||
|
@ -174,7 +182,7 @@ impl Param for EnumParamInner {
|
||||||
type Plain = i32;
|
type Plain = i32;
|
||||||
|
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
&self.inner.name
|
self.inner.name()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unit(&self) -> &'static str {
|
fn unit(&self) -> &'static str {
|
||||||
|
@ -186,6 +194,11 @@ impl Param for EnumParamInner {
|
||||||
self.inner.plain_value()
|
self.inner.plain_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalized_value(&self) -> f32 {
|
||||||
|
self.inner.normalized_value()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default_plain_value(&self) -> Self::Plain {
|
fn default_plain_value(&self) -> Self::Plain {
|
||||||
self.inner.default_plain_value()
|
self.inner.default_plain_value()
|
||||||
|
@ -207,6 +220,10 @@ impl Param for EnumParamInner {
|
||||||
self.inner.set_plain_value(plain)
|
self.inner.set_plain_value(plain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_normalized_value(&mut self, normalized: f32) {
|
||||||
|
self.inner.set_normalized_value(normalized)
|
||||||
|
}
|
||||||
|
|
||||||
fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {
|
fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {
|
||||||
let index = self.preview_plain(normalized);
|
let index = self.preview_plain(normalized);
|
||||||
self.variants[index as usize].to_string()
|
self.variants[index as usize].to_string()
|
||||||
|
@ -253,15 +270,14 @@ impl<T: Enum + PartialEq + 'static> EnumParam<T> {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: EnumParamInner {
|
inner: EnumParamInner {
|
||||||
inner: IntParam {
|
inner: IntParam::new(
|
||||||
value: T::to_index(default) as i32,
|
name,
|
||||||
range: IntRange::Linear {
|
T::to_index(default) as i32,
|
||||||
|
IntRange::Linear {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: variants.len() as i32 - 1,
|
max: variants.len() as i32 - 1,
|
||||||
},
|
},
|
||||||
name: name.into(),
|
),
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
variants,
|
variants,
|
||||||
},
|
},
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
|
@ -273,7 +289,7 @@ impl<T: Enum + PartialEq + 'static> EnumParam<T> {
|
||||||
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
||||||
/// thread.
|
/// thread.
|
||||||
pub fn with_callback(mut self, callback: Arc<dyn Fn(T) + Send + Sync>) -> Self {
|
pub fn with_callback(mut self, callback: Arc<dyn Fn(T) + Send + Sync>) -> Self {
|
||||||
self.inner.inner.value_changed = Some(Arc::new(move |value| {
|
self.inner.inner = self.inner.inner.with_callback(Arc::new(move |value| {
|
||||||
callback(T::from_index(value as usize))
|
callback(T::from_index(value as usize))
|
||||||
}));
|
}));
|
||||||
self
|
self
|
||||||
|
|
|
@ -21,10 +21,10 @@ use super::{Param, ParamFlags};
|
||||||
// a partially written to value here. We should probably reconsider this at some point though.
|
// a partially written to value here. We should probably reconsider this at some point though.
|
||||||
#[repr(C, align(4))]
|
#[repr(C, align(4))]
|
||||||
pub struct FloatParam {
|
pub struct FloatParam {
|
||||||
/// The field's current plain, unnormalized value. Should be initialized with the default value.
|
/// The field's current plain, unnormalized value.
|
||||||
/// Storing parameter values like this instead of in a single contiguous array is bad for cache
|
|
||||||
/// locality, but it does allow for a much nicer declarative API.
|
|
||||||
pub value: f32,
|
pub value: f32,
|
||||||
|
/// The field's current value normalized to the `[0, 1]` range.
|
||||||
|
normalized_value: f32,
|
||||||
/// The field's default plain, unnormalized value.
|
/// The field's default plain, unnormalized value.
|
||||||
default: f32,
|
default: f32,
|
||||||
/// An optional smoother that will automatically interpolate between the new automation values
|
/// An optional smoother that will automatically interpolate between the new automation values
|
||||||
|
@ -69,6 +69,7 @@ impl Default for FloatParam {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: 0.0,
|
value: 0.0,
|
||||||
|
normalized_value: 0.0,
|
||||||
default: 0.0,
|
default: 0.0,
|
||||||
smoothed: Smoother::none(),
|
smoothed: Smoother::none(),
|
||||||
flags: ParamFlags::default(),
|
flags: ParamFlags::default(),
|
||||||
|
@ -112,6 +113,11 @@ impl Param for FloatParam {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalized_value(&self) -> Self::Plain {
|
||||||
|
self.normalized_value
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default_plain_value(&self) -> Self::Plain {
|
fn default_plain_value(&self) -> Self::Plain {
|
||||||
self.default
|
self.default
|
||||||
|
@ -146,8 +152,17 @@ impl Param for FloatParam {
|
||||||
|
|
||||||
fn set_plain_value(&mut self, plain: Self::Plain) {
|
fn set_plain_value(&mut self, plain: Self::Plain) {
|
||||||
self.value = plain;
|
self.value = plain;
|
||||||
|
self.normalized_value = self.preview_normalized(plain);
|
||||||
if let Some(f) = &self.value_changed {
|
if let Some(f) = &self.value_changed {
|
||||||
f(plain);
|
f(self.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_normalized_value(&mut self, normalized: f32) {
|
||||||
|
self.value = self.preview_plain(normalized);
|
||||||
|
self.normalized_value = normalized;
|
||||||
|
if let Some(f) = &self.value_changed {
|
||||||
|
f(self.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +233,7 @@ impl FloatParam {
|
||||||
pub fn new(name: impl Into<String>, default: f32, range: FloatRange) -> Self {
|
pub fn new(name: impl Into<String>, default: f32, range: FloatRange) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: default,
|
value: default,
|
||||||
|
normalized_value: range.normalize(default),
|
||||||
default,
|
default,
|
||||||
range,
|
range,
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
|
|
|
@ -21,18 +21,18 @@ use super::{Param, ParamFlags};
|
||||||
// a partially written to value here. We should probably reconsider this at some point though.
|
// a partially written to value here. We should probably reconsider this at some point though.
|
||||||
#[repr(C, align(4))]
|
#[repr(C, align(4))]
|
||||||
pub struct IntParam {
|
pub struct IntParam {
|
||||||
/// The field's current plain, unnormalized value. Should be initialized with the default value.
|
/// The field's current plain, unnormalized value.
|
||||||
/// Storing parameter values like this instead of in a single contiguous array is bad for cache
|
|
||||||
/// locality, but it does allow for a much nicer declarative API.
|
|
||||||
pub value: i32,
|
pub value: i32,
|
||||||
|
/// The field's current value normalized to the `[0, 1]` range.
|
||||||
|
normalized_value: f32,
|
||||||
/// The field's default plain, unnormalized value.
|
/// The field's default plain, unnormalized value.
|
||||||
pub(crate) default: i32,
|
default: i32,
|
||||||
/// An optional smoother that will automatically interpolate between the new automation values
|
/// An optional smoother that will automatically interpolate between the new automation values
|
||||||
/// set by the host.
|
/// set by the host.
|
||||||
pub smoothed: Smoother<i32>,
|
pub smoothed: Smoother<i32>,
|
||||||
|
|
||||||
/// Flags to control the parameter's behavior. See [`ParamFlags`].
|
/// Flags to control the parameter's behavior. See [`ParamFlags`].
|
||||||
pub(crate) flags: ParamFlags,
|
flags: ParamFlags,
|
||||||
/// Optional callback for listening to value changes. The argument passed to this function is
|
/// Optional callback for listening to value changes. The argument passed to this function is
|
||||||
/// the parameter's new **plain** value. This should not do anything expensive as it may be
|
/// the parameter's new **plain** value. This should not do anything expensive as it may be
|
||||||
/// called multiple times in rapid succession.
|
/// called multiple times in rapid succession.
|
||||||
|
@ -41,30 +41,31 @@ pub struct IntParam {
|
||||||
/// parameters struct, move a clone of that `Arc` into this closure, and then modify that.
|
/// parameters struct, move a clone of that `Arc` into this closure, and then modify that.
|
||||||
///
|
///
|
||||||
/// TODO: We probably also want to pass the old value to this function.
|
/// TODO: We probably also want to pass the old value to this function.
|
||||||
pub(crate) value_changed: Option<Arc<dyn Fn(i32) + Send + Sync>>,
|
value_changed: Option<Arc<dyn Fn(i32) + Send + Sync>>,
|
||||||
|
|
||||||
/// The distribution of the parameter's values.
|
/// The distribution of the parameter's values.
|
||||||
pub(crate) range: IntRange,
|
range: IntRange,
|
||||||
/// The parameter's human readable display name.
|
/// The parameter's human readable display name.
|
||||||
pub(crate) name: String,
|
name: String,
|
||||||
/// The parameter value's unit, added after `value_to_string` if that is set. NIH-plug will not
|
/// The parameter value's unit, added after `value_to_string` if that is set. NIH-plug will not
|
||||||
/// automatically add a space before the unit.
|
/// automatically add a space before the unit.
|
||||||
pub(crate) unit: &'static str,
|
unit: &'static str,
|
||||||
/// Optional custom conversion function from a plain **unnormalized** value to a string.
|
/// Optional custom conversion function from a plain **unnormalized** value to a string.
|
||||||
pub(crate) value_to_string: Option<Arc<dyn Fn(i32) -> String + Send + Sync>>,
|
value_to_string: Option<Arc<dyn Fn(i32) -> String + Send + Sync>>,
|
||||||
/// Optional custom conversion function from a string to a plain **unnormalized** value. If the
|
/// Optional custom conversion function from a string to a plain **unnormalized** value. If the
|
||||||
/// string cannot be parsed, then this should return a `None`. If this happens while the
|
/// string cannot be parsed, then this should return a `None`. If this happens while the
|
||||||
/// parameter is being updated then the update will be canceled.
|
/// parameter is being updated then the update will be canceled.
|
||||||
///
|
///
|
||||||
/// The input string may or may not contain the unit, so you will need to be able to handle
|
/// The input string may or may not contain the unit, so you will need to be able to handle
|
||||||
/// that.
|
/// that.
|
||||||
pub(crate) string_to_value: Option<Arc<dyn Fn(&str) -> Option<i32> + Send + Sync>>,
|
string_to_value: Option<Arc<dyn Fn(&str) -> Option<i32> + Send + Sync>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for IntParam {
|
impl Default for IntParam {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: 0,
|
value: 0,
|
||||||
|
normalized_value: 0.0,
|
||||||
default: 0,
|
default: 0,
|
||||||
smoothed: Smoother::none(),
|
smoothed: Smoother::none(),
|
||||||
flags: ParamFlags::default(),
|
flags: ParamFlags::default(),
|
||||||
|
@ -98,10 +99,17 @@ impl Param for IntParam {
|
||||||
self.unit
|
self.unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn plain_value(&self) -> Self::Plain {
|
fn plain_value(&self) -> Self::Plain {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalized_value(&self) -> f32 {
|
||||||
|
self.normalized_value
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn default_plain_value(&self) -> Self::Plain {
|
fn default_plain_value(&self) -> Self::Plain {
|
||||||
self.default
|
self.default
|
||||||
}
|
}
|
||||||
|
@ -120,8 +128,17 @@ impl Param for IntParam {
|
||||||
|
|
||||||
fn set_plain_value(&mut self, plain: Self::Plain) {
|
fn set_plain_value(&mut self, plain: Self::Plain) {
|
||||||
self.value = plain;
|
self.value = plain;
|
||||||
|
self.normalized_value = self.preview_normalized(plain);
|
||||||
if let Some(f) = &self.value_changed {
|
if let Some(f) = &self.value_changed {
|
||||||
f(plain);
|
f(self.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_normalized_value(&mut self, normalized: f32) {
|
||||||
|
self.value = self.preview_plain(normalized);
|
||||||
|
self.normalized_value = normalized;
|
||||||
|
if let Some(f) = &self.value_changed {
|
||||||
|
f(self.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +197,7 @@ impl IntParam {
|
||||||
pub fn new(name: impl Into<String>, default: i32, range: IntRange) -> Self {
|
pub fn new(name: impl Into<String>, default: i32, range: IntRange) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: default,
|
value: default,
|
||||||
|
normalized_value: range.normalize(default),
|
||||||
default,
|
default,
|
||||||
range,
|
range,
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue