storing the modulation amount in the NodeConfigurator / Matrix is now implemented
This commit is contained in:
parent
b48d423b5a
commit
196d094673
5 changed files with 115 additions and 24 deletions
|
@ -470,7 +470,7 @@ impl Matrix {
|
|||
let _ = self.sync();
|
||||
}
|
||||
|
||||
pub fn for_each_atom<F: FnMut(usize, ParamId, &SAtom)>(&self, f: F) {
|
||||
pub fn for_each_atom<F: FnMut(usize, ParamId, &SAtom, Option<f32>)>(&self, f: F) {
|
||||
self.config.for_each_param(f);
|
||||
}
|
||||
|
||||
|
@ -623,6 +623,17 @@ impl Matrix {
|
|||
self.config.set_param(param, at);
|
||||
}
|
||||
|
||||
/// Assign or remove modulation of an input parameter.
|
||||
pub fn set_param_modamt(&mut self, param: ParamId, modamt: Option<f32>)
|
||||
-> Result<(), MatrixError>
|
||||
{
|
||||
if self.config.set_param_modamt(param, modamt) {
|
||||
self.sync()
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_adjacent_output(&self, x: usize, y: usize, dir: CellDir)
|
||||
-> Option<(NodeId, u8)>
|
||||
{
|
||||
|
|
|
@ -142,7 +142,7 @@ impl PatternRepr {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct MatrixRepr {
|
||||
pub cells: Vec<CellRepr>,
|
||||
pub params: Vec<(ParamId, f32)>,
|
||||
pub params: Vec<(ParamId, f32, Option<f32>)>,
|
||||
pub atoms: Vec<(ParamId, SAtom)>,
|
||||
pub patterns: Vec<Option<PatternRepr>>,
|
||||
}
|
||||
|
@ -312,7 +312,9 @@ impl MatrixRepr {
|
|||
|
||||
if let Some(param_id) = param_id {
|
||||
m.params.push(
|
||||
(param_id, v[3].as_f64().unwrap_or(0.0) as f32));
|
||||
(param_id,
|
||||
v[3].as_f64().unwrap_or(0.0) as f32,
|
||||
v[4].as_f64().map(|v| v as f32)));
|
||||
} else {
|
||||
return Err(
|
||||
MatrixDeserError::UnknownParamId(v.to_string()));
|
||||
|
@ -358,14 +360,21 @@ impl MatrixRepr {
|
|||
|
||||
let mut params = json!([]);
|
||||
if let Value::Array(params) = &mut params {
|
||||
for (p, v) in self.params.iter() {
|
||||
params.push(
|
||||
json!([
|
||||
p.node_id().name(),
|
||||
p.node_id().instance(),
|
||||
p.name(),
|
||||
v
|
||||
]));
|
||||
for (p, v, ma) in self.params.iter() {
|
||||
let mut param_v = json!([
|
||||
p.node_id().name(),
|
||||
p.node_id().instance(),
|
||||
p.name(),
|
||||
v,
|
||||
]);
|
||||
|
||||
if let Value::Array(param_v) = &mut param_v {
|
||||
if let Some(ma) = ma {
|
||||
param_v.push(json!(ma));
|
||||
}
|
||||
}
|
||||
|
||||
params.push(param_v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,10 +53,11 @@ pub enum GraphMessage {
|
|||
/// and the NodeConfigurator.
|
||||
#[derive(Debug)]
|
||||
pub enum QuickMessage {
|
||||
AtomUpdate { at_idx: usize, value: SAtom },
|
||||
ParamUpdate { input_idx: usize, value: f32 },
|
||||
AtomUpdate { at_idx: usize, value: SAtom },
|
||||
ParamUpdate { input_idx: usize, value: f32 },
|
||||
ModamtUpdate { input_idx: usize, modamt: f32 },
|
||||
/// Sets the buffer indices to monitor with the FeedbackProcessor.
|
||||
SetMonitor { bufs: [usize; MON_SIG_CNT], },
|
||||
SetMonitor { bufs: [usize; MON_SIG_CNT], },
|
||||
}
|
||||
|
||||
pub const UNUSED_MONITOR_IDX : usize = 99999;
|
||||
|
|
|
@ -154,6 +154,8 @@ pub struct NodeConfigurator {
|
|||
params: std::collections::HashMap<ParamId, NodeInputParam>,
|
||||
/// Stores the most recently set parameter values
|
||||
param_values: std::collections::HashMap<ParamId, f32>,
|
||||
/// Stores the modulation amount of a parameter
|
||||
param_modamt: std::collections::HashMap<ParamId, Option<f32>>,
|
||||
/// Contains non automateable atom data for the nodes
|
||||
atoms: std::collections::HashMap<ParamId, NodeInputAtom>,
|
||||
/// Stores the most recently set atoms
|
||||
|
@ -241,6 +243,7 @@ impl NodeConfigurator {
|
|||
output_fb_cons: None,
|
||||
params: std::collections::HashMap::new(),
|
||||
param_values: std::collections::HashMap::new(),
|
||||
param_modamt: std::collections::HashMap::new(),
|
||||
atoms: std::collections::HashMap::new(),
|
||||
atom_values: std::collections::HashMap::new(),
|
||||
node2idx: HashMap::new(),
|
||||
|
@ -299,6 +302,47 @@ impl NodeConfigurator {
|
|||
self.nodes.get_mut(idx)
|
||||
}
|
||||
|
||||
/// Set the modulation amount of a parameter.
|
||||
/// Returns true if a new [NodeProg] needs to be created, which can be
|
||||
/// necessary if there was no modulation amount assigned to this parameter
|
||||
/// yet.
|
||||
pub fn set_param_modamt(&mut self, param: ParamId, v: Option<f32>) -> bool {
|
||||
if param.is_atom() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the modulation amount was already set, if not, we need
|
||||
// to reconstruct the graph and upload an updated NodeProg.
|
||||
if let Some(_old_modamt) =
|
||||
self.param_modamt.get(¶m).copied().flatten()
|
||||
{
|
||||
if v.is_none() {
|
||||
self.param_modamt.insert(param, v);
|
||||
true
|
||||
|
||||
} else {
|
||||
let modamt = v.unwrap();
|
||||
|
||||
self.param_modamt.insert(param, v);
|
||||
|
||||
if let Some(nparam) = self.params.get_mut(¶m) {
|
||||
let input_idx = nparam.input_idx;
|
||||
let _ =
|
||||
self.shared.quick_update_prod.push(
|
||||
QuickMessage::ModamtUpdate {
|
||||
input_idx, modamt
|
||||
});
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
} else {
|
||||
self.param_modamt.insert(param, v);
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// Assign [SAtom] values to input parameters and atoms.
|
||||
///
|
||||
/// Only updates the DSP backend if [NodeConfigurator::rebuild_node_ports] was called
|
||||
|
@ -356,12 +400,18 @@ impl NodeConfigurator {
|
|||
/// Most useful for serialization and saving patches.
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn dump_param_values(&self)
|
||||
-> (Vec<(ParamId, f32)>, Vec<(ParamId, SAtom)>)
|
||||
-> (Vec<(ParamId, f32, Option<f32>)>, Vec<(ParamId, SAtom)>)
|
||||
{
|
||||
let params : Vec<(ParamId, f32)> =
|
||||
let params : Vec<(ParamId, f32, Option<f32>)> =
|
||||
self.param_values
|
||||
.iter()
|
||||
.map(|(param_id, value)| (*param_id, *value))
|
||||
.map(|(param_id, value)|
|
||||
(*param_id,
|
||||
*value,
|
||||
self.param_modamt
|
||||
.get(param_id)
|
||||
.copied()
|
||||
.flatten()))
|
||||
.collect();
|
||||
|
||||
let atoms : Vec<(ParamId, SAtom)> =
|
||||
|
@ -376,10 +426,13 @@ impl NodeConfigurator {
|
|||
/// Loads parameter values from a dump. You will still need to upload
|
||||
/// a new [NodeProg] which contains these values.
|
||||
pub fn load_dumped_param_values(
|
||||
&mut self, params: &[(ParamId, f32)], atoms: &[(ParamId, SAtom)])
|
||||
&mut self,
|
||||
params: &[(ParamId, f32, Option<f32>)],
|
||||
atoms: &[(ParamId, SAtom)])
|
||||
{
|
||||
for (param_id, val) in params.iter() {
|
||||
for (param_id, val, modamt) in params.iter() {
|
||||
self.set_param(*param_id, (*val).into());
|
||||
self.set_param_modamt(*param_id, *modamt);
|
||||
}
|
||||
|
||||
for (param_id, val) in atoms.iter() {
|
||||
|
@ -389,12 +442,12 @@ impl NodeConfigurator {
|
|||
|
||||
/// Iterates over every parameter and calls the given function with
|
||||
/// it's current value.
|
||||
pub fn for_each_param<F: FnMut(usize, ParamId, &SAtom)>(&self, mut f: F) {
|
||||
pub fn for_each_param<F: FnMut(usize, ParamId, &SAtom, Option<f32>)>(&self, mut f: F) {
|
||||
for (_, node_input) in self.atoms.iter() {
|
||||
if let Some(unique_idx) =
|
||||
self.unique_index_for(&node_input.param_id.node_id())
|
||||
{
|
||||
f(unique_idx, node_input.param_id, &node_input.value);
|
||||
f(unique_idx, node_input.param_id, &node_input.value, None);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,8 +455,15 @@ impl NodeConfigurator {
|
|||
if let Some(unique_idx) =
|
||||
self.unique_index_for(&node_input.param_id.node_id())
|
||||
{
|
||||
let modamt =
|
||||
self.param_modamt
|
||||
.get(&node_input.param_id)
|
||||
.copied()
|
||||
.flatten();
|
||||
|
||||
f(unique_idx, node_input.param_id,
|
||||
&SAtom::param(node_input.value));
|
||||
&SAtom::param(node_input.value),
|
||||
modamt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -513,11 +573,15 @@ impl NodeConfigurator {
|
|||
/// The monitor data can be retrieved using
|
||||
/// [NodeConfigurator::get_minmax_monitor_samples].
|
||||
pub fn monitor(&mut self,
|
||||
node_id: &NodeId, inputs: &[Option<u8>], outputs: &[Option<u8>])
|
||||
node_id: &NodeId,
|
||||
inputs: &[Option<u8>],
|
||||
outputs: &[Option<u8>])
|
||||
{
|
||||
let mut bufs = [UNUSED_MONITOR_IDX; MON_SIG_CNT];
|
||||
|
||||
if let Some((_node_info, Some(node_instance))) = self.node_by_id(node_id) {
|
||||
if let Some((_node_info, Some(node_instance))) =
|
||||
self.node_by_id(node_id)
|
||||
{
|
||||
let mut i = 0;
|
||||
for inp_idx in inputs.iter().take(MON_SIG_CNT / 2) {
|
||||
if let Some(inp_idx) = inp_idx {
|
||||
|
@ -572,6 +636,7 @@ impl NodeConfigurator {
|
|||
self.nodes.fill_with(|| (NodeInfo::Nop, None));
|
||||
self.params .clear();
|
||||
self.param_values.clear();
|
||||
self.param_modamt.clear();
|
||||
self.atoms .clear();
|
||||
self.atom_values .clear();
|
||||
|
||||
|
|
|
@ -398,6 +398,11 @@ impl NodeExecutor {
|
|||
QuickMessage::ParamUpdate { input_idx, value } => {
|
||||
self.set_param(input_idx, value);
|
||||
},
|
||||
// TODO: MODAMT
|
||||
// QuickMessage::ModamtUpdate { input_idx, modamt } => {
|
||||
QuickMessage::ModamtUpdate { .. } => {
|
||||
// assign to NodeProg
|
||||
},
|
||||
QuickMessage::SetMonitor { bufs } => {
|
||||
self.monitor_signal_cur_inp_indices = bufs;
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue