From c56846ad0212029d79448db8f93e8faeb0eba69a Mon Sep 17 00:00:00 2001 From: Weird Constructor Date: Thu, 3 Jun 2021 20:16:31 +0200 Subject: [PATCH] wrote test for FbRd and FbWr, and fixed remaining bugs --- src/matrix.rs | 1 + src/nodes/mod.rs | 2 +- src/nodes/node_exec.rs | 22 +++++++++------ tests/basics.rs | 64 +++++++++++++++++++++++++++--------------- 4 files changed, 57 insertions(+), 32 deletions(-) diff --git a/src/matrix.rs b/src/matrix.rs index 75db120..e64d071 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -857,6 +857,7 @@ impl Matrix { let mut prog = self.config.rebuild_node_ports(); for node_id in ordered_nodes.iter() { + println!("PROG NODE ORD: {:?}", node_id); self.config.add_prog_node(&mut prog, node_id); } diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index 172f1aa..6aac65b 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -6,7 +6,7 @@ pub const MAX_ALLOCATED_NODES : usize = 256; pub const MAX_SMOOTHERS : usize = 36 + 4; // 6 * 6 modulator inputs + 4 UI Knobs pub const MAX_AVAIL_TRACKERS : usize = 128; pub const MAX_FB_DELAYS : usize = 256; // 256 feedback delays, thats roughly 1.2MB RAM -pub const FB_DELAY_TIME_US : usize = 1500; // 1.5ms +pub const FB_DELAY_TIME_US : usize = 3140; // 3.14ms (should be enough for MAX_BLOCK_SIZE) // This means, until 384000 sample rate the times are accurate. pub const MAX_FB_DELAY_SRATE : usize = 48000 * 8; pub const MAX_FB_DELAY_SIZE : usize = diff --git a/src/nodes/node_exec.rs b/src/nodes/node_exec.rs index 40136ff..d8dd478 100644 --- a/src/nodes/node_exec.rs +++ b/src/nodes/node_exec.rs @@ -7,7 +7,7 @@ use super::{ UNUSED_MONITOR_IDX, MAX_ALLOCATED_NODES, MAX_SMOOTHERS, MAX_FB_DELAY_SIZE, FB_DELAY_TIME_US, }; -use crate::dsp::{NodeId, Node}; +use crate::dsp::{NodeId, Node, MAX_BLOCK_SIZE}; use crate::util::{Smoother, AtomicFloat}; use crate::monitor::{MonitorBackend, MON_SIG_CNT}; @@ -86,7 +86,7 @@ pub trait NodeAudioContext { /// FbWr and FbRd. /// /// Note that the previous audio period or even the first one ever may -/// produce less than 64 samples. This means we need to keep track +/// produce less than 128 samples. This means we need to keep track /// how many samples were actually written to the feedback buffer! /// See also `sample_count` field. pub struct FeedbackBuffer { @@ -108,7 +108,7 @@ impl FeedbackBuffer { Self { buffer: [0.0; MAX_FB_DELAY_SIZE], write_ptr: 0, - read_ptr: (64 + MAX_FB_DELAY_SIZE) % MAX_FB_DELAY_SIZE, + read_ptr: 0, sample_count: 0, } } @@ -133,8 +133,7 @@ impl FeedbackBuffer { // For more elaborate and longer delays an extra delay node should // be used before FbWr or after FbRd. let delay_sample_count = (sr as usize * FB_DELAY_TIME_US) / 1000000; - self.read_ptr = (delay_sample_count + FB_DELAY_TIME_US) - % FB_DELAY_TIME_US; + self.read_ptr = 0; } #[inline] @@ -174,6 +173,12 @@ impl NodeExecContext { } } + fn set_sample_rate(&mut self, srate: f32) { + for b in self.feedback_delay_buffers.iter_mut() { + b.set_sample_rate(srate); + } + } + fn clear(&mut self) { for b in self.feedback_delay_buffers.iter_mut() { b.clear(); @@ -303,6 +308,7 @@ impl NodeExecutor { pub fn set_sample_rate(&mut self, sample_rate: f32) { self.sample_rate = sample_rate; + self.exec_ctx.set_sample_rate(sample_rate); for n in self.nodes.iter_mut() { n.set_sample_rate(sample_rate); } @@ -510,8 +516,8 @@ impl NodeExecutor { let mut offs = 0; while nframes > 0 { let cur_nframes = - if nframes >= crate::dsp::MAX_BLOCK_SIZE { - crate::dsp::MAX_BLOCK_SIZE + if nframes >= MAX_BLOCK_SIZE { + MAX_BLOCK_SIZE } else { nframes }; @@ -528,7 +534,7 @@ impl NodeExecutor { if realtime { let micros = - ((crate::dsp::MAX_BLOCK_SIZE as u64) * 1000000) + ((MAX_BLOCK_SIZE as u64) * 1000000) / (SAMPLE_RATE as u64); std::thread::sleep( std::time::Duration::from_micros(micros)); diff --git a/tests/basics.rs b/tests/basics.rs index c96b648..55f8b83 100644 --- a/tests/basics.rs +++ b/tests/basics.rs @@ -928,34 +928,52 @@ fn check_matrix_node_feedback() { let wr2 = NodeId::FbWr(1); let rd2 = NodeId::FbRd(1); let out = NodeId::Out(0); - matrix.place(0, 0, Cell::empty(sin) - .out(None, None, sin.out("sig"))); - matrix.place(0, 1, Cell::empty(wr) - .input(wr.inp("inp"), None, None)); - matrix.place(1, 0, Cell::empty(rd) - .out(None, None, rd.out("sig"))); - matrix.place(1, 1, Cell::empty(out) - .input(out.inp("ch1"), None, None)); - matrix.place(0, 2, Cell::empty(sin2) - .out(None, None, sin2.out("sig"))); - matrix.place(0, 3, Cell::empty(wr2) - .input(wr2.inp("inp"), None, None)); - matrix.place(1, 2, Cell::empty(rd2) - .out(None, None, rd2.out("sig"))); - matrix.place(1, 3, Cell::empty(out) - .input(out.inp("ch2"), None, None)); + matrix.place(0, 0, Cell::empty(sin).out(None, None, sin.out("sig"))); + matrix.place(0, 1, Cell::empty(wr) .input(wr.inp("inp"), None, None)); + matrix.place(1, 0, Cell::empty(rd) .out(None, None, rd.out("sig"))); + matrix.place(1, 1, Cell::empty(out).input(out.inp("ch1"), None, None)); + + matrix.place(0, 2, Cell::empty(sin2).out(None, None, sin2.out("sig"))); + matrix.place(0, 3, Cell::empty(wr2) .input(wr2.inp("inp"), None, None)); + matrix.place(1, 2, Cell::empty(rd2) .out(None, None, rd2.out("sig"))); + matrix.place(1, 3, Cell::empty(out) .input(out.inp("ch2"), None, None)); matrix.sync().unwrap(); let freq_param = sin2.inp_param("freq").unwrap(); - matrix.set_param( - freq_param, - SAtom::param(freq_param.norm(880.0))); + matrix.set_param(freq_param, SAtom::param(freq_param.norm(880.0))); - let (out_l, out_r) = run_for_ms(&mut node_exec, 5.0); + let (out_l, out_r) = run_for_ms(&mut node_exec, 10.0); + assert_decimated_feq!( + out_l, 15, vec![ + // The initial zeros are the feedback delays: + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.4248709, 0.9816776, 0.7325672, -0.11797579, -0.8716552, + -0.90973216, -0.20093217, 0.6728242, 0.99420625, 0.49937242, + -0.40543562, -0.9773846, -0.7469322, 0.096737176, 0.86098254, + 0.9183933, 0.22181934, -0.6568572, -0.9962849, -0.5177674, + 0.3858096]); + assert_decimated_feq!( + out_r, 15, vec![ + // The initial zeros are the feedback delays: + // The frequency will be established a bit later because + // the parameter setting of 880 Hz will be smoothed: + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.42738196, 0.9861684, 0.68267936, -0.2549982, -0.96115613, + -0.7120098, 0.28678903, 0.9854398, 0.56962675, -0.52827656, + -0.9845062, -0.17494306, 0.8781463, 0.7117191, -0.49352795, + -0.95974547, 0.085026, 0.9966484, 0.21335565, -0.9510752, + -0.3690226]); - println!("L: {:?}", out_l); - println!("R: {:?}", out_r); + // Let the frequency settle... + run_for_ms(&mut node_exec, 50.0); - assert!(false); + let (mut out_l, mut out_r) = run_for_ms(&mut node_exec, 50.0); + let fft_res_l = fft_thres_at_ms(&mut out_l[..], FFT::F1024, 100, 0.0); + assert_eq!(fft_res_l[0], (431, 245)); + assert_eq!(fft_res_l[1], (474, 170)); + + let fft_res_r = fft_thres_at_ms(&mut out_r[..], FFT::F1024, 100, 0.0); + assert_eq!(fft_res_r[0], (861, 224)); + assert_eq!(fft_res_r[1], (904, 206)); }