wrote test for FbRd and FbWr, and fixed remaining bugs
This commit is contained in:
parent
3bf1d62239
commit
c56846ad02
4 changed files with 57 additions and 32 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue