Moved TSeq to Mod and wrote first tests for PVerb
This commit is contained in:
parent
348cc8d7c7
commit
2c458ca117
4 changed files with 256 additions and 1 deletions
|
@ -673,7 +673,7 @@ macro_rules! node_list {
|
||||||
(6 max n_id d_id r_s f_def stp_d -1.0, 1.0, 1.0)
|
(6 max n_id d_id r_s f_def stp_d -1.0, 1.0, 1.0)
|
||||||
{7 0 clip setting(0) fa_map_clip 0 1}
|
{7 0 clip setting(0) fa_map_clip 0 1}
|
||||||
[0 sig],
|
[0 sig],
|
||||||
tseq => TSeq UIType::Generic UICategory::CV
|
tseq => TSeq UIType::Generic UICategory::Mod
|
||||||
(0 clock n_id d_id r_id f_def stp_d 0.0, 1.0, 0.0)
|
(0 clock n_id d_id r_id f_def stp_d 0.0, 1.0, 0.0)
|
||||||
(1 trig n_id n_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
(1 trig n_id n_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||||
{2 0 cmode setting(1) fa_tseq_cmode 0 2}
|
{2 0 cmode setting(1) fa_tseq_cmode 0 2}
|
||||||
|
|
|
@ -19,6 +19,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use core::arch::x86_64::{
|
use core::arch::x86_64::{
|
||||||
_MM_FLUSH_ZERO_ON,
|
_MM_FLUSH_ZERO_ON,
|
||||||
|
// _MM_FLUSH_ZERO_OFF,
|
||||||
_MM_SET_FLUSH_ZERO_MODE,
|
_MM_SET_FLUSH_ZERO_MODE,
|
||||||
// _MM_GET_FLUSH_ZERO_MODE
|
// _MM_GET_FLUSH_ZERO_MODE
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,16 @@ pub const SAMPLE_RATE : f32 = 44100.0;
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub const SAMPLE_RATE_US : usize = 44100;
|
pub const SAMPLE_RATE_US : usize = 44100;
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! init_test {
|
||||||
|
($matrix: ident, $node_exec: ident, $size: expr) => {
|
||||||
|
let (node_conf, mut node_exec) = new_node_engine();
|
||||||
|
let mut matrix = Matrix::new(node_conf, $size, $size);
|
||||||
|
let $matrix = &mut matrix;
|
||||||
|
let $node_exec = &mut node_exec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! assert_float_eq {
|
macro_rules! assert_float_eq {
|
||||||
($a:expr, $b:expr) => {
|
($a:expr, $b:expr) => {
|
||||||
|
@ -228,6 +238,13 @@ assertion failed: `(left[{}] == right[{}])`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! dump_table {
|
||||||
|
($vec:expr) => {
|
||||||
|
for (i, s) in $vec.iter().enumerate() { println!("{:2} {:?}", i, s); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn collect_signal_changes(inp: &[f32], thres: i64) -> Vec<(usize, i64)> {
|
pub fn collect_signal_changes(inp: &[f32], thres: i64) -> Vec<(usize, i64)> {
|
||||||
let mut idxs = vec![];
|
let mut idxs = vec![];
|
||||||
|
@ -428,6 +445,21 @@ pub fn run_and_get_each_rms_mimax(
|
||||||
calc_rms_mimax_each_ms(&out_l[..], len_ms)
|
calc_rms_mimax_each_ms(&out_l[..], len_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the rms of a specified amount of time 'len_ms' and take samples
|
||||||
|
/// of RMS, Min and Max each 'sample_ms' (of the same length).
|
||||||
|
///
|
||||||
|
/// * 'len_ms' - complete runtime
|
||||||
|
/// * 'sample_ms' - length of each rms sample
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn run_and_get_rms_mimax(
|
||||||
|
node_exec: &mut hexodsp::nodes::NodeExecutor,
|
||||||
|
len_ms: f32,
|
||||||
|
sample_ms: f32) -> Vec<(f32, f32, f32)>
|
||||||
|
{
|
||||||
|
let (out_l, _out_r) = run_no_input(node_exec, len_ms / 1000.0);
|
||||||
|
calc_rms_mimax_each_ms(&out_l[..], sample_ms)
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn run_and_get_first_rms_mimax(
|
pub fn run_and_get_first_rms_mimax(
|
||||||
node_exec: &mut hexodsp::nodes::NodeExecutor,
|
node_exec: &mut hexodsp::nodes::NodeExecutor,
|
||||||
|
@ -511,6 +543,27 @@ pub fn run_and_get_fft4096_2(
|
||||||
fft(&mut out_l[..], FFT::F4096, thres)
|
fft(&mut out_l[..], FFT::F4096, thres)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Minimal 'each_ms' is 47ms, because each spectrum takes that time.
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn run_fft_spectrum_each_47ms(
|
||||||
|
node_exec: &mut hexodsp::nodes::NodeExecutor,
|
||||||
|
thres: u32, count: usize)
|
||||||
|
-> Vec<Vec<(u16, u32)>>
|
||||||
|
{
|
||||||
|
let mut out = vec![];
|
||||||
|
|
||||||
|
for _ in 0..count {
|
||||||
|
let min_samples_for_fft = 1024.0;
|
||||||
|
let min_len_samples = 2.0 * min_samples_for_fft;
|
||||||
|
let run_len_s = min_len_samples / SAMPLE_RATE;
|
||||||
|
let offs_ms = (run_len_s * 1000.0);
|
||||||
|
let (mut out_l, _out_r) = run_no_input(node_exec, run_len_s);
|
||||||
|
out.push(fft(&mut out_l[..], FFT::F1024, thres));
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn calc_exp_avg_buckets4096(fft: &[(u16, u32)]) -> Vec<(u16, u32)> {
|
pub fn calc_exp_avg_buckets4096(fft: &[(u16, u32)]) -> Vec<(u16, u32)> {
|
||||||
let mut avg = vec![];
|
let mut avg = vec![];
|
||||||
|
|
201
tests/node_pverb.rs
Normal file
201
tests/node_pverb.rs
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
// 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::*;
|
||||||
|
|
||||||
|
fn trig_env(matrix: &mut Matrix, node_exec: &mut NodeExecutor) {
|
||||||
|
let ad_1 = NodeId::Ad(0);
|
||||||
|
pset_n(matrix, ad_1, "trig", 1.0);
|
||||||
|
run_for_ms(node_exec, 7.0); // Wait for attack start.
|
||||||
|
pset_n(matrix, ad_1, "trig", 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_pverb(matrix: &mut Matrix) {
|
||||||
|
let sin_1 = NodeId::Sin(0);
|
||||||
|
let ad_1 = NodeId::Ad(0);
|
||||||
|
let pverb_1 = NodeId::PVerb(0);
|
||||||
|
let out_1 = NodeId::Out(0);
|
||||||
|
matrix.place(0, 0,
|
||||||
|
Cell::empty(sin_1)
|
||||||
|
.input(None, None, None)
|
||||||
|
.out(None, None, sin_1.out("sig")));
|
||||||
|
matrix.place(0, 1,
|
||||||
|
Cell::empty(ad_1)
|
||||||
|
.input(ad_1.inp("inp"), None, None)
|
||||||
|
.out(ad_1.out("sig"), None, None));
|
||||||
|
matrix.place(1, 0,
|
||||||
|
Cell::empty(pverb_1)
|
||||||
|
.input(None, None, pverb_1.inp("in_l"))
|
||||||
|
.out(None, None, pverb_1.out("sig_l")));
|
||||||
|
matrix.place(1, 1,
|
||||||
|
Cell::empty(out_1)
|
||||||
|
.input(out_1.inp("ch1"), None, None)
|
||||||
|
.out(None, None, None));
|
||||||
|
pset_n(matrix, ad_1, "ashp", 0.870);
|
||||||
|
pset_n(matrix, ad_1, "dshp", 0.870);
|
||||||
|
pset_d(matrix, ad_1, "atk", 6.0);
|
||||||
|
pset_d(matrix, ad_1, "dcy", 100.0);
|
||||||
|
pset_n(matrix, pverb_1, "mix", 1.000);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_node_pverb_dcy_1() {
|
||||||
|
init_test!(matrix, node_exec, 3);
|
||||||
|
|
||||||
|
let ad_1 = NodeId::Ad(0);
|
||||||
|
let pverb_1 = NodeId::PVerb(0);
|
||||||
|
|
||||||
|
setup_pverb(matrix);
|
||||||
|
matrix.sync().unwrap();
|
||||||
|
|
||||||
|
// pset_n(&mut matrix, pverb_1, "dcy", 0.675);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "dif", 1.000);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "ihpf", -1.543);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "ilpf", 0.565);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "in_l", 0.000);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "in_r", 0.000);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "mdepth", 0.200);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "mshp", 0.500);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "mspeed", 0.075);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "predly", 0.000);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "rhpf", -1.543);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "rlpf", 0.565);
|
||||||
|
// pset_n(&mut matrix, pverb_1, "size", 0.330);
|
||||||
|
|
||||||
|
// Dry mix:
|
||||||
|
pset_n_wait(matrix, node_exec, pverb_1, "mix", 0.000);
|
||||||
|
trig_env(matrix, node_exec);
|
||||||
|
|
||||||
|
let spec = run_fft_spectrum_each_47ms(node_exec, 5, 4);
|
||||||
|
//d// for s in &spec { println!("{:?}", s); }
|
||||||
|
|
||||||
|
// We see the sine decaying with the AD envelope:
|
||||||
|
assert_eq!(spec[0], vec![(345, 6), (388, 85), (431, 240), (474, 164), (517, 13)]);
|
||||||
|
assert_eq!(spec[1], vec![(388, 65), (431, 185), (474, 126), (517, 10)]);
|
||||||
|
assert_eq!(spec[2], vec![(345, 11), (388, 24), (431, 32), (474, 29), (517, 16), (560, 6)]);
|
||||||
|
assert_eq!(spec[3], vec![]);
|
||||||
|
|
||||||
|
// Wet mix & clear out the reset in the tank:
|
||||||
|
pset_n(matrix, pverb_1, "mix", 0.000);
|
||||||
|
pset_n(matrix, pverb_1, "dcy", 0.000);
|
||||||
|
run_for_ms(node_exec, 100.0); // Wait flor clearance
|
||||||
|
|
||||||
|
// Check that there is nothing playing:
|
||||||
|
let spec = run_fft_spectrum_each_47ms(node_exec, 20, 1);
|
||||||
|
assert_eq!(spec[0], vec![]);
|
||||||
|
|
||||||
|
// Wet mix and decay:
|
||||||
|
pset_n(matrix, pverb_1, "dcy", 0.2);
|
||||||
|
pset_n_wait(matrix, node_exec, pverb_1, "mix", 1.0);
|
||||||
|
trig_env(matrix, node_exec);
|
||||||
|
|
||||||
|
let spec = run_fft_spectrum_each_47ms(node_exec, 5, 20);
|
||||||
|
for (i, s) in spec.iter().enumerate() { println!("{:2} {:?}", i, s); }
|
||||||
|
|
||||||
|
// 0 [(388, 19), (431, 74), (474, 61), (517, 10)]
|
||||||
|
// 1 [(388, 64), (431, 150), (474, 92), (517, 11)]
|
||||||
|
// 2 [(345, 5), (388, 72), (431, 205), (474, 138), (517, 11), (560, 5)]
|
||||||
|
// 3 [(388, 82), (431, 220), (474, 146), (517, 8)]
|
||||||
|
// 4 [(345, 6), (388, 54), (431, 161), (474, 109), (517, 9)]
|
||||||
|
// 5 [(388, 9), (431, 37), (474, 26)]
|
||||||
|
// 6 [(388, 12), (431, 11), (474, 6)]
|
||||||
|
// 7 [(388, 10), (431, 23), (474, 11)]
|
||||||
|
// 8 [(388, 14), (431, 37), (474, 26)]
|
||||||
|
// 9 [(388, 18), (431, 50), (474, 37), (517, 5)]
|
||||||
|
// 10 [(388, 10), (431, 18), (474, 7)]
|
||||||
|
// 11 [(388, 15), (431, 34), (474, 27), (517, 7)]
|
||||||
|
// 12 [(431, 15), (474, 16)]
|
||||||
|
// 13 [(388, 9), (431, 29), (474, 24)]
|
||||||
|
// 14 [(388, 18), (431, 47), (474, 30)]
|
||||||
|
// 15 [(388, 7), (431, 18), (474, 12)]
|
||||||
|
// 16 [(431, 6)]
|
||||||
|
// 17 [(388, 7), (431, 19), (474, 12)]
|
||||||
|
// 18 [(388, 7), (431, 24), (474, 17)]
|
||||||
|
// 19 []
|
||||||
|
|
||||||
|
// Now we see a very much longer tail:
|
||||||
|
assert_eq!(spec[0], vec![(388, 19), (431, 74), (474, 61), (517, 10)]);
|
||||||
|
assert_eq!(spec[5], vec![(388, 9), (431, 37), (474, 26)]);
|
||||||
|
assert_eq!(spec[9], vec![(388, 18), (431, 50), (474, 37), (517, 5)]);
|
||||||
|
assert_eq!(spec[19], vec![(388, 7), (431, 15), (474, 8)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_node_pverb_dcy_2() {
|
||||||
|
init_test!(matrix, node_exec, 3);
|
||||||
|
let pverb_1 = NodeId::PVerb(0);
|
||||||
|
|
||||||
|
setup_pverb(matrix);
|
||||||
|
matrix.sync().unwrap();
|
||||||
|
|
||||||
|
// Small room, short decay:
|
||||||
|
pset_n_wait(matrix, node_exec, pverb_1, "dcy", 0.2);
|
||||||
|
pset_n_wait(matrix, node_exec, pverb_1, "size", 0.1);
|
||||||
|
trig_env(matrix, node_exec);
|
||||||
|
|
||||||
|
let rms_spec = run_and_get_rms_mimax(node_exec, 500.0, 100.0);
|
||||||
|
//d// dump_table!(rms_spec);
|
||||||
|
assert_vec_feq!(rms_spec.iter().map(|rms| rms.0).collect::<Vec<f32>>(),
|
||||||
|
// Decay over 500 ms:
|
||||||
|
vec![
|
||||||
|
0.2108,
|
||||||
|
0.5744,
|
||||||
|
0.0881,
|
||||||
|
0.0021,
|
||||||
|
0.0006
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_node_pverb_dcy_3() {
|
||||||
|
init_test!(matrix, node_exec, 3);
|
||||||
|
let pverb_1 = NodeId::PVerb(0);
|
||||||
|
|
||||||
|
setup_pverb(matrix);
|
||||||
|
matrix.sync().unwrap();
|
||||||
|
|
||||||
|
// Small room, long decay:
|
||||||
|
pset_n_wait(matrix, node_exec, pverb_1, "dcy", 0.8);
|
||||||
|
pset_n_wait(matrix, node_exec, pverb_1, "size", 0.1);
|
||||||
|
trig_env(matrix, node_exec);
|
||||||
|
|
||||||
|
let rms_spec = run_and_get_rms_mimax(node_exec, 5000.0, 1000.0);
|
||||||
|
//d// dump_table!(rms_spec);
|
||||||
|
assert_vec_feq!(rms_spec.iter().map(|rms| rms.0).collect::<Vec<f32>>(),
|
||||||
|
// Decay over 5000 ms:
|
||||||
|
vec![
|
||||||
|
0.6254,
|
||||||
|
0.2868,
|
||||||
|
0.0633,
|
||||||
|
0.0385,
|
||||||
|
0.0186,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_node_pverb_dcy_4() {
|
||||||
|
init_test!(matrix, node_exec, 3);
|
||||||
|
let pverb_1 = NodeId::PVerb(0);
|
||||||
|
|
||||||
|
setup_pverb(matrix);
|
||||||
|
matrix.sync().unwrap();
|
||||||
|
|
||||||
|
// Big room, long decay:
|
||||||
|
pset_n_wait(matrix, node_exec, pverb_1, "dcy", 0.8);
|
||||||
|
pset_n_wait(matrix, node_exec, pverb_1, "size", 0.5);
|
||||||
|
trig_env(matrix, node_exec);
|
||||||
|
|
||||||
|
let rms_spec = run_and_get_rms_mimax(node_exec, 5000.0, 1000.0);
|
||||||
|
//d// dump_table!(rms_spec);
|
||||||
|
assert_vec_feq!(rms_spec.iter().map(|rms| rms.0).collect::<Vec<f32>>(),
|
||||||
|
// Decay over 10000 ms:
|
||||||
|
vec![
|
||||||
|
0.1313,
|
||||||
|
0.0995,
|
||||||
|
0.0932,
|
||||||
|
0.0507,
|
||||||
|
0.0456,
|
||||||
|
]);
|
||||||
|
}
|
Loading…
Reference in a new issue