HexoDSP/tests/node_ad.rs
2021-08-04 03:58:43 +02:00

400 lines
15 KiB
Rust

// Copyright (c) 2021 Weird Constructor <weirdconstructor@gmail.com>
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
mod common;
use common::*;
#[test]
fn check_node_ad_1() {
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();
let trig_p = ad.inp_param("trig").unwrap();
matrix.set_param(trig_p, SAtom::param(1.0));
let res = run_for_ms(&mut node_exec, 25.0);
assert_decimated_slope_feq!(res.0, 50, vec![
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
// 44.1 per ms, attack is default 3.0ms (roughly 3 * 50 samples):
0.007558584, 0.007558584, 0.007558584,
// 44.1 per ms, decay is default 10.0ms (=> roughly 9 * 50 samples):
-0.002267599, -0.0022675395, -0.002267599, -0.0022675395,
-0.0022675693, -0.0022675693, -0.0022675842, -0.0022675693,
-0.0022675726,
0.0, 0.0, 0.0, 0.0
]);
matrix.set_param(trig_p, SAtom::param(0.0));
run_for_ms(&mut node_exec, 10.0);
matrix.set_param(trig_p, SAtom::param(1.0));
let res = run_for_ms(&mut node_exec, 25.0);
//d// println!("RES: {:?}", res);
let start = res.0[330];
assert_float_eq!(start, 0.0075585);
let peak = res.0[330 + ((44.1_f64 * 3.0).floor() as usize)];
assert_float_eq!(peak, 1.0);
}
#[test]
fn check_node_ad_retrig() {
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
let test = NodeId::Test(0);
let ad = NodeId::Ad(0);
let out = NodeId::Out(0);
matrix.place(0, 0, Cell::empty(test)
.out(None, None, test.out("sig")));
matrix.place(0, 1, Cell::empty(ad)
.input(ad.inp("trig"), None, None)
.out(None, None, ad.out("sig")));
matrix.place(0, 2, Cell::empty(out)
.input(out.inp("ch1"), None, None));
matrix.sync().unwrap();
let trig_p = test.inp_param("p").unwrap();
matrix.set_param(trig_p, SAtom::param(1.0));
let res = run_for_ms(&mut node_exec, 25.0);
assert_decimated_slope_feq!(res.0, 50, vec![
// XXX: Direct trigger!
// Due to Test node outputting an unsmoothed value!
// 44.1 per ms, attack is default 3.0ms (roughly 3 * 50 samples):
0.007558584, 0.007558584, 0.007558584,
// 44.1 per ms, decay is default 10.0ms (=> roughly 9 * 50 samples):
-0.002267599, -0.0022675395, -0.002267599, -0.0022675395,
-0.0022675693, -0.0022675693, -0.0022675842, -0.0022675693,
-0.0022675726,
0.0, 0.0, 0.0, 0.0
]);
matrix.set_param(trig_p, SAtom::param(0.0));
run_for_ms(&mut node_exec, 0.1);
matrix.set_param(trig_p, SAtom::param(1.0));
let res = run_for_ms(&mut node_exec, 1.5);
assert_decimated_feq!(res.0, 2, vec![
0.0075585, 0.022675736, 0.03779289, 0.05291005, 0.068027206, 0.08314436,
0.09826152, 0.113378674, 0.12849583, 0.143613, 0.15873015,
0.1738473, 0.18896446, 0.20408161, 0.21919878, 0.23431593,
0.24943309, 0.26455024, 0.2796674, 0.29478455, 0.3099017,
0.32501888, 0.34013602, 0.3552532, 0.37037033, 0.3854875,
0.40060467, 0.4157218, 0.43083897, 0.4459561, 0.46107328,
0.47619045, 0.4913076
]);
// Reset trigger
matrix.set_param(trig_p, SAtom::param(0.0));
let res = run_for_ms(&mut node_exec, 0.1);
assert_slope_feq!(res.0, vec![0.00755; 3]);
// Retrigger attack (should do nothing)
matrix.set_param(trig_p, SAtom::param(1.0));
let res = run_for_ms(&mut node_exec, 0.1);
assert_slope_feq!(res.0, vec![0.00755; 7]);
// Wait into decay phase
matrix.set_param(trig_p, SAtom::param(0.0));
let res = run_for_ms(&mut node_exec, 1.4);
let mut v = vec![0.00755; 57];
v.append(&mut vec![0.002267, -0.002267, -0.002267]);
assert_slope_feq!(res.0, v);
// Decay some more
let res = run_for_ms(&mut node_exec, 0.8);
assert_slope_feq!(res.0, vec![-0.002267; 100]);
// Retrigger right in the decay phase
matrix.set_param(trig_p, SAtom::param(1.0));
let res = run_for_ms(&mut node_exec, 1.0);
assert_slope_feq!(res.0, vec![
// Re-attack until we are at 1.0 again
0.007558584, 0.007558584, 0.007558584, 0.0075585246, 0.007558584,
0.007558584, 0.007558584, 0.007558584, 0.007558584, 0.007558584,
0.0007558465,
// Restart decay after 1.0 was reached:
-0.002267599, -0.0022675395, -0.002267599,
-0.0022675395, -0.002267599, -0.0022675395, -0.002267599,
-0.002267599, -0.0022675395, -0.002267599, -0.0022675395,
-0.002267599, -0.0022675395, -0.002267599, -0.002267599,
-0.0022675395, -0.002267599, -0.0022675395, -0.002267599,
-0.0022675395, -0.002267599, -0.002267599, -0.0022675395,
-0.002267599, -0.0022675395, -0.002267599, -0.0022675395,
-0.002267599, -0.002267599, -0.0022675395, -0.002267599, -0.0022675395
]);
}
#[test]
fn check_node_ad_inp_sin() {
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
let sin = NodeId::Sin(0);
let ad = NodeId::Ad(0);
let out = NodeId::Out(0);
matrix.place(0, 0, Cell::empty(sin)
.out(None, None, sin.out("sig")));
matrix.place(0, 1, Cell::empty(ad)
.input(ad.inp("inp"), None, None)
.out(None, None, ad.out("sig")));
matrix.place(0, 2, Cell::empty(out)
.input(out.inp("ch1"), None, None));
matrix.sync().unwrap();
let trig_p = ad.inp_param("trig").unwrap();
let atk_p = ad.inp_param("atk").unwrap();
let dcy_p = ad.inp_param("dcy").unwrap();
// check if we have any frequencies resembling 440Hz
matrix.set_param(trig_p, SAtom::param(1.0));
run_for_ms(&mut node_exec, 7.0);
let fft = run_and_get_fft4096_now(&mut node_exec, 6);
assert_eq!(fft[0], (420, 6));
assert_eq!(fft[1], (431, 6));
assert_eq!(fft[2], (441, 6));
assert_eq!(fft[3], (452, 6));
assert_eq!(fft[4], (463, 6));
// Next we test if lengthening the attack has
// effect on the captured frequencies.
matrix.set_param(trig_p, SAtom::param(0.0));
run_for_ms(&mut node_exec, 8.0);
matrix.set_param(atk_p, SAtom::param(atk_p.norm(40.0)));
matrix.set_param(trig_p, SAtom::param(1.0));
run_for_ms(&mut node_exec, 7.0);
let fft = run_and_get_fft4096_now(&mut node_exec, 300);
assert_eq!(fft[0], (431, 322));
assert_eq!(fft[1], (441, 360));
matrix.set_param(trig_p, SAtom::param(0.0));
run_for_ms(&mut node_exec, 8.0);
// Next we test if lengthening the decay too has
// effect on the captured frequencies.
matrix.set_param(trig_p, SAtom::param(0.0));
run_for_ms(&mut node_exec, 8.0);
matrix.set_param(dcy_p, SAtom::param(dcy_p.norm(40.0)));
matrix.set_param(trig_p, SAtom::param(1.0));
run_for_ms(&mut node_exec, 7.0);
let fft = run_and_get_fft4096_now(&mut node_exec, 300);
assert_eq!(fft[0], (431, 489));
assert_eq!(fft[1], (441, 647));
assert_eq!(fft[2], (452, 398));
matrix.set_param(trig_p, SAtom::param(0.0));
run_for_ms(&mut node_exec, 8.0);
}
#[test]
fn check_node_ad_shp_log() {
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, "ashp", 1.0);
pset_n(&mut matrix, ad, "dshp", 1.0);
let res = run_for_ms(&mut node_exec, 25.0);
assert_decimated_slope_feq!(res.0, 50, vec![
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
// 44.1 per ms, attack is default 3.0ms (roughly 3 * 50 samples):
0.009243369, 0.003936231, 0.0020142794,
// 44.1 per ms, decay is default 10.0ms (=> roughly 9 * 50 samples):
-0.0006071329, -0.00067061186, -0.000752151, -0.0008612871,
-0.0010163188, -0.0012571216, -0.0016934872, -0.0027971864,
-0.027684271,
0.0, 0.0, 0.0, 0.0
]);
}
#[test]
fn check_node_ad_shp_exp() {
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, "ashp", 0.0);
pset_n(&mut matrix, ad, "dshp", 0.0);
let res = run_for_ms(&mut node_exec, 25.0);
assert_decimated_slope_feq!(res.0, 50, vec![
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
// 44.1 per ms, attack is default 3.0ms (roughly 3 * 50 samples):
0.0009576017, 0.0044435486, 0.023418367,
// 44.1 per ms, decay is default 10.0ms (=> roughly 9 * 50 samples):
-0.0068960786, -0.004632175, -0.002927363, -0.0017025322,
-0.00087817386, -0.0003750762, -0.000113890506, -0.0000153047,
-0.0000000017186217,
0.0, 0.0, 0.0, 0.0
]);
}
#[test]
fn check_node_ad_eoet() {
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.place(1, 0, Cell::empty(ad)
.out(None, None, ad.out("eoet")));
matrix.place(1, 1, Cell::empty(out)
.input(out.inp("ch2"), None, None));
matrix.sync().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![
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
// 44.1 per ms, attack is default 3.0ms (roughly 3 * 50 samples):
0.007558584, 0.007558584, 0.007558584,
// 44.1 per ms, decay is default 10.0ms (=> roughly 9 * 50 samples):
-0.002267599, -0.0022675395, -0.002267599, -0.0022675395,
-0.0022675693, -0.0022675693, -0.0022675842, -0.0022675693,
-0.0022675726,
0.0, // <- EOET expected here
0.0, 0.0, 0.0
]);
// check if trigger appears:
assert_decimated_feq!(res.1, 50, vec![
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
// 44.1 per ms, attack is default 3.0ms (roughly 3 * 50 samples):
0.0, 0.0, 0.0,
// 44.1 per ms, decay is default 10.0ms (=> roughly 9 * 50 samples):
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0,
1.0, // <- End of envelope!
0.0, 0.0, 0.0
]);
}
#[test]
fn check_node_ad_atk_dcy() {
let (node_conf, mut node_exec) = new_node_engine();
let mut matrix = Matrix::new(node_conf, 3, 3);
let test = NodeId::Test(0);
let ad = NodeId::Ad(0);
let out = NodeId::Out(0);
matrix.place(0, 0, Cell::empty(test)
.out(None, None, test.out("sig")));
matrix.place(0, 1, Cell::empty(ad)
.input(ad.inp("trig"), None, None)
.out(None, None, ad.out("sig")));
matrix.place(0, 2, Cell::empty(out)
.input(out.inp("ch1"), None, None));
matrix.sync().unwrap();
pset_d(&mut matrix, ad, "atk", 20.0);
pset_n(&mut matrix, test, "p", 0.0);
run_for_ms(&mut node_exec, 10.0);
pset_n(&mut matrix, test, "p", 1.0);
let res = run_for_ms(&mut node_exec, 10.0);
assert_decimated_slope_feq!(res.0, 10, vec![0.001133787; 50]);
pset_d(&mut matrix, ad, "atk", 50.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.0011277795, 0.0010179877, 0.00092345476, 0.00084143877,
0.0007699132, 0.0007072091, 0.0006517768, 0.00060266256,
0.00055885315, 0.0005196929, 0.00048446655, 0.00045353174,
// Slope does not change after the "atk" change has been smoothed
0.00045353174, 0.00045353174, 0.00045353174, 0.00045347214,
0.00045353174, 0.00045353174, 0.00045353174, 0.00045353174,
0.00045347214, 0.00045353174,
// 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,
]);
}