Implemented a bitmask to enable nodes to not produce output if it is not used.
This commit is contained in:
parent
967535d771
commit
26830e8e56
19 changed files with 218 additions and 73 deletions
|
@ -76,6 +76,18 @@ pub const MIDI_MAX_FREQ : f32 = 13289.75;
|
|||
|
||||
pub const MAX_BLOCK_SIZE : usize = 128;
|
||||
|
||||
|
||||
/// A context structure that holds temporary information about the
|
||||
/// currently executed node.
|
||||
/// This structure is created by the [crate::nodes::NodeExecutor] on the fly.
|
||||
pub struct NodeContext<'a> {
|
||||
/// The bitmask that indicates which output ports are used/connected
|
||||
/// to some input.
|
||||
pub out_connected: u64,
|
||||
/// The node parameters, which are usually not accessed directly.
|
||||
pub params: &'a [ProcBuf],
|
||||
}
|
||||
|
||||
/// This trait is an interface between the graph functions
|
||||
/// and the AtomDataModel of the UI.
|
||||
pub trait GraphAtomData {
|
||||
|
@ -116,8 +128,9 @@ pub trait DspNode {
|
|||
/// * `outputs` are the output buffers of this node.
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], led: LedPhaseVals);
|
||||
nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf], outputs: &mut [ProcBuf],
|
||||
led: LedPhaseVals);
|
||||
|
||||
/// A function factory for generating a graph for the generic node UI.
|
||||
fn graph_fun() -> Option<GraphFun> { None }
|
||||
|
@ -564,7 +577,11 @@ macro_rules! node_list {
|
|||
{1 0 p param(0.0) fa_test_s 0 10}
|
||||
{2 1 trig param(0.0) fa_test_s 0 0}
|
||||
[0 sig]
|
||||
[1 tsig],
|
||||
[1 tsig]
|
||||
[2 out2]
|
||||
[3 out3]
|
||||
[4 out4]
|
||||
[5 outc],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1119,6 +1136,15 @@ macro_rules! make_node_info_enum {
|
|||
})+
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub mod out_buf {
|
||||
$(pub mod $variant {
|
||||
$(#[inline] pub fn $out(outputs: &mut [crate::dsp::ProcBuf]) -> crate::dsp::ProcBuf {
|
||||
outputs[$out_idx]
|
||||
})*
|
||||
})+
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub mod out_idx {
|
||||
$(pub mod $variant {
|
||||
|
@ -1126,6 +1152,15 @@ macro_rules! make_node_info_enum {
|
|||
})+
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub mod is_out_con {
|
||||
$(pub mod $variant {
|
||||
$(#[inline] pub fn $out(nctx: &crate::dsp::NodeContext) -> bool {
|
||||
nctx.out_connected & (1 << $out_idx) != 0x0
|
||||
})*
|
||||
})+
|
||||
}
|
||||
|
||||
mod ni {
|
||||
$(
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -1441,8 +1476,8 @@ impl Node {
|
|||
#[inline]
|
||||
pub fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], params: &[ProcBuf],
|
||||
inputs: &[ProcBuf], outputs: &mut [ProcBuf],
|
||||
nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf], outputs: &mut [ProcBuf],
|
||||
led: LedPhaseVals)
|
||||
{
|
||||
macro_rules! make_node_process {
|
||||
|
@ -1462,7 +1497,7 @@ impl Node {
|
|||
match self {
|
||||
Node::$v1 => {},
|
||||
$(Node::$variant { node } =>
|
||||
node.process(ctx, ectx, atoms, params,
|
||||
node.process(ctx, ectx, nctx, atoms,
|
||||
inputs, outputs, led),)+
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{
|
||||
NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals,
|
||||
GraphAtomData, GraphFun,
|
||||
GraphAtomData, GraphFun, NodeContext,
|
||||
};
|
||||
use super::helpers::{Trigger, TrigSignal, sqrt4_to_pow4};
|
||||
|
||||
|
@ -120,7 +120,8 @@ impl DspNode for Ad {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{out, inp, denorm, at};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
use crate::dsp::helpers::AllPass;
|
||||
|
||||
/// A simple amplifier
|
||||
|
@ -82,7 +82,8 @@ impl DspNode for AllP {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
_atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
_atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{out, inp, denorm};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fa_amp_neg_att { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||
|
@ -71,7 +71,8 @@ impl DspNode for Amp {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{out, inp, denorm, denorm_v, inp_dir, at};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
use crate::dsp::helpers::{DelayBuffer, crossfade, TriggerSampleClock};
|
||||
|
||||
#[macro_export]
|
||||
|
@ -91,7 +91,8 @@ impl DspNode for Delay {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{at, out, inp, denorm};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
|
||||
/// A simple amplifier
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -54,7 +54,8 @@ impl DspNode for FbWr {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, ectx: &mut NodeExecContext,
|
||||
_atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
_atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
_outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{inp};
|
||||
|
@ -126,7 +127,8 @@ impl DspNode for FbRd {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, ectx: &mut NodeExecContext,
|
||||
_atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
_atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{out, inp, denorm};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fa_map_clip { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||
|
@ -91,7 +91,8 @@ impl DspNode for Map {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{out, inp, at};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
use crate::dsp::helpers::Rng;
|
||||
|
||||
#[macro_export]
|
||||
|
@ -84,7 +84,8 @@ impl DspNode for Noise {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{at, out, inp, denorm};
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, inp, at, denorm, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{
|
||||
NodeId, SAtom, ProcBuf, inp, at, denorm, DspNode, LedPhaseVals, NodeContext};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fa_out_mono { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||
|
@ -81,7 +82,8 @@ impl DspNode for Out {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
_outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
let in1 = inp::Out::ch1(inputs);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
use crate::dsp::{out, at, inp, denorm, denorm_offs}; //, inp, denorm, denorm_v, inp_dir, at};
|
||||
use super::helpers::Trigger;
|
||||
|
||||
|
@ -370,7 +370,8 @@ impl DspNode for Sampl {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
let sample = at::Sampl::sample(atoms);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{
|
||||
NodeId, SAtom, ProcBuf, denorm_offs,
|
||||
out, inp, DspNode, LedPhaseVals
|
||||
out, inp, DspNode, LedPhaseVals, NodeContext
|
||||
};
|
||||
use crate::dsp::helpers::fast_sin;
|
||||
|
||||
|
@ -76,7 +76,8 @@ impl DspNode for Sin {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
_atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
_atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
let o = out::Sin::sig(outputs);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! fa_smap_clip { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||
|
@ -98,7 +98,8 @@ impl DspNode for SMap {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{out, inp, at};
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, GraphFun, GraphAtomData, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{
|
||||
NodeId, SAtom, ProcBuf, GraphFun, GraphAtomData, DspNode, LedPhaseVals,
|
||||
NodeContext
|
||||
};
|
||||
use crate::dsp::helpers::{TrigSignal};
|
||||
|
||||
#[macro_export]
|
||||
|
@ -46,6 +49,10 @@ impl Test {
|
|||
pub const trig: &'static str = "Test trig\nA trigger input, that will create a short pulse on the 'tsig' output.\nRange: (-1..1)";
|
||||
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 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!";
|
||||
|
||||
pub const DESC : &'static str = r#""#;
|
||||
pub const HELP : &'static str = r#""#;
|
||||
|
@ -66,14 +73,18 @@ impl DspNode for Test {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], _inputs: &[ProcBuf],
|
||||
nctx: &NodeContext,
|
||||
atoms: &[SAtom], _inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], _led: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{out_idx, at};
|
||||
use crate::dsp::{out_idx, at, is_out_con, out_buf};
|
||||
|
||||
let p = at::Test::p(atoms);
|
||||
let trig = at::Test::trig(atoms);
|
||||
let tsig = out_idx::Test::tsig();
|
||||
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 outc = out_buf::Test::outc(outputs);
|
||||
|
||||
let (out, tsig) = outputs.split_at_mut(tsig);
|
||||
let out = &mut out[0];
|
||||
|
@ -99,6 +110,10 @@ impl DspNode for Test {
|
|||
out.write(frame, p.f());
|
||||
let t = self.trig_sig.next();
|
||||
tsig.write(frame, t);
|
||||
|
||||
out2.write(frame,
|
||||
if is_out_con::Test::sig(nctx) { 1.0 } else { 0.0 });
|
||||
outc.write(frame, nctx.out_connected as f32);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::dsp::helpers::{TriggerPhaseClock, Trigger};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals};
|
||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||
use crate::dsp::tracker::TrackerBackend;
|
||||
|
||||
use crate::dsp::MAX_BLOCK_SIZE;
|
||||
|
@ -180,7 +180,8 @@ impl DspNode for TSeq {
|
|||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self, ctx: &mut T, _ectx: &mut NodeExecContext,
|
||||
atoms: &[SAtom], _params: &[ProcBuf], inputs: &[ProcBuf],
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom], inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf], ctx_vals: LedPhaseVals)
|
||||
{
|
||||
use crate::dsp::{out, inp, at, denorm};
|
||||
|
|
|
@ -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) in=(0-2) at=(0-0) mod=(0-0))");
|
||||
assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-2) 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) 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) 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))");
|
||||
}
|
||||
|
||||
#[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) in=(0-2) at=(0-0) mod=(0-0))");
|
||||
assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-1) 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) 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))");
|
||||
}
|
||||
|
||||
#[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) in=(4-6) at=(0-0) mod=(0-0))");
|
||||
assert_eq!(prog.prog[1].to_string(), "Op(i=3 out=(3-3) 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) 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))");
|
||||
}
|
||||
|
||||
#[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) in=(0-2) at=(0-0) mod=(0-1))");
|
||||
assert_eq!(prog.prog[1].to_string(), "Op(i=3 out=(3-4) in=(6-8) at=(0-0) mod=(5-5))");
|
||||
assert_eq!(prog.prog[2].to_string(), "Op(i=1 out=(1-2) 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) 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) 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)");
|
||||
}
|
||||
|
||||
#[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) in=(0-2) at=(0-0) mod=(0-1))");
|
||||
assert_eq!(prog.prog[1].to_string(), "Op(i=1 out=(1-2) 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) 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) 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))");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,17 +56,17 @@ impl NodeInstance {
|
|||
pub fn new(id: NodeId) -> Self {
|
||||
Self {
|
||||
id,
|
||||
in_use: false,
|
||||
prog_idx: 0,
|
||||
out_start: 0,
|
||||
out_end: 0,
|
||||
in_start: 0,
|
||||
in_end: 0,
|
||||
at_start: 0,
|
||||
at_end: 0,
|
||||
mod_start: 0,
|
||||
mod_end: 0,
|
||||
in2mod_map: [None; MAX_INPUTS],
|
||||
in_use: false,
|
||||
prog_idx: 0,
|
||||
out_start: 0,
|
||||
out_end: 0,
|
||||
in_start: 0,
|
||||
in_end: 0,
|
||||
at_start: 0,
|
||||
at_end: 0,
|
||||
mod_start: 0,
|
||||
mod_end: 0,
|
||||
in2mod_map: [None; MAX_INPUTS],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,12 +75,13 @@ impl NodeInstance {
|
|||
|
||||
pub fn as_op(&self) -> NodeOp {
|
||||
NodeOp {
|
||||
idx: self.prog_idx as u8,
|
||||
out_idxlen: (self.out_start, self.out_end),
|
||||
in_idxlen: (self.in_start, self.in_end),
|
||||
at_idxlen: (self.at_start, self.at_end),
|
||||
mod_idxlen: (self.mod_start, self.mod_end),
|
||||
inputs: vec![],
|
||||
idx: self.prog_idx as u8,
|
||||
out_idxlen: (self.out_start, self.out_end),
|
||||
in_idxlen: (self.in_start, self.in_end),
|
||||
at_idxlen: (self.at_start, self.at_end),
|
||||
mod_idxlen: (self.mod_start, self.mod_end),
|
||||
out_connected: 0x0,
|
||||
inputs: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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, MAX_BLOCK_SIZE};
|
||||
use crate::dsp::{NodeId, Node, NodeContext, MAX_BLOCK_SIZE};
|
||||
use crate::util::{Smoother, AtomicFloat};
|
||||
use crate::monitor::{MonitorBackend, MON_SIG_CNT};
|
||||
|
||||
|
@ -447,8 +447,11 @@ impl NodeExecutor {
|
|||
.process(
|
||||
ctx,
|
||||
exec_ctx,
|
||||
&NodeContext {
|
||||
out_connected: op.out_connected,
|
||||
params: &prog.inp[inp.0..inp.1],
|
||||
},
|
||||
&prog.atoms[at.0..at.1],
|
||||
&prog.inp[inp.0..inp.1],
|
||||
&prog.cur_inp[inp.0..inp.1],
|
||||
&mut prog.out[out.0..out.1],
|
||||
&ctx_vals[ctx_idx..ctx_idx + 2]);
|
||||
|
|
|
@ -81,14 +81,34 @@ pub struct NodeOp {
|
|||
/// (<out vec index>, <own node input index>,
|
||||
/// (<mod index into NodeProg::modops>, <mod amt>))
|
||||
pub inputs: Vec<(usize, usize, Option<usize>)>,
|
||||
/// 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 out_idx_belongs_to_nodeop(&self, idx: usize) -> bool {
|
||||
idx >= self.out_idxlen.0
|
||||
&& idx < self.out_idxlen.1
|
||||
}
|
||||
|
||||
pub fn set_out_idx_connected_flag(&mut self, global_idx: usize) {
|
||||
if !self.out_idx_belongs_to_nodeop(global_idx) {
|
||||
return;
|
||||
}
|
||||
|
||||
let local_idx = global_idx - self.out_idxlen.0;
|
||||
self.out_connected |= 0x1 << local_idx;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for NodeOp {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Op(i={} out=({}-{}) in=({}-{}) at=({}-{}) mod=({}-{})",
|
||||
write!(f, "Op(i={} out=({}-{}|{:x}) in=({}-{}) at=({}-{}) mod=({}-{})",
|
||||
self.idx,
|
||||
self.out_idxlen.0,
|
||||
self.out_idxlen.1,
|
||||
self.out_connected,
|
||||
self.in_idxlen.0,
|
||||
self.in_idxlen.1,
|
||||
self.at_idxlen.0,
|
||||
|
@ -167,7 +187,6 @@ impl Drop for NodeProg {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl NodeProg {
|
||||
pub fn empty() -> Self {
|
||||
let out_fb = vec![];
|
||||
|
@ -237,13 +256,14 @@ impl NodeProg {
|
|||
&mut self.modops
|
||||
}
|
||||
|
||||
pub fn append_op(&mut self, node_op: NodeOp) {
|
||||
pub fn append_op(&mut self, mut node_op: NodeOp) {
|
||||
for n_op in self.prog.iter_mut() {
|
||||
if n_op.idx == node_op.idx {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
node_op.out_connected = 0x0;
|
||||
self.prog.push(node_op);
|
||||
}
|
||||
|
||||
|
@ -254,6 +274,12 @@ impl NodeProg {
|
|||
out_index: usize,
|
||||
mod_index: Option<usize>)
|
||||
{
|
||||
for n_op in self.prog.iter_mut() {
|
||||
if n_op.out_idx_belongs_to_nodeop(out_index) {
|
||||
n_op.set_out_idx_connected_flag(out_index);
|
||||
}
|
||||
}
|
||||
|
||||
for n_op in self.prog.iter_mut() {
|
||||
if n_op.idx == node_op.idx {
|
||||
n_op.inputs.push((out_index, inp_index, mod_index));
|
||||
|
|
|
@ -28,3 +28,54 @@ fn check_node_test_1() {
|
|||
let res = run_for_ms(&mut node_exec, 1.0);
|
||||
assert_decimated_feq!(res.0, 1, vec![ 0.0; 10 ]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_node_test_out_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 out = NodeId::Out(0);
|
||||
let sin = NodeId::Sin(0);
|
||||
let sin2 = NodeId::Sin(1);
|
||||
let sin3 = NodeId::Sin(2);
|
||||
matrix.place(0, 0, Cell::empty(test)
|
||||
.out(None, None, test.out("outc")));
|
||||
matrix.place(0, 1, Cell::empty(out)
|
||||
.input(out.inp("ch1"), None, None));
|
||||
|
||||
matrix.place(1, 0, Cell::empty(test)
|
||||
.out(None, None, test.out("out2")));
|
||||
matrix.place(1, 1, Cell::empty(out)
|
||||
.input(out.inp("ch2"), None, None));
|
||||
|
||||
matrix.place(2, 0, Cell::empty(test)
|
||||
.out(None, None, test.out("out3")));
|
||||
matrix.place(2, 1, Cell::empty(sin)
|
||||
.input(sin.inp("freq"), None, None));
|
||||
|
||||
matrix.place(3, 0, Cell::empty(test)
|
||||
.out(None, None, test.out("out4")));
|
||||
matrix.place(3, 1, Cell::empty(sin2)
|
||||
.input(sin2.inp("freq"), None, None));
|
||||
|
||||
matrix.place(4, 0, Cell::empty(test)
|
||||
.out(None, None, test.out("sig")));
|
||||
matrix.place(4, 1, Cell::empty(sin3)
|
||||
.input(sin3.inp("freq"), None, None));
|
||||
matrix.sync().unwrap();
|
||||
|
||||
let res = run_for_ms(&mut node_exec, 2.0);
|
||||
let mask = 0x01 | 0x04 | 0x08 | 0x10 | 0x20;
|
||||
assert_decimated_feq!(res.0, 1, vec![ mask as f32; 10 ]);
|
||||
assert_decimated_feq!(res.1, 1, vec![ 1.0; 10 ]);
|
||||
|
||||
// Remove a connection for testing:
|
||||
matrix.place(1, 1, Cell::empty(NodeId::Nop));
|
||||
matrix.sync().unwrap();
|
||||
|
||||
let res = run_for_ms(&mut node_exec, 2.0);
|
||||
let mask = 0x01 | 0x08 | 0x10 | 0x20;
|
||||
assert_decimated_feq!(res.0, 1, vec![ mask as f32; 10 ]);
|
||||
assert_decimated_feq!(res.1, 1, vec![ 0.0; 10 ]);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue