diff --git a/tests/common/mod.rs b/tests/common/mod.rs index ab57382..942dc90 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -393,15 +393,28 @@ macro_rules! assert_minmax_of_rms { }; } +#[allow(unused)] +pub fn wait_params_smooth(ne: &mut NodeExecutor) { + run_for_ms(ne, 15.0); +} + +#[allow(unused)] +pub fn node_pset_s(matrix: &mut Matrix, node: &str, instance: usize, parm: &str, set: i64) { + let nid = NodeId::from_str(node).to_instance(instance); + assert!(nid != NodeId::Nop); + let p = nid.inp_param(parm).expect("param exists"); + matrix.set_param(p, SAtom::setting(set)); +} + #[allow(unused)] pub fn pset_s(matrix: &mut Matrix, nid: NodeId, parm: &str, set: i64) { - let p = nid.inp_param(parm).unwrap(); + let p = nid.inp_param(parm).expect("param exists"); matrix.set_param(p, SAtom::setting(set)); } #[allow(unused)] pub fn pset_n(matrix: &mut Matrix, nid: NodeId, parm: &str, v_norm: f32) { - let p = nid.inp_param(parm).unwrap(); + let p = nid.inp_param(parm).expect("param exists"); matrix.set_param(p, SAtom::param(v_norm)); } @@ -409,13 +422,13 @@ pub fn pset_n(matrix: &mut Matrix, nid: NodeId, parm: &str, v_norm: f32) { pub fn node_pset_n(matrix: &mut Matrix, node: &str, instance: usize, parm: &str, v_norm: f32) { let nid = NodeId::from_str(node).to_instance(instance); assert!(nid != NodeId::Nop); - let p = nid.inp_param(parm).unwrap(); + let p = nid.inp_param(parm).expect("param exists"); matrix.set_param(p, SAtom::param(v_norm)); } #[allow(unused)] pub fn pset_d(matrix: &mut Matrix, nid: NodeId, parm: &str, v_denorm: f32) { - let p = nid.inp_param(parm).unwrap(); + let p = nid.inp_param(parm).expect("param exists"); matrix.set_param(p, SAtom::param(p.norm(v_denorm))); } @@ -423,7 +436,7 @@ pub fn pset_d(matrix: &mut Matrix, nid: NodeId, parm: &str, v_denorm: f32) { pub fn node_pset_d(matrix: &mut Matrix, node: &str, instance: usize, parm: &str, v_denorm: f32) { let nid = NodeId::from_str(node).to_instance(instance); assert!(nid != NodeId::Nop); - let p = nid.inp_param(parm).unwrap(); + let p = nid.inp_param(parm).expect("param exists"); matrix.set_param(p, SAtom::param(p.norm(v_denorm))); } @@ -435,9 +448,9 @@ pub fn pset_n_wait( parm: &str, v_norm: f32, ) { - let p = nid.inp_param(parm).unwrap(); + let p = nid.inp_param(parm).expect("param exists"); matrix.set_param(p, SAtom::param(v_norm)); - run_for_ms(ne, 15.0); + wait_params_smooth(ne); } #[allow(unused)] @@ -448,14 +461,14 @@ pub fn pset_d_wait( parm: &str, v_denorm: f32, ) { - let p = nid.inp_param(parm).unwrap(); + let p = nid.inp_param(parm).expect("param exists"); matrix.set_param(p, SAtom::param(p.norm(v_denorm))); - run_for_ms(ne, 15.0); + wait_params_smooth(ne); } #[allow(unused)] pub fn pset_mod(matrix: &mut Matrix, nid: NodeId, parm: &str, modamt: f32) { - let p = nid.inp_param(parm).unwrap(); + let p = nid.inp_param(parm).expect("param exists"); matrix.set_param_modamt(p, Some(modamt)); } @@ -469,7 +482,7 @@ pub fn pset_mod_wait( ) { let p = nid.inp_param(parm).unwrap(); matrix.set_param_modamt(p, Some(modamt)); - run_for_ms(ne, 15.0); + wait_params_smooth(ne); } #[allow(dead_code)] diff --git a/tests/node_scope.rs b/tests/node_scope.rs index e3bf294..598c76b 100644 --- a/tests/node_scope.rs +++ b/tests/node_scope.rs @@ -16,14 +16,14 @@ fn read_scope_buf(matrix: &Matrix, sig_idx: usize) -> (Vec, Vec, f32, let mut total_max: f32 = -99999.9; for i in 0..SCOPE_SAMPLES { - let (mi, ma) = handle.read(sig_idx, i); + let (ma, mi) = handle.read(sig_idx, i); min.push(mi); max.push(ma); total_min = total_min.min(mi); total_max = total_max.max(ma); } - (min, max, total_min, total_max) + (max, min, total_max, total_min) } #[test] @@ -45,9 +45,141 @@ fn check_node_scope_inputs() { let _res = run_for_ms(&mut node_exec, 11.0); let (minv, maxv, min, max) = read_scope_buf(&matrix, sig_idx); + // This tests the smoothing ramp that is applied to setting the "inp" of the Amp(0) node: assert_decimated_feq!(minv, 80, vec![0.0022, 0.1836, 0.3650, 0.5464, 0.7278, 0.9093, 1.0]); assert_decimated_feq!(maxv, 80, vec![0.0022, 0.1836, 0.3650, 0.5464, 0.7278, 0.9093, 1.0]); assert_float_eq!(min, 0.0); assert_float_eq!(max, 1.0); } } + +#[test] +fn check_node_scope_offs_gain_thrsh() { + let (node_conf, mut node_exec) = new_node_engine(); + let mut matrix = Matrix::new(node_conf, 3, 3); + + let mut chain = MatrixCellChain::new(CellDir::B); + chain.node_out("amp", "sig").node_inp("scope", "in1").place(&mut matrix, 0, 0).unwrap(); + matrix.sync().unwrap(); + + node_pset_d(&mut matrix, "scope", 0, "off1", 0.1); + node_pset_d(&mut matrix, "scope", 0, "off2", 0.2); + node_pset_d(&mut matrix, "scope", 0, "off3", 0.3); + node_pset_d(&mut matrix, "scope", 0, "gain1", 2.0); + node_pset_d(&mut matrix, "scope", 0, "gain2", 3.0); + node_pset_d(&mut matrix, "scope", 0, "gain3", 4.0); + node_pset_d(&mut matrix, "scope", 0, "thrsh", 0.95); + node_pset_s(&mut matrix, "scope", 0, "tsrc", 1); + wait_params_smooth(&mut node_exec); + + let handle = matrix.get_scope_handle(0).unwrap(); + let _res = run_for_ms(&mut node_exec, 11.0); + + let thres = handle.get_threshold().unwrap(); + assert_float_eq!(thres, 0.95); + + let (off, gain) = handle.get_offs_gain(0); + assert_float_eq!(off, 0.1); + assert_float_eq!(gain, 2.0); + + let (off, gain) = handle.get_offs_gain(1); + assert_float_eq!(off, 0.2); + assert_float_eq!(gain, 3.0); + + let (off, gain) = handle.get_offs_gain(2); + assert_float_eq!(off, 0.3); + assert_float_eq!(gain, 4.0); +} + +#[test] +fn check_node_scope_sine_2hz() { + let (node_conf, mut node_exec) = new_node_engine(); + let mut matrix = Matrix::new(node_conf, 3, 3); + + let mut chain = MatrixCellChain::new(CellDir::B); + chain + .node_out("sin", "sig") + .set_denorm("freq", 2.0) + .node_io("amp", "inp", "sig") + .node_inp("scope", "in1") + .place(&mut matrix, 0, 0) + .unwrap(); + matrix.sync().unwrap(); + + wait_params_smooth(&mut node_exec); + + let handle = matrix.get_scope_handle(0).unwrap(); + let _res = run_for_ms(&mut node_exec, 1000.0); + + let (maxv, minv, max, min) = read_scope_buf(&matrix, 0); + // 2 Hz is exactly 2 sine peaks in 1000ms. 1000ms is the default time of the Scope. + assert_decimated_feq!( + maxv, + 64, + vec![0.0264, 1.0, -0.0004, -0.99968, 0.02546, 1.0, -0.0011, -0.9996] + ); + assert_decimated_feq!( + minv, + 64, + vec![0.0016, 0.9996, -0.0249, -1.0, 0.0009, 0.9996, -0.0256, -0.9999] + ); + assert_float_eq!(max, 1.0); + assert_float_eq!(min, -1.0); + + // Now change timing to 500ms, so we expect one peak: + node_pset_d(&mut matrix, "scope", 0, "time", 500.0); + let _res = run_for_ms(&mut node_exec, 1000.0); + + let (maxv, minv, max, min) = read_scope_buf(&matrix, 0); + // 2 Hz is exactly 1 sine peaks in 500ms. + assert_decimated_feq!(maxv, 128, vec![0.1494, 0.9905, -0.1371, -0.9887]); + assert_decimated_feq!(minv, 128, vec![0.1376, 0.9888, -0.1489, -0.9904]); + assert_float_eq!(max, 1.0); + assert_float_eq!(min, -1.0); +} + + +#[test] +fn check_node_scope_sine_oversampled() { + let (node_conf, mut node_exec) = new_node_engine(); + let mut matrix = Matrix::new(node_conf, 3, 3); + + let mut chain = MatrixCellChain::new(CellDir::B); + chain + .node_out("sin", "sig") + .set_denorm("freq", 440.0) + .node_io("amp", "inp", "sig") + .node_inp("scope", "in1") + .set_denorm("time", 1.0) + .place(&mut matrix, 0, 0) + .unwrap(); + matrix.sync().unwrap(); + + wait_params_smooth(&mut node_exec); + + let handle = matrix.get_scope_handle(0).unwrap(); + let _res = run_for_ms(&mut node_exec, 1000.0); + + let (maxv, minv, max, min) = read_scope_buf(&matrix, 0); + assert_decimated_feq!( + maxv[0..25], + 5, + vec![ + 0.4506, + 0.4506, + 0.4506, + 0.3938, + 0.3938, + 0.3354, + 0.3354, + 0.2150, + 0.2150, + 0.1534, + 0.1534, + 0.1534, + ] + ); + // Full wave does not fit into the buffer at 1ms for 512 samples + assert_float_eq!(max, 0.9996); + assert_float_eq!(min, -0.5103); +}