diff --git a/examples/list_synth_reference.rs b/examples/list_synth_reference.rs index d7a89d2..a970ae8 100644 --- a/examples/list_synth_reference.rs +++ b/examples/list_synth_reference.rs @@ -61,7 +61,9 @@ fn main() { println!("| NtoM | Signal routing, routing N signals to M outputs (mixer, router, ...) |"); println!("| Signal | Signal filtering and shaping (filters, delays, reverbs, ...) |"); println!("| Ctrl | Control signal generators and shapers (for instance quantizers) |"); - println!("| IOUtil | Input, output and utility nodes (audio output, feedback nodes, MIDI CC, ...) |"); + println!( + "| IOUtil | Input, output and utility nodes (audio output, feedback nodes, MIDI CC, ...) |" + ); println!(""); println!("| Node | Category | Description |"); diff --git a/src/dsp/mod.rs b/src/dsp/mod.rs index 26acc00..a297445 100644 --- a/src/dsp/mod.rs +++ b/src/dsp/mod.rs @@ -601,7 +601,7 @@ pub type LedPhaseVals<'a> = &'a [Arc]; pub use satom::*; pub use node_rust::new_dummy_dynamic_node1x1; -pub use node_rust::{DynNode1x1Context, DynamicNode1x1, DynNodeHandle, DynNodeBuffer}; +pub use node_rust::{DynNode1x1Context, DynNodeBuffer, DynNodeHandle, DynamicNode1x1}; use crate::fa_ad_mult; use crate::fa_adsr_mult; diff --git a/src/dsp/node_fvafilt.rs b/src/dsp/node_fvafilt.rs index aa09fbb..220f03e 100644 --- a/src/dsp/node_fvafilt.rs +++ b/src/dsp/node_fvafilt.rs @@ -43,16 +43,16 @@ macro_rules! fa_fvafilt_svf_mode { macro_rules! fa_fvafilt_lmode { ($formatter: expr, $v: expr, $denorm_v: expr) => {{ let s = match ($v.round() as usize) { - 0 => "LP 6dB", - 1 => "LP 12dB", - 2 => "LP 18dB", - 3 => "LP 24dB", - 4 => "HP 6dB", - 5 => "HP 12dB", - 6 => "HP 18dB", - 7 => "HP 24dB", - 8 => "BP 12dB", - 9 => "BP 24dB", + 0 => "LP 6dB", + 1 => "LP 12dB", + 2 => "LP 18dB", + 3 => "LP 24dB", + 4 => "HP 6dB", + 5 => "HP 12dB", + 6 => "HP 18dB", + 7 => "HP 24dB", + 8 => "BP 12dB", + 9 => "BP 24dB", 10 => "N 12dB", _ => "?", }; @@ -79,10 +79,7 @@ impl FVaFilt { ladder: LadderFilter::new(params.clone()), svf: Svf::new(params.clone()), sallenkey: SallenKey::new(params.clone()), - oversample: ( - PolyIIRHalfbandFilter::new(8, true), - PolyIIRHalfbandFilter::new(8, true), - ), + oversample: (PolyIIRHalfbandFilter::new(8, true), PolyIIRHalfbandFilter::new(8, true)), dc_filter: DCFilterX4::default(), params, old_params: Box::new((0.0, 0.0, 0.0, 0, 0, -1)), @@ -145,7 +142,7 @@ macro_rules! on_param_change { denorm::FVaFilt::drive($drive, $frame).max(0.0), $ftype, $lmode, - $smode + $smode, ); if new_params != *$self.old_params { @@ -243,9 +240,20 @@ impl DspNode for FVaFilt { // SallenKey let sallenkey = &mut self.sallenkey; for frame in 0..ctx.nframes() { - on_param_change!(self, freq, res, drive, ftype, smode, lmode, frame, ladder_mode_changed, { - sallenkey.update(); - }); + on_param_change!( + self, + freq, + res, + drive, + ftype, + smode, + lmode, + frame, + ladder_mode_changed, + { + sallenkey.update(); + } + ); let sig_l = denorm::FVaFilt::in_l(in_l, frame); let sig_r = denorm::FVaFilt::in_r(in_r, frame); @@ -271,9 +279,20 @@ impl DspNode for FVaFilt { // SVF let svf = &mut self.svf; for frame in 0..ctx.nframes() { - on_param_change!(self, freq, res, drive, ftype, smode, lmode, frame, ladder_mode_changed, { - svf.update(); - }); + on_param_change!( + self, + freq, + res, + drive, + ftype, + smode, + lmode, + frame, + ladder_mode_changed, + { + svf.update(); + } + ); let sig_l = denorm::FVaFilt::in_l(in_l, frame); let sig_r = denorm::FVaFilt::in_r(in_r, frame); @@ -299,11 +318,22 @@ impl DspNode for FVaFilt { // Ladder let ladder = &mut self.ladder; for frame in 0..ctx.nframes() { - on_param_change!(self, freq, res, drive, ftype, smode, lmode, frame, ladder_mode_changed, { - if ladder_mode_changed { - ladder.set_mix(self.params.ladder_mode); + on_param_change!( + self, + freq, + res, + drive, + ftype, + smode, + lmode, + frame, + ladder_mode_changed, + { + if ladder_mode_changed { + ladder.set_mix(self.params.ladder_mode); + } } - }); + ); let sig_l = denorm::FVaFilt::in_l(in_l, frame); let sig_r = denorm::FVaFilt::in_r(in_r, frame); diff --git a/src/dsp/node_rust.rs b/src/dsp/node_rust.rs index 31e039d..c7db024 100644 --- a/src/dsp/node_rust.rs +++ b/src/dsp/node_rust.rs @@ -8,8 +8,7 @@ use crate::dsp::{ use crate::nodes::{NodeAudioContext, NodeExecContext}; use std::sync::Arc; use synfx_dsp::AtomicFloat; -use triple_buffer::{TripleBuffer, Input, Output}; - +use triple_buffer::{Input, Output, TripleBuffer}; /// A context structure for supporting the [DynamicNode1x1::process] function. /// @@ -112,7 +111,10 @@ pub struct DynNodeBuffer { output: Output, } -impl DynNodeBuffer where T: Send { +impl DynNodeBuffer +where + T: Send, +{ #[inline] pub fn access(&mut self) -> &mut T { self.output.update(); @@ -131,13 +133,13 @@ impl Default for Box { } } -impl DynNodeHandle where T: Send + Default { +impl DynNodeHandle +where + T: Send + Default, +{ pub fn new() -> Self { let (input, output) = TripleBuffer::default().split(); - Self { - input, - output: Some(output), - } + Self { input, output: Some(output) } } pub fn write(&mut self, node: T) { @@ -145,14 +147,13 @@ impl DynNodeHandle where T: Send + Default { } pub fn get_output_buffer(&mut self) -> DynNodeBuffer { - let output = - if let Some(output) = self.output.take() { - output - } else { - let (input, output) = TripleBuffer::default().split(); - self.input = input; - output - }; + let output = if let Some(output) = self.output.take() { + output + } else { + let (input, output) = TripleBuffer::default().split(); + self.input = input; + output + }; DynNodeBuffer { output } } } @@ -170,13 +171,12 @@ pub struct Rust1x1 { impl Rust1x1 { pub fn new(nid: &NodeId, node_global: &NodeGlobalRef) -> Self { - let buffer = - if let Ok(mut handle) = node_global.lock() { - handle.get_dynamic_node1x1_buffer(nid.instance() as usize) - } else { - let mut handle = DynNodeHandle::>::new(); - handle.get_output_buffer() - }; + let buffer = if let Ok(mut handle) = node_global.lock() { + handle.get_dynamic_node1x1_buffer(nid.instance() as usize) + } else { + let mut handle = DynNodeHandle::>::new(); + handle.get_output_buffer() + }; Self { buffer } } diff --git a/src/dsp_nodes_ref.md b/src/dsp_nodes_ref.md index 584eb08..13f49fd 100644 --- a/src/dsp_nodes_ref.md +++ b/src/dsp_nodes_ref.md @@ -2172,31 +2172,47 @@ This is a collection of virtual analog filters that were implemented by Fredemus (aka Frederik Halkjær). They behave well when driven hard but that comes with the price that they are more expensive. -- [input **inp**](#nodeidfvafilt-input-inp) - Signal input +- [input **in_l**](#nodeidfvafilt-input-in_l) - Signal left channel input +- [input **in_r**](#nodeidfvafilt-input-in_r) - Signal right channel input - [input **freq**](#nodeidfvafilt-input-freq) - Filter cutoff frequency. - [input **res**](#nodeidfvafilt-input-res) - Filter resonance. - [input **drive**](#nodeidfvafilt-input-drive) - Filter (over) drive. - [setting **ftype**](#nodeidfvafilt-setting-ftype) - The filter type, there are varying types of filters available: - **Ladder** - **SVF** - **Sallen Key** - [setting **smode**](#nodeidfvafilt-setting-smode) - SVF Filter Mode - **LP** - Low pass - **HP** - High pass - **BP1** - Band pass 1 - **BP2** - Band pass 2 - **Notch** - Notch -- [setting **lslope**](#nodeidfvafilt-setting-lslope) - Ladder Slope Available slopes: **6dB**, **12dB**, **18dB**, **24dB** -- output **sig** -Filtered signal output. - `fvafilt(0).output().sig()` +- [setting **lmode**](#nodeidfvafilt-setting-lmode) - Ladder Slope - **LP 6dB** - Low pass 6dB - **LP 12dB** - Low pass 12dB - **LP 18dB** - Low pass 18dB - **LP 24dB** - Low pass 24dB - **HP 6dB** - High pass 6dB - **HP 12dB** - High pass 12dB - **HP 18dB** - High pass 18dB - **HP 24dB** - High pass 24dB - **BP 12dB** - Band pass 12dB - **BP 24dB** - Band pass 24dB - **N 12dB** - Notch 12dB +- output **sig_l** +Filtered signal left channel output. + `fvafilt(0).output().sig_l()` +- output **sig_r** +Filtered signal right channel output. + `fvafilt(0).output().sig_r()` #### NodeId::FVaFilt Help **Frederik Halkjær Virtual Analog Stereo Filters** -#### NodeId::FVaFilt input inp -Signal input +#### NodeId::FVaFilt input in_l +Signal left channel input API example for connecting the input: -`fvafilt(0).input().inp(&(1).output().sig())` +`fvafilt(0).input().in_l(&(1).output().sig())` | | value | denormalized | fmt | build API | [crate::ParamId] | |-|-------|--------------|-----|-----------|------------------| -| **default** | 0.0000 | 0.00 | 0.000 | `fvafilt(0).set().inp(0)` | `NodeId::FVaFilt(0).inp_param("inp")` | -| **min** | -1.0000 | -1.00 | -1.000 | `fvafilt(0).set().inp(-1)` | `NodeId::FVaFilt(0).inp_param("inp")` | -| **mid** | 0.0000 | 0.00 | 0.000 | `fvafilt(0).set().inp(0)` | `NodeId::FVaFilt(0).inp_param("inp")` | -| **max** | 1.0000 | 1.00 | 1.000 | `fvafilt(0).set().inp(1)` | `NodeId::FVaFilt(0).inp_param("inp")` | +| **default** | 0.0000 | 0.00 | 0.000 | `fvafilt(0).set().in_l(0)` | `NodeId::FVaFilt(0).inp_param("in_l")` | +| **min** | -1.0000 | -1.00 | -1.000 | `fvafilt(0).set().in_l(-1)` | `NodeId::FVaFilt(0).inp_param("in_l")` | +| **mid** | 0.0000 | 0.00 | 0.000 | `fvafilt(0).set().in_l(0)` | `NodeId::FVaFilt(0).inp_param("in_l")` | +| **max** | 1.0000 | 1.00 | 1.000 | `fvafilt(0).set().in_l(1)` | `NodeId::FVaFilt(0).inp_param("in_l")` | +#### NodeId::FVaFilt input in_r +Signal right channel input + +API example for connecting the input: +`fvafilt(0).input().in_r(&(1).output().sig())` + +| | value | denormalized | fmt | build API | [crate::ParamId] | +|-|-------|--------------|-----|-----------|------------------| +| **default** | 0.0000 | 0.00 | 0.000 | `fvafilt(0).set().in_r(0)` | `NodeId::FVaFilt(0).inp_param("in_r")` | +| **min** | -1.0000 | -1.00 | -1.000 | `fvafilt(0).set().in_r(-1)` | `NodeId::FVaFilt(0).inp_param("in_r")` | +| **mid** | 0.0000 | 0.00 | 0.000 | `fvafilt(0).set().in_r(0)` | `NodeId::FVaFilt(0).inp_param("in_r")` | +| **max** | 1.0000 | 1.00 | 1.000 | `fvafilt(0).set().in_r(1)` | `NodeId::FVaFilt(0).inp_param("in_r")` | #### NodeId::FVaFilt input freq Filter cutoff frequency. @@ -2261,16 +2277,34 @@ SVF Filter Mode | 2 | BP1 | `fvafilt(0).set().smode(2)` | `NodeId::FVaFilt(0).inp_param("smode")` | | 3 | BP2 | `fvafilt(0).set().smode(3)` | `NodeId::FVaFilt(0).inp_param("smode")` | | 4 | Notch | `fvafilt(0).set().smode(4)` | `NodeId::FVaFilt(0).inp_param("smode")` | -#### NodeId::FVaFilt setting lslope +#### NodeId::FVaFilt setting lmode Ladder Slope -Available slopes: **6dB**, **12dB**, **18dB**, **24dB** +- **LP 6dB** - Low pass 6dB +- **LP 12dB** - Low pass 12dB +- **LP 18dB** - Low pass 18dB +- **LP 24dB** - Low pass 24dB +- **HP 6dB** - High pass 6dB +- **HP 12dB** - High pass 12dB +- **HP 18dB** - High pass 18dB +- **HP 24dB** - High pass 24dB +- **BP 12dB** - Band pass 12dB +- **BP 24dB** - Band pass 24dB +- **N 12dB** - Notch 12dB + | setting | fmt | build API | [crate::ParamId] | |---------|-----|-----------|------------------| -| 0 | Ladder 6dB | `fvafilt(0).set().lslope(0)` | `NodeId::FVaFilt(0).inp_param("lslope")` | -| 1 | Ladder 12dB | `fvafilt(0).set().lslope(1)` | `NodeId::FVaFilt(0).inp_param("lslope")` | -| 2 | Ladder 18dB | `fvafilt(0).set().lslope(2)` | `NodeId::FVaFilt(0).inp_param("lslope")` | -| 3 | Ladder 24dB | `fvafilt(0).set().lslope(3)` | `NodeId::FVaFilt(0).inp_param("lslope")` | +| 0 | LP 6dB | `fvafilt(0).set().lmode(0)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 1 | LP 12dB | `fvafilt(0).set().lmode(1)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 2 | LP 18dB | `fvafilt(0).set().lmode(2)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 3 | LP 24dB | `fvafilt(0).set().lmode(3)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 4 | HP 6dB | `fvafilt(0).set().lmode(4)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 5 | HP 12dB | `fvafilt(0).set().lmode(5)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 6 | HP 18dB | `fvafilt(0).set().lmode(6)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 7 | HP 24dB | `fvafilt(0).set().lmode(7)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 8 | BP 12dB | `fvafilt(0).set().lmode(8)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 9 | BP 24dB | `fvafilt(0).set().lmode(9)` | `NodeId::FVaFilt(0).inp_param("lmode")` | +| 10 | N 12dB | `fvafilt(0).set().lmode(10)` | `NodeId::FVaFilt(0).inp_param("lmode")` | ### NodeId::PVerb **Plate Reverb** diff --git a/src/global.rs b/src/global.rs index a6c0525..fe5c76f 100644 --- a/src/global.rs +++ b/src/global.rs @@ -3,7 +3,7 @@ // See README.md and COPYING for details. use crate::dsp::tracker::{PatternData, Tracker, TrackerBackend}; -use crate::dsp::{DynNodeHandle, DynNodeBuffer, DynamicNode1x1}; +use crate::dsp::{DynNodeBuffer, DynNodeHandle, DynamicNode1x1}; use crate::wblockdsp::*; use crate::{ScopeHandle, SharedFeedback, SharedFeedbackReader, SharedFeedbackWriter}; use std::collections::HashMap; @@ -239,7 +239,10 @@ impl NodeGlobalData { /// That means, after construction of a new Rust1x1, you should update the DynamicNode1x1 /// using [NodeGlobalData::send_dynamic_node1x1]. /// This will be very relevant to do after [crate::NodeConfigurator::set_sample_rate]. - pub(crate) fn get_dynamic_node1x1_buffer(&mut self, id: usize) -> DynNodeBuffer> { + pub(crate) fn get_dynamic_node1x1_buffer( + &mut self, + id: usize, + ) -> DynNodeBuffer> { if !self.dyn_nodes1x1.contains_key(&id) { self.dyn_nodes1x1.insert(id, DynNodeHandle::new()); } diff --git a/src/nodes/node_conf.rs b/src/nodes/node_conf.rs index b5560b0..b25fffa 100644 --- a/src/nodes/node_conf.rs +++ b/src/nodes/node_conf.rs @@ -177,31 +177,31 @@ struct NodeInputAtom { /// The execution of the nodes in the audio thread is /// controlled by a `NodeProg`, which defines the order /// the nodes are executed in. -/// +/// /// This only showcases the non-realtime generation of audio /// samples. For a real time application of this library please /// refer to the examples that come with this library. -/// +/// /// ```rust /// use hexodsp::*; -/// +/// /// let (mut node_conf, mut node_exec) = new_node_engine(); -/// +/// /// node_conf.create_node(NodeId::Sin(0)); /// node_conf.create_node(NodeId::Amp(0)); -/// +/// /// let mut prog = node_conf.rebuild_node_ports(); -/// +/// /// node_conf.add_prog_node(&mut prog, &NodeId::Sin(0)); /// node_conf.add_prog_node(&mut prog, &NodeId::Amp(0)); -/// +/// /// node_conf.set_prog_node_exec_connection( /// &mut prog, /// (NodeId::Amp(0), NodeId::Amp(0).inp("inp").unwrap()), /// (NodeId::Sin(0), NodeId::Sin(0).out("sig").unwrap())); -/// +/// /// node_conf.upload_prog(prog, true); -/// +/// /// let (out_l, out_r) = node_exec.test_run(0.1, false, &[]); /// ``` pub struct NodeConfigurator { diff --git a/src/nodes/node_exec.rs b/src/nodes/node_exec.rs index ae45b4e..bd5d5aa 100644 --- a/src/nodes/node_exec.rs +++ b/src/nodes/node_exec.rs @@ -3,8 +3,8 @@ // See README.md and COPYING for details. use super::{ - DropMsg, EventWindowing, GraphEvent, GraphMessage, HxMidiEvent, HxTimedEvent, - NodeProg, MAX_INJ_MIDI_EVENTS, MAX_SMOOTHERS, UNUSED_MONITOR_IDX, + DropMsg, EventWindowing, GraphEvent, GraphMessage, HxMidiEvent, HxTimedEvent, NodeProg, + MAX_INJ_MIDI_EVENTS, MAX_SMOOTHERS, UNUSED_MONITOR_IDX, }; use crate::dsp::{Node, NodeContext, MAX_BLOCK_SIZE}; use crate::monitor::{MonitorBackend, MON_SIG_CNT}; @@ -171,7 +171,7 @@ impl NodeExecContext { fn set_sample_rate(&mut self, _srate: f32) {} - fn clear(&mut self) { } + fn clear(&mut self) {} } impl NodeExecutor { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 58650a4..88c6df3 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -336,12 +336,7 @@ pub fn vis_fft(table: &[(u16, u32)], max: Option) -> Vec { .iter() .map(|(freq, amt)| { let amt_ratio = ((*amt as f32).round() / max).clamp(0.0, 1.0); - format!( - "{:5} {:5} {}", - freq, - amt, - "#".repeat((amt_ratio * 20.0).ceil() as usize) - ) + format!("{:5} {:5} {}", freq, amt, "#".repeat((amt_ratio * 20.0).ceil() as usize)) }) .collect::>() }