Add polyphonic modulation IDs to parameters
In a bit we should be able to use this with a new `PolyModulation` note event to allow polyphonic modulation.
This commit is contained in:
parent
7ea2851775
commit
992fcfe969
15
src/param.rs
15
src/param.rs
|
@ -60,6 +60,21 @@ pub trait Param: Display {
|
||||||
/// Get the unit label for this parameter, if any.
|
/// Get the unit label for this parameter, if any.
|
||||||
fn unit(&self) -> &'static str;
|
fn unit(&self) -> &'static str;
|
||||||
|
|
||||||
|
/// Get this parameter's polyphonic modulation ID. If this is set for a parameter in a CLAP
|
||||||
|
/// plugin, then polyphonic modulation will be enabled for that parameter. Polyphonic modulation
|
||||||
|
/// is sent through [`NoteEvent::PolyModulation][crate::prelude::NoteEvent::PolyModulation`]
|
||||||
|
/// events containing a **normalized** value for this parameter. This value must be converted to
|
||||||
|
/// a plain value using [`preview_plain()`][Self::preview_plain()] before it can be used. The
|
||||||
|
/// plugin should use this value in place of the parameter's normal (smoothed) value for the
|
||||||
|
/// affected note, and it should apply smooth to these values as necessary.
|
||||||
|
///
|
||||||
|
/// # Important
|
||||||
|
///
|
||||||
|
/// After enabling polyphonic modulation, the plugin **must** start sending
|
||||||
|
/// [`NoteEvent::VoiceTerminated`][crate::prelude::NoteEvent::VoiceEnd] events to the host when a voice
|
||||||
|
/// has fully ended. This allows the host to reuse its modulation resources.
|
||||||
|
fn poly_modulation_id(&self) -> Option<u32>;
|
||||||
|
|
||||||
/// Get the unnormalized value for this parameter.
|
/// Get the unnormalized value for this parameter.
|
||||||
fn plain_value(&self) -> Self::Plain;
|
fn plain_value(&self) -> Self::Plain;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,12 @@ pub struct BoolParam {
|
||||||
|
|
||||||
/// The parameter's human readable display name.
|
/// The parameter's human readable display name.
|
||||||
name: String,
|
name: String,
|
||||||
|
/// If this parameter has been marked as polyphonically modulatable, then this will be a unique
|
||||||
|
/// integer identifying the parameter. Because this value is determined by the plugin itself,
|
||||||
|
/// the plugin can easily map
|
||||||
|
/// [`NoteEvent::PolyModulation][crate::prelude::NoteEvent::PolyModulation`] events to the
|
||||||
|
/// correct parameter by pattern matching on a constant.
|
||||||
|
poly_modulation_id: Option<u32>,
|
||||||
/// Optional custom conversion function from a boolean value to a string.
|
/// Optional custom conversion function from a boolean value to a string.
|
||||||
value_to_string: Option<Arc<dyn Fn(bool) -> String + Send + Sync>>,
|
value_to_string: Option<Arc<dyn Fn(bool) -> String + Send + Sync>>,
|
||||||
/// Optional custom conversion function from a string to a boolean value. If the string cannot
|
/// Optional custom conversion function from a string to a boolean value. If the string cannot
|
||||||
|
@ -65,6 +71,10 @@ impl Param for BoolParam {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poly_modulation_id(&self) -> Option<u32> {
|
||||||
|
self.poly_modulation_id
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn plain_value(&self) -> Self::Plain {
|
fn plain_value(&self) -> Self::Plain {
|
||||||
self.value
|
self.value
|
||||||
|
@ -207,11 +217,27 @@ impl BoolParam {
|
||||||
value_changed: None,
|
value_changed: None,
|
||||||
|
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
|
poly_modulation_id: None,
|
||||||
value_to_string: None,
|
value_to_string: None,
|
||||||
string_to_value: None,
|
string_to_value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable polyphonic modulation for this parameter. The ID is used to uniquely identify this
|
||||||
|
/// parameter in [`NoteEvent::PolyModulation][crate::prelude::NoteEvent::PolyModulation`]
|
||||||
|
/// events, and must thus be unique between _all_ polyphonically modulatable parameters. See the
|
||||||
|
/// event's documentation for more information on how to use this.
|
||||||
|
///
|
||||||
|
/// # Important
|
||||||
|
///
|
||||||
|
/// After enabling polyphonic modulation, the plugin **must** start sending
|
||||||
|
/// [`NoteEvent::VoiceTerminated`][crate::prelude::NoteEvent::VoiceEnd] events to the host when
|
||||||
|
/// a voice has fully ended. This allows the host to reuse its modulation resources.
|
||||||
|
pub fn with_poly_modulation_id(mut self, id: u32) -> Self {
|
||||||
|
self.poly_modulation_id = Some(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Run a callback whenever this parameter's value changes. The argument passed to this function
|
/// Run a callback whenever this parameter's value changes. The argument passed to this function
|
||||||
/// is the parameter's new value. This should not do anything expensive as it may be called
|
/// is the parameter's new value. This should not do anything expensive as it may be called
|
||||||
/// 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
|
||||||
|
|
|
@ -117,6 +117,10 @@ impl<T: Enum + PartialEq> Param for EnumParam<T> {
|
||||||
self.inner.unit()
|
self.inner.unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poly_modulation_id(&self) -> Option<u32> {
|
||||||
|
self.inner.poly_modulation_id()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn plain_value(&self) -> Self::Plain {
|
fn plain_value(&self) -> Self::Plain {
|
||||||
T::from_index(self.inner.plain_value() as usize)
|
T::from_index(self.inner.plain_value() as usize)
|
||||||
|
@ -195,6 +199,10 @@ impl Param for EnumParamInner {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poly_modulation_id(&self) -> Option<u32> {
|
||||||
|
self.inner.poly_modulation_id()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn plain_value(&self) -> Self::Plain {
|
fn plain_value(&self) -> Self::Plain {
|
||||||
self.inner.plain_value()
|
self.inner.plain_value()
|
||||||
|
@ -326,6 +334,21 @@ impl<T: Enum + PartialEq + 'static> EnumParam<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable polyphonic modulation for this parameter. The ID is used to uniquely identify this
|
||||||
|
/// parameter in [`NoteEvent::PolyModulation][crate::prelude::NoteEvent::PolyModulation`]
|
||||||
|
/// events, and must thus be unique between _all_ polyphonically modulatable parameters. See the
|
||||||
|
/// event's documentation for more information on how to use this.
|
||||||
|
///
|
||||||
|
/// # Important
|
||||||
|
///
|
||||||
|
/// After enabling polyphonic modulation, the plugin **must** start sending
|
||||||
|
/// [`NoteEvent::VoiceTerminated`][crate::prelude::NoteEvent::VoiceEnd] events to the host when
|
||||||
|
/// a voice has fully ended. This allows the host to reuse its modulation resources.
|
||||||
|
pub fn with_poly_modulation_id(mut self, id: u32) -> Self {
|
||||||
|
self.inner.inner = self.inner.inner.with_poly_modulation_id(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Run a callback whenever this parameter's value changes. The argument passed to this function
|
/// Run a callback whenever this parameter's value changes. The argument passed to this function
|
||||||
/// is the parameter's new value. This should not do anything expensive as it may be called
|
/// is the parameter's new value. This should not do anything expensive as it may be called
|
||||||
/// 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
|
||||||
|
|
|
@ -64,6 +64,12 @@ pub struct FloatParam {
|
||||||
/// The parameter value's unit, added after [`value_to_string`][Self::value_to_string] if that
|
/// The parameter value's unit, added after [`value_to_string`][Self::value_to_string] if that
|
||||||
/// is set. NIH-plug will not automatically add a space before the unit.
|
/// is set. NIH-plug will not automatically add a space before the unit.
|
||||||
unit: &'static str,
|
unit: &'static str,
|
||||||
|
/// If this parameter has been marked as polyphonically modulatable, then this will be a unique
|
||||||
|
/// integer identifying the parameter. Because this value is determined by the plugin itself,
|
||||||
|
/// the plugin can easily map
|
||||||
|
/// [`NoteEvent::PolyModulation][crate::prelude::NoteEvent::PolyModulation`] events to the
|
||||||
|
/// correct parameter by pattern matching on a constant.
|
||||||
|
poly_modulation_id: Option<u32>,
|
||||||
/// Optional custom conversion function from a plain **unnormalized** value to a string.
|
/// Optional custom conversion function from a plain **unnormalized** value to a string.
|
||||||
value_to_string: Option<Arc<dyn Fn(f32) -> String + Send + Sync>>,
|
value_to_string: Option<Arc<dyn Fn(f32) -> 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
|
||||||
|
@ -99,6 +105,10 @@ impl Param for FloatParam {
|
||||||
self.unit
|
self.unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poly_modulation_id(&self) -> Option<u32> {
|
||||||
|
self.poly_modulation_id
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn plain_value(&self) -> Self::Plain {
|
fn plain_value(&self) -> Self::Plain {
|
||||||
self.value
|
self.value
|
||||||
|
@ -275,11 +285,26 @@ impl FloatParam {
|
||||||
step_size: None,
|
step_size: None,
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
unit: "",
|
unit: "",
|
||||||
|
poly_modulation_id: None,
|
||||||
value_to_string: None,
|
value_to_string: None,
|
||||||
string_to_value: None,
|
string_to_value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable polyphonic modulation for this parameter. The ID is used to uniquely identify this
|
||||||
|
/// parameter in [`NoteEvent::PolyModulation][crate::prelude::NoteEvent::PolyModulation`]
|
||||||
|
/// events, and must thus be unique between _all_ polyphonically modulatable parameters.
|
||||||
|
///
|
||||||
|
/// # Important
|
||||||
|
///
|
||||||
|
/// After enabling polyphonic modulation, the plugin **must** start sending
|
||||||
|
/// [`NoteEvent::VoiceTerminated`][crate::prelude::NoteEvent::VoiceEnd] events to the host when
|
||||||
|
/// a voice has fully ended. This allows the host to reuse its modulation resources.
|
||||||
|
pub fn with_poly_modulation_id(mut self, id: u32) -> Self {
|
||||||
|
self.poly_modulation_id = Some(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set up a smoother that can gradually interpolate changes made to this parameter, preventing
|
/// Set up a smoother that can gradually interpolate changes made to this parameter, preventing
|
||||||
/// clicks and zipper noises.
|
/// clicks and zipper noises.
|
||||||
pub fn with_smoother(mut self, style: SmoothingStyle) -> Self {
|
pub fn with_smoother(mut self, style: SmoothingStyle) -> Self {
|
||||||
|
|
|
@ -60,6 +60,12 @@ pub struct IntParam {
|
||||||
/// 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.
|
||||||
unit: &'static str,
|
unit: &'static str,
|
||||||
|
/// If this parameter has been marked as polyphonically modulatable, then this will be a unique
|
||||||
|
/// integer identifying the parameter. Because this value is determined by the plugin itself,
|
||||||
|
/// the plugin can easily map
|
||||||
|
/// [`NoteEvent::PolyModulation][crate::prelude::NoteEvent::PolyModulation`] events to the
|
||||||
|
/// correct parameter by pattern matching on a constant.
|
||||||
|
poly_modulation_id: Option<u32>,
|
||||||
/// Optional custom conversion function from a plain **unnormalized** value to a string.
|
/// Optional custom conversion function from a plain **unnormalized** value to a string.
|
||||||
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
|
||||||
|
@ -91,6 +97,10 @@ impl Param for IntParam {
|
||||||
self.unit
|
self.unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn poly_modulation_id(&self) -> Option<u32> {
|
||||||
|
self.poly_modulation_id
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn plain_value(&self) -> Self::Plain {
|
fn plain_value(&self) -> Self::Plain {
|
||||||
self.value
|
self.value
|
||||||
|
@ -239,11 +249,27 @@ impl IntParam {
|
||||||
range,
|
range,
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
unit: "",
|
unit: "",
|
||||||
|
poly_modulation_id: None,
|
||||||
value_to_string: None,
|
value_to_string: None,
|
||||||
string_to_value: None,
|
string_to_value: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable polyphonic modulation for this parameter. The ID is used to uniquely identify this
|
||||||
|
/// parameter in [`NoteEvent::PolyModulation][crate::prelude::NoteEvent::PolyModulation`]
|
||||||
|
/// events, and must thus be unique between _all_ polyphonically modulatable parameters. See the
|
||||||
|
/// event's documentation for more information on how to use this.
|
||||||
|
///
|
||||||
|
/// # Important
|
||||||
|
///
|
||||||
|
/// After enabling polyphonic modulation, the plugin **must** start sending
|
||||||
|
/// [`NoteEvent::VoiceTerminated`][crate::prelude::NoteEvent::VoiceEnd] events to the host when
|
||||||
|
/// a voice has fully ended. This allows the host to reuse its modulation resources.
|
||||||
|
pub fn with_poly_modulation_id(mut self, id: u32) -> Self {
|
||||||
|
self.poly_modulation_id = Some(id);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set up a smoother that can gradually interpolate changes made to this parameter, preventing
|
/// Set up a smoother that can gradually interpolate changes made to this parameter, preventing
|
||||||
/// clicks and zipper noises.
|
/// clicks and zipper noises.
|
||||||
pub fn with_smoother(mut self, style: SmoothingStyle) -> Self {
|
pub fn with_smoother(mut self, style: SmoothingStyle) -> Self {
|
||||||
|
|
|
@ -154,6 +154,7 @@ macro_rules! param_ptr_forward(
|
||||||
impl ParamPtr {
|
impl ParamPtr {
|
||||||
param_ptr_forward!(pub unsafe fn name(&self) -> &str);
|
param_ptr_forward!(pub unsafe fn name(&self) -> &str);
|
||||||
param_ptr_forward!(pub unsafe fn unit(&self) -> &'static str);
|
param_ptr_forward!(pub unsafe fn unit(&self) -> &'static str);
|
||||||
|
param_ptr_forward!(pub unsafe fn poly_modulation_id(&self) -> Option<u32>);
|
||||||
param_ptr_forward!(pub unsafe fn normalized_value(&self) -> f32);
|
param_ptr_forward!(pub unsafe fn normalized_value(&self) -> f32);
|
||||||
param_ptr_forward!(pub unsafe fn unmodulated_normalized_value(&self) -> f32);
|
param_ptr_forward!(pub unsafe fn unmodulated_normalized_value(&self) -> f32);
|
||||||
param_ptr_forward!(pub unsafe fn default_normalized_value(&self) -> f32);
|
param_ptr_forward!(pub unsafe fn default_normalized_value(&self) -> f32);
|
||||||
|
|
Loading…
Reference in a new issue