only frequency test left + description

This commit is contained in:
Dimas Leenman 2022-08-07 21:28:45 +02:00
parent 22aa19cf9f
commit c656b40729
30 changed files with 213 additions and 69 deletions

View file

@ -2,11 +2,11 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{sqrt4_to_pow4, TrigSignal, Trigger};
use crate::dsp::{
DspNode, GraphAtomData, GraphFun, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom,
};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{sqrt4_to_pow4, TrigSignal, Trigger};
#[macro_export]
macro_rules! fa_ad_mult {

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::AllPass;
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::AllPass;
/// A simple amplifier
#[derive(Debug, Clone)]

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::*;
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::*;
#[macro_export]
macro_rules! fa_biqfilt_type {

View file

@ -2,11 +2,11 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::PolyBlepOscillator;
use crate::dsp::{
DspNode, GraphAtomData, GraphFun, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom,
};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::PolyBlepOscillator;
#[macro_export]
macro_rules! fa_bosc_wtype {

View file

@ -2,11 +2,11 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{DelayBuffer, FixedOnePole, Biquad};
use crate::dsp::{
denorm, denorm_offs, inp, out, DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom,
};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{Biquad, DelayBuffer, FixedOnePole};
// Bowed String instrument oscillator
// Bowed string model, a la Smith (1986),

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp;
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp;
#[macro_export]
macro_rules! fa_comb_mode {

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{ChangeTrig, CtrlPitchQuantizer};
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{ChangeTrig, CtrlPitchQuantizer};
#[macro_export]
macro_rules! fa_cqnt {

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{crossfade, DelayBuffer, TriggerSampleClock};
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{crossfade, DelayBuffer, TriggerSampleClock};
#[macro_export]
macro_rules! fa_delay_mode {

View file

@ -69,14 +69,17 @@ impl DspNode for Formant {
let decay_freq = denorm::Formant::dcy(decay_freq, frame);
// where the two decays meet
let carrier_center = attack_freq / (attack_freq + decay_freq);
// clamp to avoid division by 0
let carrier_center =
(attack_freq / (attack_freq + decay_freq)).max(1e-6).min(1.0 - 1e-6);
// where they meet in amplitude
let carrier_lowest_amplitude = if carrier_center * decay_freq > base_freq * 2.0 {
0.0
} else {
(-(std::f32::consts::PI * carrier_center * decay_freq) / base_freq).exp()
};
let carrier_lowest_amplitude =
if carrier_center * decay_freq > base_freq * 2.0 || base_freq == 0.0 {
0.0
} else {
(-(std::f32::consts::PI * carrier_center * decay_freq) / base_freq).exp()
};
// make a triangle wave, with the peak at carrier center
let carrier_base =
@ -88,17 +91,22 @@ impl DspNode for Formant {
* (carrier_base * carrier_base * (3.0 - 2.0 * carrier_base)));
// multiple of the frequency the modulators are at
let multiple = formant_freq / base_freq;
let multiple = formant_freq / base_freq.max(1e-6);
// round them to the closest integer of the formant freq
let freq_a = multiple.floor().max(1.0);
let freq_a = multiple.floor();
let freq_b = freq_a + 1.0;
// and how much to lerp between them
let blend = multiple.max(1.0).fract();
let blend = multiple.fract();
// get the true modulator
let modulator = (1.0 - blend) * (std::f32::consts::TAU * self.phase * freq_a).cos()
let modulator = (1.0 - blend)
* if multiple < 1.0 {
0.0
} else {
(std::f32::consts::TAU * self.phase * freq_a).cos()
}
+ blend * (std::f32::consts::TAU * self.phase * freq_b).cos();
// entire wave

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::Trigger;
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::Trigger;
#[macro_export]
macro_rules! fa_mux9_in_cnt {

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::Rng;
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::Rng;
#[macro_export]
macro_rules! fa_noise_mode {

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{DattorroReverb, DattorroReverbParams, crossfade};
use crate::dsp::{denorm, DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{crossfade, DattorroReverb, DattorroReverbParams};
pub struct DatParams {
frame: usize,

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{ChangeTrig, Quantizer};
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{ChangeTrig, Quantizer};
#[macro_export]
macro_rules! fa_quant {

View file

@ -2,9 +2,9 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{Rng, SlewValue, Trigger};
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{Rng, SlewValue, Trigger};
/// A triggered random walker
#[derive(Debug, Clone)]

View file

@ -2,10 +2,10 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{cubic_interpolate, Trigger};
use crate::dsp::{at, denorm, denorm_offs, inp, out}; //, inp, denorm, denorm_v, inp_dir, at};
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{cubic_interpolate, Trigger};
#[macro_export]
macro_rules! fa_sampl_dir {

View file

@ -8,12 +8,12 @@
// Copyright by Andrew Belt, 2021
//use super::helpers::{sqrt4_to_pow4, TrigSignal, Trigger};
use synfx_dsp::CustomTrigger;
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::SCOPE_SAMPLES;
use crate::nodes::{NodeAudioContext, NodeExecContext};
use crate::ScopeHandle;
use std::sync::Arc;
use synfx_dsp::CustomTrigger;
#[macro_export]
macro_rules! fa_scope_tsrc {

View file

@ -2,13 +2,13 @@
// 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 synfx_dsp::{
process_1pole_highpass, process_1pole_lowpass, process_1pole_tpt_highpass,
process_1pole_tpt_lowpass, process_hal_chamberlin_svf, process_simper_svf,
process_stilson_moog,
};
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
#[macro_export]
macro_rules! fa_sfilter_type {

View file

@ -2,11 +2,11 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::fast_sin;
use crate::dsp::{
denorm_offs, inp, out, DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom,
};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::fast_sin;
/// A sine oscillator
#[derive(Debug, Clone)]

View file

@ -2,11 +2,11 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::TrigSignal;
use crate::dsp::{
DspNode, GraphAtomData, GraphFun, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom,
};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::TrigSignal;
#[macro_export]
macro_rules! fa_test_s {

View file

@ -2,10 +2,10 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{Trigger, TriggerPhaseClock};
use crate::dsp::tracker::TrackerBackend;
use crate::dsp::{DspNode, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{Trigger, TriggerPhaseClock};
use crate::dsp::MAX_BLOCK_SIZE;

View file

@ -2,11 +2,11 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{TriSawLFO, Trigger};
use crate::dsp::{
DspNode, GraphAtomData, GraphFun, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom,
};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{TriSawLFO, Trigger};
#[derive(Debug, Clone)]
pub struct TsLFO {

View file

@ -2,11 +2,11 @@
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
use synfx_dsp::{Oversampling, apply_distortion, VPSOscillator};
use crate::dsp::{
DspNode, GraphAtomData, GraphFun, LedPhaseVals, NodeContext, NodeId, ProcBuf, SAtom,
};
use crate::nodes::{NodeAudioContext, NodeExecContext};
use synfx_dsp::{apply_distortion, Oversampling, VPSOscillator};
#[macro_export]
macro_rules! fa_vosc_ovrsmpl {

View file

@ -321,8 +321,8 @@ pub mod monitor;
pub mod nodes;
pub mod sample_lib;
pub mod scope_handle;
pub mod wblockdsp;
mod util;
pub mod wblockdsp;
pub use cell_dir::CellDir;
pub use chain_builder::MatrixCellChain;

View file

@ -8,9 +8,9 @@ use crate::matrix_repr::*;
pub use crate::monitor::MON_SIG_CNT;
pub use crate::nodes::MinMaxMonitorSamples;
use crate::nodes::{NodeConfigurator, NodeGraphOrdering, NodeProg, MAX_ALLOCATED_NODES};
use crate::wblockdsp::{BlkJITCompileError, BlockFun, BlockFunSnapshot};
pub use crate::CellDir;
use crate::ScopeHandle;
use crate::wblockdsp::{BlockFun, BlockFunSnapshot, BlkJITCompileError};
use std::collections::{HashMap, HashSet};

View file

@ -3,8 +3,8 @@
// See README.md and COPYING for details.
use crate::dsp::{NodeId, ParamId, SAtom};
use serde_json::{json, Value};
use crate::wblockdsp::BlockFunSnapshot;
use serde_json::{json, Value};
#[derive(Debug, Clone, Copy)]
pub struct CellRepr {

View file

@ -6,15 +6,15 @@ 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::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 synfx_dsp_jit::engine::CodeEngine;
use crate::wblockdsp::*;
use crate::SampleLibrary;
use crate::ScopeHandle;
#[cfg(feature = "synfx-dsp-jit")]
use synfx_dsp_jit::engine::CodeEngine;
use ringbuf::{Producer, RingBuffer};
use std::collections::HashMap;

View file

@ -210,7 +210,7 @@ pub struct Block2JITCompiler {
#[cfg(not(feature = "synfx-dsp-jit"))]
pub enum ASTNode {
NoSynfxDSPJit
NoSynfxDSPJit,
}
impl Block2JITCompiler {

View file

@ -208,39 +208,42 @@ pub fn setup_hxdsp_block_language(
});
}
dsp_lib.borrow().for_each(|node_type| -> Result<(), ()> {
let max_ports = node_type.input_count().max(node_type.output_count());
let is_stateful = node_type.is_stateful();
dsp_lib
.borrow()
.for_each(|node_type| -> Result<(), ()> {
let max_ports = node_type.input_count().max(node_type.output_count());
let is_stateful = node_type.is_stateful();
let mut inputs = vec![];
let mut outputs = vec![];
let mut inputs = vec![];
let mut outputs = vec![];
let mut i = 0;
while let Some(name) = node_type.input_names(i) {
inputs.push(Some(name[0..(name.len().min(2))].to_string()));
i += 1;
}
let mut i = 0;
while let Some(name) = node_type.input_names(i) {
inputs.push(Some(name[0..(name.len().min(2))].to_string()));
i += 1;
}
let mut i = 0;
while let Some(name) = node_type.output_names(i) {
outputs.push(Some(name[0..(name.len().min(2))].to_string()));
i += 1;
}
let mut i = 0;
while let Some(name) = node_type.output_names(i) {
outputs.push(Some(name[0..(name.len().min(2))].to_string()));
i += 1;
}
lang.define(BlockType {
category: if is_stateful { "nodes".to_string() } else { "functions".to_string() },
name: node_type.name().to_string(),
rows: max_ports,
area_count: 0,
user_input: BlockUserInput::None,
description: node_type.documentation().to_string(),
color: if is_stateful { 8 } else { 16 },
inputs,
outputs,
});
lang.define(BlockType {
category: if is_stateful { "nodes".to_string() } else { "functions".to_string() },
name: node_type.name().to_string(),
rows: max_ports,
area_count: 0,
user_input: BlockUserInput::None,
description: node_type.documentation().to_string(),
color: if is_stateful { 8 } else { 16 },
inputs,
outputs,
});
Ok(())
}).expect("seriously no error here");
Ok(())
})
.expect("seriously no error here");
lang.define_identifier("in1");
lang.define_identifier("in2");

View file

@ -6,10 +6,10 @@
*/
mod compiler;
mod definition;
mod language;
mod compiler;
pub use compiler::*;
pub use definition::*;
pub use language::*;
pub use compiler::*;

133
tests/node_formant.rs Normal file
View file

@ -0,0 +1,133 @@
mod common;
use common::*;
#[test]
fn check_normalized_if_freq_lower_than_formant_freq() {
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("formant", "sig").node_inp("out", "ch1").place(&mut matrix, 0, 0).unwrap();
matrix.sync().unwrap();
let formant = NodeId::Formant(0);
// params
let freq_p = formant.inp_param("freq").unwrap();
let form_p = formant.inp_param("form").unwrap();
let atk_p = formant.inp_param("atk").unwrap();
let dcy_p = formant.inp_param("dcy").unwrap();
// set params to reasonable values
matrix.set_param(freq_p, SAtom::param(-0.2));
matrix.set_param(form_p, SAtom::param(0.0));
matrix.set_param(atk_p, SAtom::param(0.2));
matrix.set_param(dcy_p, SAtom::param(-0.2));
// run
let res = run_for_ms(&mut node_exec, 100.0);
// and check it's normalized
let max = res.0.iter().fold(0.0 as f32, |acc, x| acc.max(*x));
let min = res.0.iter().fold(0.0 as f32, |acc, x| acc.min(*x));
assert!(max > 0.8 && max < 1.01 && min < -0.8 && min > -1.01);
}
#[test]
fn check_no_dc_bias_at_formant_freq_lower_than_freq() {
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("formant", "sig").node_inp("out", "ch1").place(&mut matrix, 0, 0).unwrap();
matrix.sync().unwrap();
let formant = NodeId::Formant(0);
// params
let freq_p = formant.inp_param("freq").unwrap();
let form_p = formant.inp_param("form").unwrap();
let atk_p = formant.inp_param("atk").unwrap();
let dcy_p = formant.inp_param("dcy").unwrap();
// set params to reasonable values
matrix.set_param(freq_p, SAtom::param(0.0));
matrix.set_param(form_p, SAtom::param(-0.2));
matrix.set_param(atk_p, SAtom::param(0.2));
matrix.set_param(dcy_p, SAtom::param(-0.2));
// run
let res = run_for_ms(&mut node_exec, 100.0);
// average should remain at ~0
let sum = res.0.iter().sum::<f32>();
let avg = sum / res.0.len() as f32;
assert!(avg > -0.05 && avg < 0.05);
}
#[test]
fn check_no_nan() {
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("formant", "sig").node_inp("out", "ch1").place(&mut matrix, 0, 0).unwrap();
matrix.sync().unwrap();
let formant = NodeId::Formant(0);
// params
let freq_p = formant.inp_param("freq").unwrap();
let form_p = formant.inp_param("form").unwrap();
let atk_p = formant.inp_param("atk").unwrap();
let dcy_p = formant.inp_param("dcy").unwrap();
// set params to non-reasonable values here
// base freq 0
matrix.set_param(freq_p, SAtom::param(-1.0));
matrix.set_param(form_p, SAtom::param(0.0));
matrix.set_param(atk_p, SAtom::param(0.2));
matrix.set_param(dcy_p, SAtom::param(-0.2));
// run
let res = run_for_ms(&mut node_exec, 100.0);
// and check there's no NaN
assert!(res.0.iter().all(|x| !x.is_nan()));
// set params to non-reasonable values here
// base freq attack freq 0
matrix.set_param(freq_p, SAtom::param(-0.2));
matrix.set_param(form_p, SAtom::param(0.0));
matrix.set_param(atk_p, SAtom::param(-1.0));
matrix.set_param(dcy_p, SAtom::param(-0.2));
// run
let res = run_for_ms(&mut node_exec, 100.0);
// and check there's no NaN
assert!(res.0.iter().all(|x| !x.is_nan()));
// set params to non-reasonable values here
// decay freq freq 0
matrix.set_param(freq_p, SAtom::param(-0.2));
matrix.set_param(form_p, SAtom::param(0.0));
matrix.set_param(atk_p, SAtom::param(0.2));
matrix.set_param(dcy_p, SAtom::param(-1.0));
// run
let res = run_for_ms(&mut node_exec, 100.0);
// and check there's no NaN
assert!(res.0.iter().all(|x| !x.is_nan()));
}
#[test]
fn check_formant_freq() {}