Give direct access to the node parameters via the Matrix struct

This commit is contained in:
Weird Constructor 2021-09-30 19:27:02 +02:00
parent dabb3ffa8e
commit 4128fc69a0
3 changed files with 69 additions and 7 deletions

View file

@ -2,7 +2,7 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later. // This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details. // See README.md and COPYING for details.
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq)]
pub enum SAtom { pub enum SAtom {
Str(String), Str(String),
MicroSample(Vec<f32>), MicroSample(Vec<f32>),

View file

@ -652,7 +652,7 @@ impl Matrix {
} }
/// Iterates through all atoms. This is useful for reading /// Iterates through all atoms. This is useful for reading
/// the atoms after a [MatrixRepr] has been loaded with [Matrix::from_repr]. /// all the atoms after a [MatrixRepr] has been loaded with [Matrix::from_repr].
pub fn for_each_atom<F: FnMut(usize, ParamId, &SAtom, Option<f32>)>(&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);
} }
@ -664,11 +664,7 @@ impl Matrix {
/// should update their knowledge of the nodes in the DSP /// should update their knowledge of the nodes in the DSP
/// graph. Such as parameter values. /// graph. Such as parameter values.
/// ///
/// HexoSynth for instance updates the UI parameters /// HexoSynth for instance updates the UI by tracking this value.
/// by tracking this value and calling [Matrix::for_each_atom]
/// to retrieve the most current set of parameter values.
/// In case new nodes were created and their default
/// parameter/atom values were added.
pub fn get_generation(&self) -> usize { self.gen_counter } pub fn get_generation(&self) -> usize { self.gen_counter }
/// Returns a serializable representation of the matrix. /// Returns a serializable representation of the matrix.
@ -790,6 +786,7 @@ impl Matrix {
/// assert_eq!(matrix2.get_prop("test").unwrap().i(), 31337); /// assert_eq!(matrix2.get_prop("test").unwrap().i(), 31337);
///``` ///```
pub fn set_prop(&mut self, key: &str, val: SAtom) { pub fn set_prop(&mut self, key: &str, val: SAtom) {
self.gen_counter += 1;
self.properties.insert(key.to_string(), val); self.properties.insert(key.to_string(), val);
} }
@ -848,9 +845,20 @@ impl Matrix {
self.config.pop_error() self.config.pop_error()
} }
/// Retrieve [SAtom] values for input parameters and atoms.
pub fn get_param(&self, param: &ParamId) -> Option<SAtom> {
self.config.get_param(param)
}
/// Assign [SAtom] values to input parameters and atoms. /// Assign [SAtom] values to input parameters and atoms.
pub fn set_param(&mut self, param: ParamId, at: SAtom) { pub fn set_param(&mut self, param: ParamId, at: SAtom) {
self.config.set_param(param, at); self.config.set_param(param, at);
self.gen_counter += 1;
}
/// Retrieve the modulation amount of the input parameter.
pub fn get_param_modamt(&self, param: &ParamId) -> Option<f32> {
self.config.get_param_modamt(param)
} }
/// Assign or remove modulation of an input parameter. /// Assign or remove modulation of an input parameter.
@ -858,8 +866,10 @@ impl Matrix {
-> Result<(), MatrixError> -> Result<(), MatrixError>
{ {
if self.config.set_param_modamt(param, modamt) { if self.config.set_param_modamt(param, modamt) {
// XXX: sync implicitly increases gen_counter!
self.sync() self.sync()
} else { } else {
self.gen_counter += 1;
Ok(()) Ok(())
} }
} }
@ -1548,4 +1558,40 @@ mod tests {
assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-2|1) in=(2-4|1) at=(0-0) mod=(1-3) cpy=(o0 => i2) mod=1)"); assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-2|1) in=(2-4|1) at=(0-0) mod=(1-3) cpy=(o0 => i2) mod=1)");
assert_eq!(prog.prog[2].to_string(), "Op(i=2 out=(2-3|0) in=(4-6|1) at=(0-0) mod=(3-3) cpy=(o1 => i4))"); assert_eq!(prog.prog[2].to_string(), "Op(i=2 out=(2-3|0) in=(4-6|1) at=(0-0) mod=(3-3) cpy=(o1 => i4))");
} }
#[test]
fn check_matrix_set_get() {
use crate::nodes::new_node_engine;
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
let pa1 = NodeId::Sin(1).param_by_idx(0).unwrap();
let pa2 = NodeId::Sin(1).param_by_idx(1).unwrap();
let pb1 = NodeId::Sin(2).param_by_idx(0).unwrap();
let pb2 = NodeId::Sin(2).param_by_idx(1).unwrap();
let px1 = NodeId::BOsc(1).param_by_idx(0).unwrap();
let px2 = NodeId::BOsc(1).param_by_idx(1).unwrap();
let gen1 = matrix.get_generation();
matrix.set_param(pa1, (0.75).into());
matrix.set_param(pa2, (0.50).into());
matrix.set_param(pb1, (0.25).into());
matrix.set_param(pb2, (0.20).into());
matrix.set_param(px1, (0.10).into());
matrix.set_param(px2, (0.13).into());
assert_eq!(matrix.get_generation(), gen1 + 6);
assert_eq!(matrix.get_param(&pa1), Some((0.75).into()));
let _ = matrix.set_param_modamt(pa2, Some(0.4));
let _ = matrix.set_param_modamt(pa1, Some(0.4));
let _ = matrix.set_param_modamt(pa1, None);
assert_eq!(matrix.get_generation(), gen1 + 9);
assert_eq!(matrix.get_param_modamt(&pa2), Some(0.4));
assert_eq!(matrix.get_param_modamt(&pa1), None);
}
} }

View file

@ -339,6 +339,13 @@ impl NodeConfigurator {
self.nodes.get_mut(idx) self.nodes.get_mut(idx)
} }
/// Returns the current modulation amount of the given parameter.
/// Returns `None` if no modulation amount if set and thus no
/// implicit attenuverter is set.
pub fn get_param_modamt(&self, param: &ParamId) -> Option<f32> {
self.param_modamt.get(&param).copied().flatten()
}
/// Set the modulation amount of a parameter. /// Set the modulation amount of a parameter.
/// Returns true if a new [NodeProg] needs to be created, which can be /// Returns true if a new [NodeProg] needs to be created, which can be
/// necessary if there was no modulation amount assigned to this parameter /// necessary if there was no modulation amount assigned to this parameter
@ -386,6 +393,15 @@ impl NodeConfigurator {
} }
} }
/// Retrieve [SAtom] values for input parameters and atoms.
pub fn get_param(&self, param: &ParamId) -> Option<SAtom> {
if param.is_atom() {
self.atom_values.get(param).cloned()
} else {
self.param_values.get(param).map(|v| (*v).into())
}
}
/// 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