// Copyright (c) 2021 Weird Constructor // 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}; #[cfg(feature = "wblockdsp")] use crate::wblockdsp::CodeEngineBackend; use crate::dsp::MAX_BLOCK_SIZE; /// A WBlockDSP code execution node for JIT'ed DSP code pub struct Code { #[cfg(feature = "wblockdsp")] backend: Option>, 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 { #[cfg(feature = "wblockdsp")] backend: None, srate: 48000.0, } } #[cfg(feature = "wblockdsp")] 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; #[cfg(feature = "wblockdsp")] if let Some(backend) = self.backend.as_mut() { backend.set_sample_rate(srate); } } fn reset(&mut self) { #[cfg(feature = "wblockdsp")] if let Some(backend) = self.backend.as_mut() { backend.clear(); } } #[inline] fn process( &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 out = out::Code::sig(outputs); #[cfg(feature = "wblockdsp")] { 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); out.write(frame, ret); } ctx_vals[0].set(0.0); ctx_vals[1].set(0.0); } } }