wrote test for FbRd and FbWr, and fixed remaining bugs

This commit is contained in:
Weird Constructor 2021-06-03 20:16:31 +02:00
parent 3bf1d62239
commit c56846ad02
4 changed files with 57 additions and 32 deletions

View file

@ -857,6 +857,7 @@ impl Matrix {
let mut prog = self.config.rebuild_node_ports(); let mut prog = self.config.rebuild_node_ports();
for node_id in ordered_nodes.iter() { for node_id in ordered_nodes.iter() {
println!("PROG NODE ORD: {:?}", node_id);
self.config.add_prog_node(&mut prog, node_id); self.config.add_prog_node(&mut prog, node_id);
} }

View file

@ -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_SMOOTHERS : usize = 36 + 4; // 6 * 6 modulator inputs + 4 UI Knobs
pub const MAX_AVAIL_TRACKERS : usize = 128; pub const MAX_AVAIL_TRACKERS : usize = 128;
pub const MAX_FB_DELAYS : usize = 256; // 256 feedback delays, thats roughly 1.2MB RAM 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. // This means, until 384000 sample rate the times are accurate.
pub const MAX_FB_DELAY_SRATE : usize = 48000 * 8; pub const MAX_FB_DELAY_SRATE : usize = 48000 * 8;
pub const MAX_FB_DELAY_SIZE : usize = pub const MAX_FB_DELAY_SIZE : usize =

View file

@ -7,7 +7,7 @@ use super::{
UNUSED_MONITOR_IDX, MAX_ALLOCATED_NODES, MAX_SMOOTHERS, UNUSED_MONITOR_IDX, MAX_ALLOCATED_NODES, MAX_SMOOTHERS,
MAX_FB_DELAY_SIZE, FB_DELAY_TIME_US, 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::util::{Smoother, AtomicFloat};
use crate::monitor::{MonitorBackend, MON_SIG_CNT}; use crate::monitor::{MonitorBackend, MON_SIG_CNT};
@ -86,7 +86,7 @@ pub trait NodeAudioContext {
/// FbWr and FbRd. /// FbWr and FbRd.
/// ///
/// Note that the previous audio period or even the first one ever may /// 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! /// how many samples were actually written to the feedback buffer!
/// See also `sample_count` field. /// See also `sample_count` field.
pub struct FeedbackBuffer { pub struct FeedbackBuffer {
@ -108,7 +108,7 @@ impl FeedbackBuffer {
Self { Self {
buffer: [0.0; MAX_FB_DELAY_SIZE], buffer: [0.0; MAX_FB_DELAY_SIZE],
write_ptr: 0, write_ptr: 0,
read_ptr: (64 + MAX_FB_DELAY_SIZE) % MAX_FB_DELAY_SIZE, read_ptr: 0,
sample_count: 0, sample_count: 0,
} }
} }
@ -133,8 +133,7 @@ impl FeedbackBuffer {
// For more elaborate and longer delays an extra delay node should // For more elaborate and longer delays an extra delay node should
// be used before FbWr or after FbRd. // be used before FbWr or after FbRd.
let delay_sample_count = (sr as usize * FB_DELAY_TIME_US) / 1000000; let delay_sample_count = (sr as usize * FB_DELAY_TIME_US) / 1000000;
self.read_ptr = (delay_sample_count + FB_DELAY_TIME_US) self.read_ptr = 0;
% FB_DELAY_TIME_US;
} }
#[inline] #[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) { fn clear(&mut self) {
for b in self.feedback_delay_buffers.iter_mut() { for b in self.feedback_delay_buffers.iter_mut() {
b.clear(); b.clear();
@ -303,6 +308,7 @@ impl NodeExecutor {
pub fn set_sample_rate(&mut self, sample_rate: f32) { pub fn set_sample_rate(&mut self, sample_rate: f32) {
self.sample_rate = sample_rate; self.sample_rate = sample_rate;
self.exec_ctx.set_sample_rate(sample_rate);
for n in self.nodes.iter_mut() { for n in self.nodes.iter_mut() {
n.set_sample_rate(sample_rate); n.set_sample_rate(sample_rate);
} }
@ -510,8 +516,8 @@ impl NodeExecutor {
let mut offs = 0; let mut offs = 0;
while nframes > 0 { while nframes > 0 {
let cur_nframes = let cur_nframes =
if nframes >= crate::dsp::MAX_BLOCK_SIZE { if nframes >= MAX_BLOCK_SIZE {
crate::dsp::MAX_BLOCK_SIZE MAX_BLOCK_SIZE
} else { } else {
nframes nframes
}; };
@ -528,7 +534,7 @@ impl NodeExecutor {
if realtime { if realtime {
let micros = let micros =
((crate::dsp::MAX_BLOCK_SIZE as u64) * 1000000) ((MAX_BLOCK_SIZE as u64) * 1000000)
/ (SAMPLE_RATE as u64); / (SAMPLE_RATE as u64);
std::thread::sleep( std::thread::sleep(
std::time::Duration::from_micros(micros)); std::time::Duration::from_micros(micros));

View file

@ -928,34 +928,52 @@ fn check_matrix_node_feedback() {
let wr2 = NodeId::FbWr(1); let wr2 = NodeId::FbWr(1);
let rd2 = NodeId::FbRd(1); let rd2 = NodeId::FbRd(1);
let out = NodeId::Out(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(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) matrix.place(0, 0, Cell::empty(sin).out(None, None, sin.out("sig")));
.out(None, None, sin2.out("sig"))); matrix.place(0, 1, Cell::empty(wr) .input(wr.inp("inp"), None, None));
matrix.place(0, 3, Cell::empty(wr2) matrix.place(1, 0, Cell::empty(rd) .out(None, None, rd.out("sig")));
.input(wr2.inp("inp"), None, None)); matrix.place(1, 1, Cell::empty(out).input(out.inp("ch1"), None, None));
matrix.place(1, 2, Cell::empty(rd2)
.out(None, None, rd2.out("sig"))); matrix.place(0, 2, Cell::empty(sin2).out(None, None, sin2.out("sig")));
matrix.place(1, 3, Cell::empty(out) matrix.place(0, 3, Cell::empty(wr2) .input(wr2.inp("inp"), None, None));
.input(out.inp("ch2"), 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(); matrix.sync().unwrap();
let freq_param = sin2.inp_param("freq").unwrap(); let freq_param = sin2.inp_param("freq").unwrap();
matrix.set_param( matrix.set_param(freq_param, SAtom::param(freq_param.norm(880.0)));
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); // Let the frequency settle...
println!("R: {:?}", out_r); 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));
} }