diff --git a/src/dsp/node_code.rs b/src/dsp/node_code.rs index 2835211..4a23385 100644 --- a/src/dsp/node_code.rs +++ b/src/dsp/node_code.rs @@ -5,7 +5,7 @@ use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom}; use crate::nodes::{NodeAudioContext, NodeExecContext}; #[cfg(feature = "synfx-dsp-jit")] -use crate::wblockdsp::CodeEngineBackend; +use synfx_dsp_jit::engine::CodeEngineBackend; //use crate::dsp::MAX_BLOCK_SIZE; diff --git a/src/lib.rs b/src/lib.rs index 6cae805..f944009 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -321,11 +321,7 @@ pub mod monitor; pub mod nodes; pub mod sample_lib; pub mod scope_handle; -#[cfg(feature="synfx-dsp-jit")] pub mod wblockdsp; -pub mod blocklang; -pub mod blocklang_def; -mod block_compiler; mod util; pub use cell_dir::CellDir; diff --git a/src/matrix.rs b/src/matrix.rs index 9817541..ee2fb50 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -10,8 +10,7 @@ pub use crate::nodes::MinMaxMonitorSamples; use crate::nodes::{NodeConfigurator, NodeGraphOrdering, NodeProg, MAX_ALLOCATED_NODES}; pub use crate::CellDir; use crate::ScopeHandle; -use crate::blocklang::{BlockFun, BlockFunSnapshot}; -use crate::block_compiler::BlkJITCompileError; +use crate::wblockdsp::{BlockFun, BlockFunSnapshot, BlkJITCompileError}; use std::collections::{HashMap, HashSet}; @@ -600,13 +599,13 @@ impl Matrix { /// Checks the block function for the id `id`. If the block function did change, /// updates are then sent to the audio thread. - /// See also [get_block_function]. + /// See also [Matrix::get_block_function]. pub fn check_block_function(&mut self, id: usize) -> Result<(), BlkJITCompileError> { self.config.check_block_function(id) } /// Retrieve a handle to the block function `id`. In case you modify the block function, - /// make sure to call [check_block_function]. + /// make sure to call [Matrix::check_block_function]. pub fn get_block_function(&self, id: usize) -> Option>> { self.config.get_block_function(id) } diff --git a/src/matrix_repr.rs b/src/matrix_repr.rs index 6611d0a..3d34aa3 100644 --- a/src/matrix_repr.rs +++ b/src/matrix_repr.rs @@ -4,7 +4,7 @@ use crate::dsp::{NodeId, ParamId, SAtom}; use serde_json::{json, Value}; -use crate::blocklang::BlockFunSnapshot; +use crate::wblockdsp::BlockFunSnapshot; #[derive(Debug, Clone, Copy)] pub struct CellRepr { diff --git a/src/nodes/node_conf.rs b/src/nodes/node_conf.rs index 2403b4c..4fb8f50 100644 --- a/src/nodes/node_conf.rs +++ b/src/nodes/node_conf.rs @@ -6,15 +6,13 @@ use super::{ FeedbackFilter, GraphMessage, NodeOp, NodeProg, MAX_ALLOCATED_NODES, MAX_AVAIL_CODE_ENGINES, MAX_AVAIL_TRACKERS, MAX_INPUTS, MAX_SCOPES, UNUSED_MONITOR_IDX, }; -use crate::block_compiler::{BlkJITCompileError, Block2JITCompiler}; -use crate::blocklang::*; -use crate::blocklang_def; +use crate::wblockdsp::*; use crate::dsp::tracker::{PatternData, Tracker}; use crate::dsp::{node_factory, Node, NodeId, NodeInfo, ParamId, SAtom}; use crate::monitor::{new_monitor_processor, MinMaxMonitorSamples, Monitor, MON_SIG_CNT}; use crate::nodes::drop_thread::DropThread; #[cfg(feature = "synfx-dsp-jit")] -use crate::wblockdsp::CodeEngine; +use synfx_dsp_jit::engine::CodeEngine; use crate::SampleLibrary; use crate::ScopeHandle; @@ -190,7 +188,7 @@ pub struct NodeConfigurator { pub(crate) code_engines: Vec, /// Holds the block functions that are JIT compiled to DSP code /// for the `Code` nodes. The code is then sent via the [CodeEngine] - /// in [check_block_function]. + /// in [NodeConfigurator::check_block_function]. #[cfg(feature = "synfx-dsp-jit")] pub(crate) block_functions: Vec<(u64, Arc>)>, /// The shared parts of the [NodeConfigurator] @@ -284,9 +282,9 @@ impl NodeConfigurator { #[cfg(feature = "synfx-dsp-jit")] let (code_engines, block_functions) = { - let code_engines = vec![CodeEngine::new(); MAX_AVAIL_CODE_ENGINES]; + let code_engines = vec![CodeEngine::new_stdlib(); MAX_AVAIL_CODE_ENGINES]; - let lang = blocklang_def::setup_hxdsp_block_language(code_engines[0].get_lib()); + let lang = setup_hxdsp_block_language(code_engines[0].get_lib()); let mut block_functions = vec![]; block_functions.resize_with(MAX_AVAIL_CODE_ENGINES, || { (0, Arc::new(Mutex::new(BlockFun::new(lang.clone())))) @@ -703,7 +701,7 @@ impl NodeConfigurator { /// Checks the block function for the id `id`. If the block function did change, /// updates are then sent to the audio thread. - /// See also [get_block_function]. + /// See also [NodeConfigurator::get_block_function]. pub fn check_block_function(&mut self, id: usize) -> Result<(), BlkJITCompileError> { #[cfg(feature = "synfx-dsp-jit")] if let Some((generation, block_fun)) = self.block_functions.get_mut(id) { @@ -727,7 +725,7 @@ impl NodeConfigurator { } /// Retrieve a handle to the block function `id`. In case you modify the block function, - /// make sure to call [check_block_function]. + /// make sure to call [NodeConfigurator::check_block_function]. pub fn get_block_function(&self, id: usize) -> Option>> { #[cfg(feature = "synfx-dsp-jit")] { diff --git a/src/wblockdsp.rs b/src/wblockdsp.rs deleted file mode 100644 index e056a02..0000000 --- a/src/wblockdsp.rs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2022 Weird Constructor -// This file is a part of HexoDSP. Released under GPL-3.0-or-later. -// See README.md and COPYING for details. - -use synfx_dsp_jit::*; - -use ringbuf::{Consumer, Producer, RingBuffer}; -use std::cell::RefCell; -use std::rc::Rc; - -const MAX_RINGBUF_SIZE: usize = 128; - -enum CodeUpdateMsg { - UpdateFun(Box), -} - -enum CodeReturnMsg { - DestroyFun(Box), -} - -pub struct CodeEngine { - dsp_ctx: Rc>, - lib: Rc>, - update_prod: Producer, - return_cons: Consumer, -} - -impl Clone for CodeEngine { - fn clone(&self) -> Self { - CodeEngine::new() - } -} - -impl CodeEngine { - pub fn new() -> Self { - 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(); - - let lib = get_standard_library(); - - Self { lib, dsp_ctx: DSPNodeContext::new_ref(), update_prod, return_cons } - } - - pub fn get_lib(&self) -> Rc> { - self.lib.clone() - } - - pub fn upload(&mut self, ast: Box) -> Result<(), JITCompileError> { - let jit = JIT::new(self.lib.clone(), self.dsp_ctx.clone()); - let fun = jit.compile(ASTFun::new(ast))?; - let _ = self.update_prod.push(CodeUpdateMsg::UpdateFun(fun)); - - Ok(()) - } - - pub fn cleanup(&self, fun: Box) { - self.dsp_ctx.borrow_mut().cleanup_dsp_fun_after_user(fun); - } - - pub fn query_returns(&mut self) { - while let Some(msg) = self.return_cons.pop() { - match msg { - CodeReturnMsg::DestroyFun(fun) => { - self.cleanup(fun); - } - } - } - } - - 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(); - - 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) - } -} - -impl Drop for CodeEngine { - fn drop(&mut self) { - self.dsp_ctx.borrow_mut().free(); - } -} - -pub struct CodeEngineBackend { - sample_rate: f32, - function: Box, - update_cons: Consumer, - return_prod: Producer, -} - -impl CodeEngineBackend { - fn new( - function: Box, - update_cons: Consumer, - return_prod: Producer, - ) -> Self { - Self { sample_rate: 0.0, function, update_cons, return_prod } - } - - #[inline] - pub fn process( - &mut self, - in1: f32, - in2: f32, - a: f32, - b: f32, - d: f32, - g: f32, - ) -> (f32, f32, f32) { - let mut s1 = 0.0_f64; - let mut s2 = 0.0_f64; - let res = self - .function - .exec(in1 as f64, in2 as f64, a as f64, b as f64, d as f64, g as f64, &mut s1, &mut s2); - (s1 as f32, s2 as f32, res as f32) - } - - pub fn swap_fun(&mut self, srate: f32, mut fun: Box) -> Box { - std::mem::swap(&mut self.function, &mut fun); - self.function.init(srate as f64, Some(&fun)); - fun - } - - pub fn set_sample_rate(&mut self, srate: f32) { - self.sample_rate = srate; - self.function.set_sample_rate(srate as f64); - } - - pub fn clear(&mut self) { - self.function.reset(); - } - - pub fn process_updates(&mut self) { - while let Some(msg) = self.update_cons.pop() { - match msg { - CodeUpdateMsg::UpdateFun(mut fun) => { - std::mem::swap(&mut self.function, &mut fun); - self.function.init(self.sample_rate as f64, Some(&fun)); - let _ = self.return_prod.push(CodeReturnMsg::DestroyFun(fun)); - } - } - } - } -} diff --git a/src/block_compiler.rs b/src/wblockdsp/compiler.rs similarity index 83% rename from src/block_compiler.rs rename to src/wblockdsp/compiler.rs index 44bbe83..608dc46 100644 --- a/src/block_compiler.rs +++ b/src/wblockdsp/compiler.rs @@ -6,7 +6,7 @@ use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; -use crate::blocklang::*; +use super::language::*; #[cfg(feature = "synfx-dsp-jit")] use synfx_dsp_jit::{ASTNode, JITCompileError}; @@ -18,6 +18,8 @@ struct JASTNode { nodes: Vec<(String, String, ASTNodeRef)>, } +/// The WBlockDSP Abstract Syntax Tree. It is generated by [BlockFun::generate_tree] +/// in [Block2JITCompiler::compile]. #[derive(Debug, Clone)] pub struct ASTNodeRef(Rc>); @@ -37,18 +39,26 @@ impl BlockASTNode for ASTNodeRef { } impl ASTNodeRef { + /// Returns the first child AST node. pub fn first_child_ref(&self) -> Option { self.0.borrow().nodes.get(0).map(|n| n.2.clone()) } + /// Returns the first child, including input/output info. pub fn first_child(&self) -> Option<(String, String, ASTNodeRef)> { self.0.borrow().nodes.get(0).cloned() } + /// Returns the nth child, including input/output info. pub fn nth_child(&self, i: usize) -> Option<(String, String, ASTNodeRef)> { self.0.borrow().nodes.get(i).cloned() } + /// Generates a recursive tree dump output. + /// + ///```ignore + /// println!("{}", node.walk_dump("", "", 0)); + ///``` pub fn walk_dump(&self, input: &str, output: &str, indent: usize) -> String { let indent_str = " ".repeat(indent + 1); @@ -528,17 +538,21 @@ mod test { }; } + fn put_n(bf: &mut BlockFun, a: usize, x: i64, y: i64, s: &str) { + bf.instanciate_at(a, x, y, s, None).expect("no put error"); + } + + fn put_v(bf: &mut BlockFun, a: usize, x: i64, y: i64, s: &str, v: &str) { + bf.instanciate_at(a, x, y, s, Some(v.to_string())).expect("no put error"); + } + use synfx_dsp_jit::{get_standard_library, ASTFun, DSPFunction, DSPNodeContext, JIT}; fn new_jit_fun( mut f: F, ) -> (Rc>, Box) { - use crate::block_compiler::{BlkJITCompileError, Block2JITCompiler}; - use crate::blocklang::BlockFun; - use crate::blocklang_def; - let lib = get_standard_library(); - let lang = blocklang_def::setup_hxdsp_block_language(lib.clone()); + let lang = crate::wblockdsp::setup_hxdsp_block_language(lib.clone()); let mut bf = BlockFun::new(lang.clone()); f(&mut bf); @@ -557,11 +571,11 @@ mod test { #[test] fn check_blocklang_sig1() { let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap(); - bf.instanciate_at(0, 1, 1, "set", Some("&sig1".to_string())).unwrap(); - bf.instanciate_at(0, 0, 2, "value", Some("-0.3".to_string())).unwrap(); - bf.instanciate_at(0, 1, 2, "set", Some("&sig2".to_string())).unwrap(); - bf.instanciate_at(0, 0, 3, "value", Some("-1.3".to_string())).unwrap(); + put_v(bf, 0, 0, 1, "value", "0.3"); + put_v(bf, 0, 1, 1, "set", "&sig1"); + put_v(bf, 0, 0, 2, "value", "-0.3"); + put_v(bf, 0, 1, 2, "set", "&sig2"); + put_v(bf, 0, 0, 3, "value", "-1.3"); }); let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); @@ -576,31 +590,31 @@ mod test { #[test] fn check_blocklang_accum_shift() { let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 1, 1, "accum", None); + put_n(bf, 0, 1, 1, "accum"); bf.shift_port(0, 1, 1, 1, false); - bf.instanciate_at(0, 0, 2, "value", Some("0.01".to_string())); - bf.instanciate_at(0, 0, 1, "get", Some("*reset".to_string())); + put_v(bf, 0, 0, 2, "value", "0.01"); + put_v(bf, 0, 0, 1, "get", "*reset"); }); fun.exec_2in_2out(0.0, 0.0); fun.exec_2in_2out(0.0, 0.0); fun.exec_2in_2out(0.0, 0.0); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); + let (_s1, _s2, ret) = fun.exec_2in_2out(0.0, 0.0); assert_float_eq!(ret, 0.04); let reset_idx = ctx.borrow().get_persistent_variable_index_by_name("*reset").unwrap(); fun.access_persistent_var(reset_idx).map(|reset| *reset = 1.0); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); + let (_s1, _s2, ret) = fun.exec_2in_2out(0.0, 0.0); assert_float_eq!(ret, 0.0); fun.access_persistent_var(reset_idx).map(|reset| *reset = 0.0); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); + fun.exec_2in_2out(0.0, 0.0); + fun.exec_2in_2out(0.0, 0.0); + fun.exec_2in_2out(0.0, 0.0); + fun.exec_2in_2out(0.0, 0.0); + let (_s1, _s2, ret) = fun.exec_2in_2out(0.0, 0.0); assert_float_eq!(ret, 0.05); ctx.borrow_mut().free(); @@ -610,64 +624,64 @@ mod test { fn check_blocklang_arithmetics() { // Check + and * let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.50".to_string())); - bf.instanciate_at(0, 0, 2, "value", Some("0.01".to_string())); - bf.instanciate_at(0, 1, 1, "+", None); + put_v(bf, 0, 0, 1, "value", "0.50"); + put_v(bf, 0, 0, 2, "value", "0.01"); + put_n(bf, 0, 1, 1, "+"); bf.shift_port(0, 1, 1, 1, true); - bf.instanciate_at(0, 1, 3, "value", Some("2.0".to_string())); - bf.instanciate_at(0, 2, 2, "*", None); + put_v(bf, 0, 1, 3, "value", "2.0"); + put_n(bf, 0, 2, 2, "*"); }); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); + let (_s1, _s2, ret) = fun.exec_2in_2out(0.0, 0.0); assert_float_eq!(ret, 1.02); ctx.borrow_mut().free(); // Check - and / let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.50".to_string())); - bf.instanciate_at(0, 0, 2, "value", Some("0.01".to_string())); - bf.instanciate_at(0, 1, 1, "-", None); + put_v(bf, 0, 0, 1, "value", "0.50"); + put_v(bf, 0, 0, 2, "value", "0.01"); + put_n(bf, 0, 1, 1, "-"); bf.shift_port(0, 1, 1, 1, true); - bf.instanciate_at(0, 1, 3, "value", Some("2.0".to_string())); - bf.instanciate_at(0, 2, 2, "/", None); + put_v(bf, 0, 1, 3, "value", "2.0"); + put_n(bf, 0, 2, 2, "/"); }); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); + let (_s1, _s2, ret) = fun.exec_2in_2out(0.0, 0.0); assert_float_eq!(ret, (0.5 - 0.01) / 2.0); ctx.borrow_mut().free(); // Check swapping inputs of "-" let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.50".to_string())); - bf.instanciate_at(0, 0, 2, "value", Some("0.01".to_string())); - bf.instanciate_at(0, 1, 1, "-", None); + put_v(bf, 0, 0, 1, "value", "0.50"); + put_v(bf, 0, 0, 2, "value", "0.01"); + put_n(bf, 0, 1, 1, "-"); bf.shift_port(0, 1, 1, 1, false); }); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); + let (_s1, _s2, ret) = fun.exec_2in_2out(0.0, 0.0); assert_float_eq!(ret, 0.01 - 0.5); ctx.borrow_mut().free(); // Check swapping inputs of "/" let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.50".to_string())); - bf.instanciate_at(0, 0, 2, "value", Some("0.01".to_string())); - bf.instanciate_at(0, 1, 1, "/", None); + put_v(bf, 0, 0, 1, "value", "0.50"); + put_v(bf, 0, 0, 2, "value", "0.01"); + put_n(bf, 0, 1, 1, "/"); bf.shift_port(0, 1, 1, 1, false); }); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); + let (_s1, _s2, ret) = fun.exec_2in_2out(0.0, 0.0); assert_float_eq!(ret, 0.01 / 0.5); ctx.borrow_mut().free(); // Check division of 0.0 let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.50".to_string())); - bf.instanciate_at(0, 0, 2, "value", Some("0.0".to_string())); - bf.instanciate_at(0, 1, 1, "/", None); + put_v(bf, 0, 0, 1, "value", "0.50"); + put_v(bf, 0, 0, 2, "value", "0.0"); + put_n(bf, 0, 1, 1, "/"); }); - let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); + let (_s1, _s2, ret) = fun.exec_2in_2out(0.0, 0.0); assert_float_eq!(ret, 0.5 / 0.0); ctx.borrow_mut().free(); } @@ -676,10 +690,10 @@ mod test { fn check_blocklang_divrem() { // &sig1 on second output: let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap(); - bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap(); - bf.instanciate_at(0, 1, 1, "/%", None); - bf.instanciate_at(0, 2, 2, "set", Some("&sig1".to_string())).unwrap(); + put_v(bf, 0, 0, 1, "value", "0.3"); + put_v(bf, 0, 0, 2, "value", "-0.4"); + put_n(bf, 0, 1, 1, "/%"); + put_v(bf, 0, 2, 2, "set", "&sig1"); }); let (s1, _, ret) = fun.exec_2in_2out(0.0, 0.0); @@ -690,10 +704,10 @@ mod test { // &sig1 on first output: let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap(); - bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap(); - bf.instanciate_at(0, 1, 1, "/%", None); - bf.instanciate_at(0, 2, 1, "set", Some("&sig1".to_string())).unwrap(); + put_v(bf, 0, 0, 1, "value", "0.3"); + put_v(bf, 0, 0, 2, "value", "-0.4"); + put_n(bf, 0, 1, 1, "/%"); + put_v(bf, 0, 2, 1, "set", "&sig1"); }); let (s1, _, ret) = fun.exec_2in_2out(0.0, 0.0); @@ -704,10 +718,10 @@ mod test { // &sig1 on second output, but swapped outputs: let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap(); - bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap(); - bf.instanciate_at(0, 1, 1, "/%", None); - bf.instanciate_at(0, 2, 2, "set", Some("&sig1".to_string())).unwrap(); + put_v(bf, 0, 0, 1, "value", "0.3"); + put_v(bf, 0, 0, 2, "value", "-0.4"); + put_n(bf, 0, 1, 1, "/%"); + put_v(bf, 0, 2, 2, "set", "&sig1"); bf.shift_port(0, 1, 1, 0, true); }); @@ -719,10 +733,10 @@ mod test { // &sig1 on first output, but swapped outputs: let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap(); - bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap(); - bf.instanciate_at(0, 1, 1, "/%", None); - bf.instanciate_at(0, 2, 1, "set", Some("&sig1".to_string())).unwrap(); + put_v(bf, 0, 0, 1, "value", "0.3"); + put_v(bf, 0, 0, 2, "value", "-0.4"); + put_n(bf, 0, 1, 1, "/%"); + put_v(bf, 0, 2, 1, "set", "&sig1"); bf.shift_port(0, 1, 1, 0, true); }); @@ -734,10 +748,10 @@ mod test { // &sig1 on first output, but swapped inputs: let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap(); - bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap(); - bf.instanciate_at(0, 1, 1, "/%", None); - bf.instanciate_at(0, 2, 1, "set", Some("&sig1".to_string())).unwrap(); + put_v(bf, 0, 0, 1, "value", "0.3"); + put_v(bf, 0, 0, 2, "value", "-0.4"); + put_n(bf, 0, 1, 1, "/%"); + put_v(bf, 0, 2, 1, "set", "&sig1"); bf.shift_port(0, 1, 1, 0, false); }); @@ -749,10 +763,10 @@ mod test { // &sig1 on first output, but swapped inputs and outputs: let (ctx, mut fun) = new_jit_fun(|bf| { - bf.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())).unwrap(); - bf.instanciate_at(0, 0, 2, "value", Some("-0.4".to_string())).unwrap(); - bf.instanciate_at(0, 1, 1, "/%", None); - bf.instanciate_at(0, 2, 1, "set", Some("&sig1".to_string())).unwrap(); + put_v(bf, 0, 0, 1, "value", "0.3"); + put_v(bf, 0, 0, 2, "value", "-0.4"); + put_n(bf, 0, 1, 1, "/%"); + put_v(bf, 0, 2, 1, "set", "&sig1"); bf.shift_port(0, 1, 1, 0, false); bf.shift_port(0, 1, 1, 0, true); }); diff --git a/src/blocklang_def.rs b/src/wblockdsp/definition.rs similarity index 89% rename from src/blocklang_def.rs rename to src/wblockdsp/definition.rs index d7949ce..f73a00a 100644 --- a/src/blocklang_def.rs +++ b/src/wblockdsp/definition.rs @@ -2,32 +2,22 @@ // This file is a part of HexoDSP. Released under GPL-3.0-or-later. // See README.md and COPYING for details. -use crate::blocklang::{BlockLanguage, BlockType, BlockUserInput}; +use crate::wblockdsp::{BlockLanguage, BlockType, BlockUserInput}; use std::cell::RefCell; use std::rc::Rc; #[cfg(feature = "synfx-dsp-jit")] use synfx_dsp_jit::DSPNodeTypeLibrary; +/** WBlockDSP language definition and standard library of nodes. + +Most of the nodes are taken from the [synfx_dsp_jit] crate standard library. +*/ #[cfg(feature = "synfx-dsp-jit")] pub fn setup_hxdsp_block_language( dsp_lib: Rc>, ) -> Rc> { let mut lang = BlockLanguage::new(); -// lang.define(BlockType { -// category: "source".to_string(), -// name: "phse".to_string(), -// rows: 1, -// inputs: vec![Some("f".to_string())], -// outputs: vec![Some("".to_string())], -// area_count: 0, -// user_input: BlockUserInput::None, -// description: -// "A phasor, returns a saw tooth wave to scan through things or use as modulator." -// .to_string(), -// color: 2, -// }); -// lang.define(BlockType { category: "literals".to_string(), name: "zero".to_string(), @@ -200,18 +190,6 @@ pub fn setup_hxdsp_block_language( // color: 8, // }); -// lang.define(BlockType { -// category: "arithmetics".to_string(), -// name: "/%".to_string(), -// rows: 2, -// inputs: vec![Some("a".to_string()), Some("b".to_string())], -// outputs: vec![Some("div".to_string()), Some("rem".to_string())], -// area_count: 0, -// user_input: BlockUserInput::None, -// description: "Computes the integer division and remainder of a / b".to_string(), -// color: 8, -// }); - for fun_name in &["+", "-", "*", "/"] { lang.define(BlockType { category: "arithmetics".to_string(), diff --git a/src/blocklang.rs b/src/wblockdsp/language.rs similarity index 99% rename from src/blocklang.rs rename to src/wblockdsp/language.rs index 61e5c8e..17dc369 100644 --- a/src/blocklang.rs +++ b/src/wblockdsp/language.rs @@ -1818,7 +1818,7 @@ mod test { #[test] fn check_blockfun_serialize_empty() { let dsp_lib = synfx_dsp_jit::get_standard_library(); - let lang = crate::blocklang_def::setup_hxdsp_block_language(dsp_lib); + let lang = crate::wblockdsp::setup_hxdsp_block_language(dsp_lib); let mut bf = BlockFun::new(lang.clone()); let sn = bf.save_snapshot(); @@ -1834,10 +1834,10 @@ mod test { #[test] fn check_blockfun_serialize_1() { let dsp_lib = synfx_dsp_jit::get_standard_library(); - let lang = crate::blocklang_def::setup_hxdsp_block_language(dsp_lib); + let lang = crate::wblockdsp::setup_hxdsp_block_language(dsp_lib); let mut bf = BlockFun::new(lang.clone()); - bf.instanciate_at(0, 0, 0, "+", None); + bf.instanciate_at(0, 0, 0, "+", None).unwrap(); let sn = bf.save_snapshot(); let serialized = sn.serialize().to_string(); diff --git a/src/wblockdsp/mod.rs b/src/wblockdsp/mod.rs new file mode 100644 index 0000000..fc210df --- /dev/null +++ b/src/wblockdsp/mod.rs @@ -0,0 +1,15 @@ +// Copyright (c) 2022 Weird Constructor +// This file is a part of HexoDSP. Released under GPL-3.0-or-later. +// See README.md and COPYING for details. + +/*! Contains the implementation of the visual DSP programming language named WBlockDSP. + +*/ + +mod definition; +mod language; +mod compiler; + +pub use definition::*; +pub use language::*; +pub use compiler::*; diff --git a/tests/blocklang.rs b/tests/blocklang.rs deleted file mode 100644 index 6eda8cd..0000000 --- a/tests/blocklang.rs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2022 Weird Constructor -// This file is a part of HexoDSP. Released under GPL-3.0-or-later. -// See README.md and COPYING for details. - -mod common; -use common::*; - -//#[test] -//fn check_blocklang_dir_1() { -// use hexodsp::block_compiler::{BlkJITCompileError, Block2JITCompiler}; -// use hexodsp::blocklang::BlockFun; -// use hexodsp::blocklang_def; -// -// let lang = blocklang_def::setup_hxdsp_block_language(); -// let mut bf = BlockFun::new(lang.clone()); -// block_fun.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())); -// block_fun.instanciate_at(0, 1, 1, "set", Some("&sig1".to_string())); -// -// let mut compiler = Block2JITCompiler::new(block_fun.block_language()); -// let ast = compiler.compile(&block_fun)?; -// let lib = synfx_dsp_jit::get_standard_library(); -// let ctx = synfx_dsp_jit::DSPNodeContext::new_ref(); -// let jit = JIT::new(lib, dsp_ctx.clone()); -// let fun = jit.compile(ASTFun::new(ast))?; -// -// fun.init(44100.0, None); -// -// let (s1, s2, ret) = fun.exec_2in_2out(0.0, 0.0); -// -// ctx.borrow_mut().free(); -//} -// -//// XXX: Test case with 3 outputs, where the first output writes a value used -//// by the computation after the first but before the third output. -// -// 0.3 ->3 set a -// => -> + set b -// get a -// => -> - set a -// get b -// get a + -// get b -//*/ -// -////#[test] -////fn check_blocklang_2() { -//// let (mut matrix, mut node_exec) = setup(); -//// -//// let block_fun = matrix.get_block_function(0).expect("block fun exists"); -//// { -//// let mut block_fun = block_fun.lock().expect("matrix lock"); -//// -//// block_fun.instanciate_at(0, 0, 0, "get", Some("in1".to_string())); -//// block_fun.instanciate_at(0, 0, 1, "value", Some("0.3".to_string())); -//// block_fun.instanciate_at(0, 1, 0, "+", None); -//// block_fun.instanciate_at(0, 2, 0, "set", Some("&sig1".to_string())); -//// -//// block_fun.instanciate_at(0, 3, 0, "get", Some("in1".to_string())); -//// block_fun.instanciate_at(0, 3, 1, "get", Some("in2".to_string())); -//// block_fun.instanciate_at(0, 4, 0, "-", None); -//// block_fun.instanciate_at(0, 5, 0, "->3", None); -//// -//// block_fun.instanciate_at(0, 3, 5, "get", Some("in1".to_string())); -//// block_fun.instanciate_at(0, 4, 5, "if", None); -//// block_fun.instanciate_at(1, 0, 0, "value", Some("0.5".to_string())); -//// block_fun.instanciate_at(2, 0, 0, "value", Some("-0.5".to_string())); -//// -//// block_fun.instanciate_at(0, 6, 1, "set", Some("*a".to_string())); -//// block_fun.instanciate_at(0, 6, 2, "set", Some("x".to_string())); -//// block_fun.instanciate_at(0, 6, 0, "->", None); -//// block_fun.instanciate_at(0, 7, 0, "->2", None); -//// -//// block_fun.instanciate_at(0, 0, 3, "get", Some("in1".to_string())); -//// block_fun.instanciate_at(0, 0, 4, "get", Some("in2".to_string())); -//// block_fun.instanciate_at(0, 1, 3, "/%", None); -//// block_fun.instanciate_at(0, 2, 3, "->", None); -//// block_fun.instanciate_at(0, 3, 3, "/%", None); -//// block_fun.instanciate_at(0, 4, 3, "set", Some("&sig2".to_string())); -//// block_fun.instanciate_at(0, 4, 4, "set", Some("*ap".to_string())); -//// } -//// -//// matrix.check_block_function(0).expect("no compile error"); -//// -//// let res = run_for_ms(&mut node_exec, 25.0); -//// assert_decimated_feq!(res.0, 50, vec![0.2; 100]); -////} diff --git a/tests/node_code.rs b/tests/node_code.rs index 69fcf39..45ec533 100644 --- a/tests/node_code.rs +++ b/tests/node_code.rs @@ -5,7 +5,7 @@ mod common; use common::*; -use hexodsp::blocklang::BlockFun; +use hexodsp::wblockdsp::BlockFun; fn setup() -> (Matrix, NodeExecutor) { let (node_conf, node_exec) = new_node_engine(); diff --git a/tests/wblockdsp.rs b/tests/wblockdsp.rs deleted file mode 100644 index 4f51935..0000000 --- a/tests/wblockdsp.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2022 Weird Constructor -// This file is a part of HexoDSP. Released under GPL-3.0-or-later. -// See README.md and COPYING for details. - -mod common; -use common::*; -#[cfg(feature="synfx-dsp-jit")] -use hexodsp::wblockdsp::*; - -#[cfg(feature="synfx-dsp-jit")] -#[test] -fn check_wblockdsp_init() { - let mut engine = CodeEngine::new(); - - let backend = engine.get_backend(); -} - -#[cfg(feature="synfx-dsp-jit")] -#[test] -fn check_wblockdsp_code_node() { - let (node_conf, mut node_exec) = new_node_engine(); - let mut matrix = Matrix::new(node_conf, 3, 3); - - let mut chain = MatrixCellChain::new(CellDir::B); - chain - .node_out("code", "sig") - .node_io("code", "in1", "sig") - .node_inp("out", "ch1") - .place(&mut matrix, 0, 0) - .unwrap(); - matrix.sync().unwrap(); - - let mut chain = MatrixCellChain::new(CellDir::B); - chain - .node_out("code", "sig") - .node_io("code", "in1", "sig") - .node_inp("out", "ch1") - .place(&mut matrix, 0, 0) - .unwrap(); - matrix.sync().unwrap(); -}