Refactored WBlockDSP into it's own sub module and removed the old wblockdsp.rs
This commit is contained in:
parent
4c5d832036
commit
87104ded31
13 changed files with 119 additions and 398 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<Arc<Mutex<BlockFun>>> {
|
||||
self.config.get_block_function(id)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<CodeEngine>,
|
||||
/// 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<Mutex<BlockFun>>)>,
|
||||
/// 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<Arc<Mutex<BlockFun>>> {
|
||||
#[cfg(feature = "synfx-dsp-jit")]
|
||||
{
|
||||
|
|
152
src/wblockdsp.rs
152
src/wblockdsp.rs
|
@ -1,152 +0,0 @@
|
|||
// Copyright (c) 2022 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 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<DSPFunction>),
|
||||
}
|
||||
|
||||
enum CodeReturnMsg {
|
||||
DestroyFun(Box<DSPFunction>),
|
||||
}
|
||||
|
||||
pub struct CodeEngine {
|
||||
dsp_ctx: Rc<RefCell<DSPNodeContext>>,
|
||||
lib: Rc<RefCell<DSPNodeTypeLibrary>>,
|
||||
update_prod: Producer<CodeUpdateMsg>,
|
||||
return_cons: Consumer<CodeReturnMsg>,
|
||||
}
|
||||
|
||||
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<RefCell<DSPNodeTypeLibrary>> {
|
||||
self.lib.clone()
|
||||
}
|
||||
|
||||
pub fn upload(&mut self, ast: Box<ASTNode>) -> 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<DSPFunction>) {
|
||||
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<DSPFunction>,
|
||||
update_cons: Consumer<CodeUpdateMsg>,
|
||||
return_prod: Producer<CodeReturnMsg>,
|
||||
}
|
||||
|
||||
impl CodeEngineBackend {
|
||||
fn new(
|
||||
function: Box<DSPFunction>,
|
||||
update_cons: Consumer<CodeUpdateMsg>,
|
||||
return_prod: Producer<CodeReturnMsg>,
|
||||
) -> 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<DSPFunction>) -> Box<DSPFunction> {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<RefCell<JASTNode>>);
|
||||
|
||||
|
@ -37,18 +39,26 @@ impl BlockASTNode for ASTNodeRef {
|
|||
}
|
||||
|
||||
impl ASTNodeRef {
|
||||
/// Returns the first child AST node.
|
||||
pub fn first_child_ref(&self) -> Option<ASTNodeRef> {
|
||||
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<F: FnMut(&mut BlockFun)>(
|
||||
mut f: F,
|
||||
) -> (Rc<RefCell<DSPNodeContext>>, Box<DSPFunction>) {
|
||||
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);
|
||||
});
|
|
@ -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<RefCell<DSPNodeTypeLibrary>>,
|
||||
) -> Rc<RefCell<BlockLanguage>> {
|
||||
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(),
|
|
@ -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();
|
15
src/wblockdsp/mod.rs
Normal file
15
src/wblockdsp/mod.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright (c) 2022 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.
|
||||
|
||||
/*! 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::*;
|
|
@ -1,86 +0,0 @@
|
|||
// Copyright (c) 2022 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.
|
||||
|
||||
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]);
|
||||
////}
|
|
@ -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();
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
// Copyright (c) 2022 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.
|
||||
|
||||
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();
|
||||
}
|
Loading…
Reference in a new issue