finished AD tests and added preliminary graph impl

This commit is contained in:
Weird Constructor 2021-06-18 03:58:00 +02:00
parent 32dd6468a8
commit e13cf0834e
4 changed files with 106 additions and 9 deletions

View file

@ -59,8 +59,9 @@ pub const MAX_BLOCK_SIZE : usize = 128;
/// This trait is an interface between the graph functions
/// and the AtomDataModel of the UI.
pub trait GraphAtomData {
fn get(&self, node_id: usize, param_idx: u32) -> Option<SAtom>;
fn get_denorm(&self, node_id: usize, param_idx: u32) -> f32;
fn get(&self, param_idx: u32) -> Option<SAtom>;
fn get_denorm(&self, param_idx: u32) -> f32;
fn get_norm(&self, param_idx: u32) -> f32;
}
pub type GraphFun = Box<dyn FnMut(&dyn GraphAtomData, bool, f32) -> f32>;

View file

@ -3,7 +3,10 @@
// See README.md and COPYING for details.
use crate::nodes::{NodeAudioContext, NodeExecContext};
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
use crate::dsp::{
NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals,
GraphAtomData, GraphFun,
};
use super::helpers::{Trigger, TrigSignal, sqrt4_to_pow4};
#[macro_export]
@ -230,4 +233,18 @@ impl DspNode for Ad {
ctx_vals[0].set(self.value as f32);
// ctx_vals[1].set(self.phase / self. + self.stage * );
}
fn graph_fun() -> Option<GraphFun> {
Some(Box::new(|gd: &dyn GraphAtomData, _init: bool, x: f32| -> f32 {
let atk_idx = NodeId::Ad(0).inp_param("atk").unwrap().inp();
let dcy_idx = NodeId::Ad(0).inp_param("dcy").unwrap().inp();
let ashp_idx = NodeId::Ad(0).inp_param("ashp").unwrap().inp();
let dshp_idx = NodeId::Ad(0).inp_param("dshp").unwrap().inp();
let ashp = gd.get_denorm(ashp_idx as u32);
let v = sqrt4_to_pow4(x * gd.get_norm(atk_idx as u32), ashp);
v
}))
}
}

View file

@ -162,6 +162,38 @@ assertion failed: `(left[{}] == right[{}])`
}
}
#[macro_export]
macro_rules! assert_decimated_slope_feq_fine {
($vec:expr, $decimate:expr, $cmp_vec:expr) => {
let cmp_vec = $cmp_vec;
let mut res : Vec<f32> = vec![];
let mut prev = 0.0;
for (i, s) in $vec.iter().enumerate() {
let delta = *s - prev;
if i > 0 {
res.push(delta);
}
prev = *s;
}
let res : Vec<f32> = res.iter().step_by($decimate).copied().collect();
for (i, (s, scmp)) in res.iter().zip(cmp_vec.iter()).enumerate() {
if (s - scmp).abs() > 0.0000001 {
panic!(r#"
table_left: {:?}
table_right: {:?}
assertion failed: `(left[{}] == right[{}])`
left: `{:?}`,
right: `{:?}`"#, &res[i..], &(cmp_vec[i..]), i, i, s, scmp)
}
}
}
}
#[macro_export]
macro_rules! assert_rmsmima {
($rms:expr, $b:expr) => {

View file

@ -256,9 +256,8 @@ fn check_node_ad_shp_exp() {
]);
}
#[test]
fn check_node_ad_trig_out() {
fn check_node_ad_eoet() {
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
@ -274,10 +273,7 @@ fn check_node_ad_trig_out() {
.input(out.inp("ch2"), None, None));
matrix.sync().unwrap();
let trig_p = ad.inp_param("trig").unwrap();
pset_n(&mut matrix, ad, "trig", 1.0);
let res = run_for_ms(&mut node_exec, 25.0);
// just make sure we are running an env:
assert_decimated_slope_feq!(res.0, 50, vec![
@ -308,7 +304,7 @@ fn check_node_ad_trig_out() {
#[test]
fn check_node_ad_atk() {
fn check_node_ad_atk_dcy() {
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
@ -346,4 +342,55 @@ fn check_node_ad_atk() {
// attack phase ended, and now we decay:
-0.002267599
]);
// check if decay stays stable:
let res = run_for_ms(&mut node_exec, 2.0);
assert_decimated_slope_feq!(res.0, 40, vec![-0.002267599; 3]);
pset_d(&mut matrix, ad, "dcy", 200.0);
let res = run_for_ms(&mut node_exec, 20.0);
assert_decimated_slope_feq!(res.0, 40, vec![
// Slope is getting less and less steep, as expected:
-0.002197802, -0.0012806058, -0.00083732605, -0.0005899668,
-0.00043797493, -0.00033789873, -0.00026863813, -0.00021868944,
-0.00018143654, -0.00015294552, -0.00013071299,
// Slope does not change after the "dcy" change has been smoothed
-0.000113368034, -0.000113368034, -0.00011339784, -0.00011339784,
-0.000113368034, -0.000113368034, -0.00011339784, -0.000113368034,
-0.000113368034, -0.00011339784, -0.000113368034, -0.000113368034
]);
}
#[test]
fn check_node_ad_mult() {
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
let ad = NodeId::Ad(0);
let out = NodeId::Out(0);
matrix.place(0, 0, Cell::empty(ad)
.out(None, None, ad.out("sig")));
matrix.place(0, 1, Cell::empty(out)
.input(out.inp("ch1"), None, None));
matrix.sync().unwrap();
pset_n(&mut matrix, ad, "trig", 1.0);
pset_n(&mut matrix, ad, "mult", 2.0);
let res = run_for_ms(&mut node_exec, 2000.0);
assert_decimated_slope_feq_fine!(res.0, 1800, vec![
0.0,
// looong attack:
0.00007558, 0.00007558, 0.00007558, 0.00007558,
0.00007558, 0.00007558, 0.00007558,
// looong decay:
-0.000022709, -0.000022709, -0.000022709, -0.000022709, -0.000022709,
-0.000022709, -0.000022709, -0.000022709, -0.000022709, -0.000022709,
-0.000022709, -0.000022709, -0.000022709, -0.000022709, -0.000022709,
-0.000022709, -0.000022709, -0.000022709, -0.000022709, -0.000022709,
-0.000022709, -0.000022709, -0.000022709, -0.000022709, -0.000022709,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0,
]);
}