Added Code node
This commit is contained in:
parent
36b76f5388
commit
70f369af70
5 changed files with 147 additions and 16 deletions
|
@ -537,6 +537,8 @@ mod node_tseq;
|
|||
mod node_tslfo;
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod node_vosc;
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod node_code;
|
||||
|
||||
pub mod biquad;
|
||||
pub mod dattorro;
|
||||
|
@ -607,6 +609,7 @@ use node_sin::Sin;
|
|||
use node_smap::SMap;
|
||||
use node_test::Test;
|
||||
use node_tseq::TSeq;
|
||||
use node_code::Code;
|
||||
use node_tslfo::TsLFO;
|
||||
use node_vosc::VOsc;
|
||||
|
||||
|
@ -1367,11 +1370,21 @@ macro_rules! node_list {
|
|||
[9 gat4]
|
||||
[10 gat5]
|
||||
[11 gat6],
|
||||
code => Code UIType::Generic UICategory::Signal
|
||||
(0 in1 n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
(1 in2 n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
(2 alpha n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
(3 beta n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
(4 delta n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
(5 gamma n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
[0 sig]
|
||||
[1 sig1]
|
||||
[2 sig2],
|
||||
sampl => Sampl UIType::Generic UICategory::Osc
|
||||
(0 freq n_pit d_pit r_fq f_def stp_d -1.0, 0.564713133, 440.0)
|
||||
(1 trig n_id n_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
(2 offs n_id n_id r_id f_def stp_d 0.0, 1.0, 0.0)
|
||||
(3 len n_id n_id r_id f_def stp_d 0.0, 1.0, 1.0)
|
||||
(1 trig n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
(2 offs n_id d_id r_id f_def stp_d 0.0, 1.0, 0.0)
|
||||
(3 len n_id d_id r_id f_def stp_d 0.0, 1.0, 1.0)
|
||||
(4 dcms n_declick d_declick r_dc_ms f_ms stp_m 0.0, 1.0, 3.0)
|
||||
(5 det n_det d_det r_det f_det stp_f -0.2, 0.2, 0.0)
|
||||
{6 0 sample audio_unloaded("") sample f_def 0 0}
|
||||
|
|
109
src/dsp/node_code.rs
Normal file
109
src/dsp/node_code.rs
Normal file
|
@ -0,0 +1,109 @@
|
|||
// Copyright (c) 2021 Weird Constructor <weirdconstructor@gmail.com>
|
||||
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
|
||||
// See README.md and COPYING for details.
|
||||
|
||||
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
|
||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||
use crate::wblockdsp::CodeEngineBackend;
|
||||
|
||||
use crate::dsp::MAX_BLOCK_SIZE;
|
||||
|
||||
/// A WBlockDSP code execution node for JIT'ed DSP code
|
||||
pub struct Code {
|
||||
backend: Option<Box<CodeEngineBackend>>,
|
||||
srate: f64,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Code {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
write!(f, "Code")
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Code {
|
||||
fn clone(&self) -> Self {
|
||||
Self::new(&NodeId::Nop)
|
||||
}
|
||||
}
|
||||
|
||||
impl Code {
|
||||
pub fn new(_nid: &NodeId) -> Self {
|
||||
Self {
|
||||
backend: None,
|
||||
srate: 48000.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_backend(&mut self, backend: CodeEngineBackend) {
|
||||
self.backend = Some(Box::new(backend));
|
||||
}
|
||||
|
||||
pub const in1: &'static str = "Code in1\nInput Signal 1\nRange: (-1..1)\n";
|
||||
pub const in2: &'static str = "Code in2\nInput Signal 1\nRange: (-1..1)\n";
|
||||
pub const alpha: &'static str = "Code alpha\nInput Parameter Alpha\nRange: (-1..1)\n";
|
||||
pub const beta: &'static str = "Code alpha\nInput Parameter Alpha\nRange: (-1..1)\n";
|
||||
pub const delta: &'static str = "Code alpha\nInput Parameter Alpha\nRange: (-1..1)\n";
|
||||
pub const gamma: &'static str = "Code alpha\nInput Parameter Alpha\nRange: (-1..1)\n";
|
||||
pub const sig: &'static str = "Code sig\nReturn output\nRange: (-1..1)\n";
|
||||
pub const sig1: &'static str = "Code sig1\nSignal channel 1 output\nRange: (-1..1)\n";
|
||||
pub const sig2: &'static str = "Code sig2\nSignal channel 2 output\nRange: (-1..1)\n";
|
||||
|
||||
pub const DESC: &'static str = "WBlockDSP Code Execution\n\n\
|
||||
This node executes just in time compiled code as fast as machine code. \
|
||||
Use this to implement real time DSP code yourself.";
|
||||
pub const HELP: &'static str = r#"WBlockDSP Code Execution
|
||||
|
||||
Do it!
|
||||
"#;
|
||||
}
|
||||
|
||||
impl DspNode for Code {
|
||||
fn outputs() -> usize {
|
||||
3
|
||||
}
|
||||
|
||||
fn set_sample_rate(&mut self, srate: f32) {
|
||||
self.srate = srate as f64;
|
||||
if let Some(backend) = self.backend.as_mut() {
|
||||
backend.set_sample_rate(srate);
|
||||
}
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
if let Some(backend) = self.backend.as_mut() {
|
||||
backend.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn process<T: NodeAudioContext>(
|
||||
&mut self,
|
||||
ctx: &mut T,
|
||||
_ectx: &mut NodeExecContext,
|
||||
_nctx: &NodeContext,
|
||||
atoms: &[SAtom],
|
||||
inputs: &[ProcBuf],
|
||||
outputs: &mut [ProcBuf],
|
||||
ctx_vals: LedPhaseVals,
|
||||
) {
|
||||
use crate::dsp::{at, denorm, inp, out};
|
||||
// let clock = inp::TSeq::clock(inputs);
|
||||
// let trig = inp::TSeq::trig(inputs);
|
||||
// let cmode = at::TSeq::cmode(atoms);
|
||||
|
||||
let backend = if let Some(backend) = &mut self.backend {
|
||||
backend
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
backend.process_updates();
|
||||
|
||||
for frame in 0..ctx.nframes() {
|
||||
let (s1, s2, ret) = backend.process(0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
ctx_vals[0].set(0.0);
|
||||
ctx_vals[1].set(0.0);
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ pub const SCOPE_SAMPLES: usize = 512;
|
|||
pub const MAX_INPUTS: usize = 32;
|
||||
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_CODE_ENGINES: usize = 32;
|
||||
pub const MAX_FB_DELAYS: usize = 256; // 256 feedback delays, thats roughly 1.2MB RAM
|
||||
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.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use super::{
|
||||
FeedbackFilter, GraphMessage, NodeOp, NodeProg, MAX_ALLOCATED_NODES, MAX_AVAIL_TRACKERS,
|
||||
MAX_INPUTS, MAX_SCOPES, UNUSED_MONITOR_IDX,
|
||||
MAX_INPUTS, MAX_SCOPES, UNUSED_MONITOR_IDX, MAX_AVAIL_CODE_ENGINES
|
||||
};
|
||||
use crate::dsp::tracker::{PatternData, Tracker};
|
||||
use crate::dsp::{node_factory, Node, NodeId, NodeInfo, ParamId, SAtom};
|
||||
|
@ -182,6 +182,9 @@ pub struct NodeConfigurator {
|
|||
pub(crate) trackers: Vec<Tracker>,
|
||||
/// Holding the scope buffers:
|
||||
pub(crate) scopes: Vec<Arc<ScopeHandle>>,
|
||||
/// Holding the WBlockDSP code engine backends:
|
||||
#[cfg(feature = "wblockdsp")]
|
||||
pub(crate) code_engines: Vec<CodeEngine>,
|
||||
/// The shared parts of the [NodeConfigurator]
|
||||
/// and the [crate::nodes::NodeExecutor].
|
||||
pub(crate) shared: SharedNodeConf,
|
||||
|
@ -287,6 +290,7 @@ impl NodeConfigurator {
|
|||
atom_values: std::collections::HashMap::new(),
|
||||
node2idx: HashMap::new(),
|
||||
trackers: vec![Tracker::new(); MAX_AVAIL_TRACKERS],
|
||||
code_engines: vec![CodeEngine::new(); MAX_AVAIL_CODE_ENGINES],
|
||||
scopes,
|
||||
},
|
||||
shared_exec,
|
||||
|
|
|
@ -24,9 +24,13 @@ pub struct CodeEngine {
|
|||
dsp_ctx: Rc<RefCell<DSPNodeContext>>,
|
||||
lib: Rc<RefCell<DSPNodeTypeLibrary>>,
|
||||
update_prod: Producer<CodeUpdateMsg>,
|
||||
update_cons: Option<Consumer<CodeUpdateMsg>>,
|
||||
return_cons: Consumer<CodeReturnMsg>,
|
||||
return_prod: Option<Producer<CodeReturnMsg>>,
|
||||
}
|
||||
|
||||
impl Clone for CodeEngine {
|
||||
fn clone(&self) -> Self {
|
||||
CodeEngine::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeEngine {
|
||||
|
@ -42,8 +46,6 @@ impl CodeEngine {
|
|||
lib,
|
||||
dsp_ctx: DSPNodeContext::new_ref(),
|
||||
update_prod,
|
||||
update_cons: Some(update_cons),
|
||||
return_prod: Some(return_prod),
|
||||
return_cons,
|
||||
}
|
||||
}
|
||||
|
@ -75,15 +77,17 @@ impl CodeEngine {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_backend(&mut self) -> Option<CodeEngineBackend> {
|
||||
if let Some(update_cons) = self.update_cons.take() {
|
||||
if let Some(return_prod) = self.return_prod.take() {
|
||||
let function = get_nop_function(self.lib.clone(), self.dsp_ctx.clone());
|
||||
return Some(CodeEngineBackend::new(function, update_cons, return_prod));
|
||||
}
|
||||
}
|
||||
pub fn get_backend(&mut self) -> CodeEngineBackend {
|
||||
let rb = RingBuffer::new(MAX_RINGBUF_SIZE);
|
||||
let (update_prod, update_cons) = rb.split();
|
||||
let rb = RingBuffer::new(MAX_RINGBUF_SIZE);
|
||||
let (return_prod, return_cons) = rb.split();
|
||||
|
||||
None
|
||||
self.update_prod = update_prod;
|
||||
self.return_cons = return_cons;
|
||||
|
||||
let function = get_nop_function(self.lib.clone(), self.dsp_ctx.clone());
|
||||
CodeEngineBackend::new(function, update_cons, return_prod)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue