storing the modulation amount in the NodeConfigurator / Matrix is now implemented

This commit is contained in:
Weird Constructor 2021-07-06 05:00:34 +02:00
parent b48d423b5a
commit 196d094673
5 changed files with 115 additions and 24 deletions

View file

@ -470,7 +470,7 @@ impl Matrix {
let _ = self.sync(); 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); self.config.for_each_param(f);
} }
@ -623,6 +623,17 @@ impl Matrix {
self.config.set_param(param, at); 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) pub fn get_adjacent_output(&self, x: usize, y: usize, dir: CellDir)
-> Option<(NodeId, u8)> -> Option<(NodeId, u8)>
{ {

View file

@ -142,7 +142,7 @@ impl PatternRepr {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MatrixRepr { pub struct MatrixRepr {
pub cells: Vec<CellRepr>, pub cells: Vec<CellRepr>,
pub params: Vec<(ParamId, f32)>, pub params: Vec<(ParamId, f32, Option<f32>)>,
pub atoms: Vec<(ParamId, SAtom)>, pub atoms: Vec<(ParamId, SAtom)>,
pub patterns: Vec<Option<PatternRepr>>, pub patterns: Vec<Option<PatternRepr>>,
} }
@ -312,7 +312,9 @@ impl MatrixRepr {
if let Some(param_id) = param_id { if let Some(param_id) = param_id {
m.params.push( 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 { } else {
return Err( return Err(
MatrixDeserError::UnknownParamId(v.to_string())); MatrixDeserError::UnknownParamId(v.to_string()));
@ -358,14 +360,21 @@ impl MatrixRepr {
let mut params = json!([]); let mut params = json!([]);
if let Value::Array(params) = &mut params { if let Value::Array(params) = &mut params {
for (p, v) in self.params.iter() { for (p, v, ma) in self.params.iter() {
params.push( let mut param_v = json!([
json!([
p.node_id().name(), p.node_id().name(),
p.node_id().instance(), p.node_id().instance(),
p.name(), p.name(),
v v,
])); ]);
if let Value::Array(param_v) = &mut param_v {
if let Some(ma) = ma {
param_v.push(json!(ma));
}
}
params.push(param_v);
} }
} }

View file

@ -55,6 +55,7 @@ pub enum GraphMessage {
pub enum QuickMessage { pub enum QuickMessage {
AtomUpdate { at_idx: usize, value: SAtom }, AtomUpdate { at_idx: usize, value: SAtom },
ParamUpdate { input_idx: usize, value: f32 }, ParamUpdate { input_idx: usize, value: f32 },
ModamtUpdate { input_idx: usize, modamt: f32 },
/// Sets the buffer indices to monitor with the FeedbackProcessor. /// Sets the buffer indices to monitor with the FeedbackProcessor.
SetMonitor { bufs: [usize; MON_SIG_CNT], }, SetMonitor { bufs: [usize; MON_SIG_CNT], },
} }

View file

@ -154,6 +154,8 @@ pub struct NodeConfigurator {
params: std::collections::HashMap<ParamId, NodeInputParam>, params: std::collections::HashMap<ParamId, NodeInputParam>,
/// Stores the most recently set parameter values /// Stores the most recently set parameter values
param_values: std::collections::HashMap<ParamId, f32>, 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 /// Contains non automateable atom data for the nodes
atoms: std::collections::HashMap<ParamId, NodeInputAtom>, atoms: std::collections::HashMap<ParamId, NodeInputAtom>,
/// Stores the most recently set atoms /// Stores the most recently set atoms
@ -241,6 +243,7 @@ impl NodeConfigurator {
output_fb_cons: None, output_fb_cons: None,
params: std::collections::HashMap::new(), params: std::collections::HashMap::new(),
param_values: std::collections::HashMap::new(), param_values: std::collections::HashMap::new(),
param_modamt: std::collections::HashMap::new(),
atoms: std::collections::HashMap::new(), atoms: std::collections::HashMap::new(),
atom_values: std::collections::HashMap::new(), atom_values: std::collections::HashMap::new(),
node2idx: HashMap::new(), node2idx: HashMap::new(),
@ -299,6 +302,47 @@ impl NodeConfigurator {
self.nodes.get_mut(idx) 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(&param).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(&param) {
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. /// Assign [SAtom] values to input parameters and atoms.
/// ///
/// Only updates the DSP backend if [NodeConfigurator::rebuild_node_ports] was called /// 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. /// Most useful for serialization and saving patches.
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub fn dump_param_values(&self) 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 self.param_values
.iter() .iter()
.map(|(param_id, value)| (*param_id, *value)) .map(|(param_id, value)|
(*param_id,
*value,
self.param_modamt
.get(param_id)
.copied()
.flatten()))
.collect(); .collect();
let atoms : Vec<(ParamId, SAtom)> = let atoms : Vec<(ParamId, SAtom)> =
@ -376,10 +426,13 @@ impl NodeConfigurator {
/// Loads parameter values from a dump. You will still need to upload /// Loads parameter values from a dump. You will still need to upload
/// a new [NodeProg] which contains these values. /// a new [NodeProg] which contains these values.
pub fn load_dumped_param_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(*param_id, (*val).into());
self.set_param_modamt(*param_id, *modamt);
} }
for (param_id, val) in atoms.iter() { for (param_id, val) in atoms.iter() {
@ -389,12 +442,12 @@ impl NodeConfigurator {
/// Iterates over every parameter and calls the given function with /// Iterates over every parameter and calls the given function with
/// it's current value. /// 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() { for (_, node_input) in self.atoms.iter() {
if let Some(unique_idx) = if let Some(unique_idx) =
self.unique_index_for(&node_input.param_id.node_id()) 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) = if let Some(unique_idx) =
self.unique_index_for(&node_input.param_id.node_id()) 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, 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 /// The monitor data can be retrieved using
/// [NodeConfigurator::get_minmax_monitor_samples]. /// [NodeConfigurator::get_minmax_monitor_samples].
pub fn monitor(&mut self, 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]; 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; let mut i = 0;
for inp_idx in inputs.iter().take(MON_SIG_CNT / 2) { for inp_idx in inputs.iter().take(MON_SIG_CNT / 2) {
if let Some(inp_idx) = inp_idx { if let Some(inp_idx) = inp_idx {
@ -572,6 +636,7 @@ impl NodeConfigurator {
self.nodes.fill_with(|| (NodeInfo::Nop, None)); self.nodes.fill_with(|| (NodeInfo::Nop, None));
self.params .clear(); self.params .clear();
self.param_values.clear(); self.param_values.clear();
self.param_modamt.clear();
self.atoms .clear(); self.atoms .clear();
self.atom_values .clear(); self.atom_values .clear();

View file

@ -398,6 +398,11 @@ impl NodeExecutor {
QuickMessage::ParamUpdate { input_idx, value } => { QuickMessage::ParamUpdate { input_idx, value } => {
self.set_param(input_idx, value); self.set_param(input_idx, value);
}, },
// TODO: MODAMT
// QuickMessage::ModamtUpdate { input_idx, modamt } => {
QuickMessage::ModamtUpdate { .. } => {
// assign to NodeProg
},
QuickMessage::SetMonitor { bufs } => { QuickMessage::SetMonitor { bufs } => {
self.monitor_signal_cur_inp_indices = bufs; self.monitor_signal_cur_inp_indices = bufs;
}, },