diff --git a/src/dsp/mod.rs b/src/dsp/mod.rs index 0e0cc72..24f3258 100644 --- a/src/dsp/mod.rs +++ b/src/dsp/mod.rs @@ -81,6 +81,9 @@ pub const MAX_BLOCK_SIZE : usize = 128; /// currently executed node. /// This structure is created by the [crate::nodes::NodeExecutor] on the fly. pub struct NodeContext<'a> { + /// The bitmask that indicates which input ports are used/connected + /// to some output. + pub in_connected: u64, /// The bitmask that indicates which output ports are used/connected /// to some input. pub out_connected: u64, @@ -1161,6 +1164,15 @@ macro_rules! make_node_info_enum { })+ } + #[allow(non_snake_case)] + pub mod is_in_con { + $(pub mod $variant { + $(#[inline] pub fn $para(nctx: &crate::dsp::NodeContext) -> bool { + nctx.in_connected & (1 << $in_idx) != 0x0 + })* + })+ + } + mod ni { $( #[derive(Debug, Clone)] diff --git a/src/dsp/node_test.rs b/src/dsp/node_test.rs index 3a5f58c..5c6a057 100644 --- a/src/dsp/node_test.rs +++ b/src/dsp/node_test.rs @@ -50,7 +50,7 @@ impl Test { pub const sig : &'static str = "Test sig\nThe output of p as signal"; pub const tsig : &'static str = "Test tsig\nA short trigger pulse will be generated when the 'trig' input is triggered."; pub const out2 : &'static str = "Test out2\nA test output that will emit 1.0 if output 'sig' is connected."; - pub const out3 : &'static str = "Test out3\n"; + pub const out3 : &'static str = "Test out3\nA test output that will emit 1.0 if input 'f' is connected."; pub const out4 : &'static str = "Test out4\n"; pub const outc : &'static str = "Test outc\nEmits a number that defines the out_connected bitmask. Used only for testing!"; @@ -77,13 +77,14 @@ impl DspNode for Test { atoms: &[SAtom], _inputs: &[ProcBuf], outputs: &mut [ProcBuf], _led: LedPhaseVals) { - use crate::dsp::{out_idx, at, is_out_con, out_buf}; + use crate::dsp::{out_idx, at, is_out_con, out_buf, is_in_con}; let p = at::Test::p(atoms); let trig = at::Test::trig(atoms); let tsig = out_idx::Test::tsig(); let mut out2 = out_buf::Test::out2(outputs); + let mut out3 = out_buf::Test::out3(outputs); let mut outc = out_buf::Test::outc(outputs); let (out, tsig) = outputs.split_at_mut(tsig); @@ -113,6 +114,8 @@ impl DspNode for Test { out2.write(frame, if is_out_con::Test::sig(nctx) { 1.0 } else { 0.0 }); + out3.write(frame, + if is_in_con::Test::f(nctx) { 1.0 } else { 0.0 }); outc.write(frame, nctx.out_connected as f32); } } diff --git a/src/matrix.rs b/src/matrix.rs index 2d84c7b..d038084 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -1054,9 +1054,9 @@ mod tests { assert!(nodes[2].to_id(2) == NodeId::Sin(2)); let prog = node_exec.get_prog(); - assert_eq!(prog.prog[0].to_string(), "Op(i=0 out=(0-1|1) in=(0-2) at=(0-0) mod=(0-0))"); - assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-2|1) in=(2-4) at=(0-0) mod=(0-0) cpy=(o0 => i2))"); - assert_eq!(prog.prog[2].to_string(), "Op(i=2 out=(2-3|0) in=(4-6) at=(0-0) mod=(0-0) cpy=(o1 => i4))"); + assert_eq!(prog.prog[0].to_string(), "Op(i=0 out=(0-1|1) in=(0-2|0) at=(0-0) mod=(0-0))"); + assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-2|1) in=(2-4|1) at=(0-0) mod=(0-0) cpy=(o0 => i2))"); + assert_eq!(prog.prog[2].to_string(), "Op(i=2 out=(2-3|0) in=(4-6|1) at=(0-0) mod=(0-0) cpy=(o1 => i4))"); } #[test] @@ -1146,8 +1146,8 @@ mod tests { let prog = node_exec.get_prog(); assert_eq!(prog.prog.len(), 2); - assert_eq!(prog.prog[0].to_string(), "Op(i=0 out=(0-1|1) in=(0-2) at=(0-0) mod=(0-0))"); - assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-1|0) in=(2-5) at=(0-1) mod=(0-0) cpy=(o0 => i2))"); + assert_eq!(prog.prog[0].to_string(), "Op(i=0 out=(0-1|1) in=(0-2|0) at=(0-0) mod=(0-0))"); + assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-1|0) in=(2-5|1) at=(0-1) mod=(0-0) cpy=(o0 => i2))"); } #[test] @@ -1177,8 +1177,8 @@ mod tests { let prog = node_exec.get_prog(); assert_eq!(prog.prog.len(), 2); - assert_eq!(prog.prog[0].to_string(), "Op(i=2 out=(2-3|1) in=(4-6) at=(0-0) mod=(0-0))"); - assert_eq!(prog.prog[1].to_string(), "Op(i=3 out=(3-3|0) in=(6-9) at=(0-1) mod=(0-0) cpy=(o2 => i6))"); + assert_eq!(prog.prog[0].to_string(), "Op(i=2 out=(2-3|1) in=(4-6|0) at=(0-0) mod=(0-0))"); + assert_eq!(prog.prog[1].to_string(), "Op(i=3 out=(3-3|0) in=(6-9|1) at=(0-1) mod=(0-0) cpy=(o2 => i6))"); } #[test] @@ -1278,10 +1278,10 @@ mod tests { node_exec.process_graph_updates(); let prog = node_exec.get_prog(); - assert_eq!(prog.prog[0].to_string(), "Op(i=0 out=(0-1|1) in=(0-2) at=(0-0) mod=(0-1))"); - assert_eq!(prog.prog[1].to_string(), "Op(i=3 out=(3-4|1) in=(6-8) at=(0-0) mod=(5-5))"); - assert_eq!(prog.prog[2].to_string(), "Op(i=1 out=(1-2|1) in=(2-4) at=(0-0) mod=(1-3) cpy=(o0 => i2) mod=1)"); - assert_eq!(prog.prog[3].to_string(), "Op(i=2 out=(2-3|0) in=(4-6) at=(0-0) mod=(3-5) cpy=(o1 => i4) cpy=(o3 => i5) mod=3 mod=4)"); + assert_eq!(prog.prog[0].to_string(), "Op(i=0 out=(0-1|1) in=(0-2|0) at=(0-0) mod=(0-1))"); + assert_eq!(prog.prog[1].to_string(), "Op(i=3 out=(3-4|1) in=(6-8|0) at=(0-0) mod=(5-5))"); + assert_eq!(prog.prog[2].to_string(), "Op(i=1 out=(1-2|1) in=(2-4|1) at=(0-0) mod=(1-3) cpy=(o0 => i2) mod=1)"); + assert_eq!(prog.prog[3].to_string(), "Op(i=2 out=(2-3|0) in=(4-6|3) at=(0-0) mod=(3-5) cpy=(o1 => i4) cpy=(o3 => i5) mod=3 mod=4)"); } #[test] @@ -1315,8 +1315,8 @@ mod tests { node_exec.process_graph_updates(); let prog = node_exec.get_prog(); - assert_eq!(prog.prog[0].to_string(), "Op(i=0 out=(0-1|1) in=(0-2) at=(0-0) mod=(0-1))"); - assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-2|1) in=(2-4) at=(0-0) mod=(1-3) cpy=(o0 => i2) mod=1)"); - assert_eq!(prog.prog[2].to_string(), "Op(i=2 out=(2-3|0) in=(4-6) at=(0-0) mod=(3-3) cpy=(o1 => i4))"); + assert_eq!(prog.prog[0].to_string(), "Op(i=0 out=(0-1|1) in=(0-2|0) at=(0-0) mod=(0-1))"); + assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-2|1) in=(2-4|1) at=(0-0) mod=(1-3) cpy=(o0 => i2) mod=1)"); + assert_eq!(prog.prog[2].to_string(), "Op(i=2 out=(2-3|0) in=(4-6|1) at=(0-0) mod=(3-3) cpy=(o1 => i4))"); } } diff --git a/src/nodes/node_conf.rs b/src/nodes/node_conf.rs index fc0f52c..47a0db8 100644 --- a/src/nodes/node_conf.rs +++ b/src/nodes/node_conf.rs @@ -81,6 +81,7 @@ impl NodeInstance { at_idxlen: (self.at_start, self.at_end), mod_idxlen: (self.mod_start, self.mod_end), out_connected: 0x0, + in_connected: 0x0, inputs: vec![], } } diff --git a/src/nodes/node_exec.rs b/src/nodes/node_exec.rs index 91b11bc..46978b1 100644 --- a/src/nodes/node_exec.rs +++ b/src/nodes/node_exec.rs @@ -449,6 +449,7 @@ impl NodeExecutor { exec_ctx, &NodeContext { out_connected: op.out_connected, + in_connected: op.in_connected, params: &prog.inp[inp.0..inp.1], }, &prog.atoms[at.0..at.1], diff --git a/src/nodes/node_prog.rs b/src/nodes/node_prog.rs index 4f5b119..01859f0 100644 --- a/src/nodes/node_prog.rs +++ b/src/nodes/node_prog.rs @@ -81,12 +81,29 @@ pub struct NodeOp { /// (, , /// (, )) pub inputs: Vec<(usize, usize, Option)>, + /// A bit mask which indicates which of the input ports are actually + /// used/connected to some output. + pub in_connected: u64, /// A bit mask which indicates which of the output ports are actually /// used/connected to some input. pub out_connected: u64, } impl NodeOp { + pub fn in_idx_belongs_to_nodeop(&self, idx: usize) -> bool { + idx >= self.in_idxlen.0 + && idx < self.in_idxlen.1 + } + + pub fn set_in_idx_connected_flag(&mut self, global_idx: usize) { + if !self.in_idx_belongs_to_nodeop(global_idx) { + return; + } + + let local_idx = global_idx - self.in_idxlen.0; + self.in_connected |= 0x1 << local_idx; + } + pub fn out_idx_belongs_to_nodeop(&self, idx: usize) -> bool { idx >= self.out_idxlen.0 && idx < self.out_idxlen.1 @@ -104,13 +121,14 @@ impl NodeOp { impl std::fmt::Display for NodeOp { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "Op(i={} out=({}-{}|{:x}) in=({}-{}) at=({}-{}) mod=({}-{})", + write!(f, "Op(i={} out=({}-{}|{:x}) in=({}-{}|{:x}) at=({}-{}) mod=({}-{})", self.idx, self.out_idxlen.0, self.out_idxlen.1, self.out_connected, self.in_idxlen.0, self.in_idxlen.1, + self.in_connected, self.at_idxlen.0, self.at_idxlen.1, self.mod_idxlen.0, @@ -264,6 +282,7 @@ impl NodeProg { } node_op.out_connected = 0x0; + node_op.in_connected = 0x0; self.prog.push(node_op); } @@ -282,6 +301,7 @@ impl NodeProg { for n_op in self.prog.iter_mut() { if n_op.idx == node_op.idx { + n_op.set_in_idx_connected_flag(inp_index); n_op.inputs.push((out_index, inp_index, mod_index)); return; } diff --git a/tests/node_test.rs b/tests/node_test.rs index 42ff0a3..80cbcff 100644 --- a/tests/node_test.rs +++ b/tests/node_test.rs @@ -79,3 +79,30 @@ fn check_node_test_out_connected() { assert_decimated_feq!(res.0, 1, vec![ mask as f32; 10 ]); assert_decimated_feq!(res.1, 1, vec![ 0.0; 10 ]); } + +#[test] +fn check_node_test_in_connected() { + let (node_conf, mut node_exec) = new_node_engine(); + let mut matrix = Matrix::new(node_conf, 6, 3); + + let test = NodeId::Test(0); + let tst2 = NodeId::Test(1); + let out = NodeId::Out(0); + matrix.place(0, 0, Cell::empty(test) + .out(None, None, test.out("sig"))); + matrix.place(0, 1, Cell::empty(tst2) + .input(tst2.inp("f"), None, None) + .out(None, None, test.out("out3"))); + matrix.place(0, 2, Cell::empty(out) + .input(out.inp("ch1"), None, None)); + matrix.sync().unwrap(); + + let res = run_for_ms(&mut node_exec, 2.0); + assert_decimated_feq!(res.0, 1, vec![ 1.0; 10 ]); + + matrix.place(0, 0, Cell::empty(NodeId::Nop)); + matrix.sync().unwrap(); + + let res = run_for_ms(&mut node_exec, 2.0); + assert_decimated_feq!(res.0, 1, vec![ 0.0; 10 ]); +}