diff --git a/src/dsp/mod.rs b/src/dsp/mod.rs index c7c59eb..81b4594 100644 --- a/src/dsp/mod.rs +++ b/src/dsp/mod.rs @@ -963,6 +963,23 @@ macro_rules! make_node_info_enum { } } + /// Consistently initialize the phase for oscillators. + /// This does some fixed phase offset for the first 3 + /// instances, which is usually relied on by the automated + /// tests. + #[inline] + pub fn init_phase(&self) -> f32 { + // The first 3 instances get a fixed predefined phase to + // not mess up the automated tests so easily. + match self.instance() { + 0 => 0.0, + 1 => 0.05, + 2 => 0.1, + // 0.25 just to protect against sine cancellation + _ => crate::dsp::helpers::rand_01() * 0.25 + } + } + /// This maps the atom index of the node to the absolute /// ParamId in the GUI (and in the [crate::matrix::Matrix]). /// The Atom/Param duality is a bit weird because they share diff --git a/src/dsp/node_bosc.rs b/src/dsp/node_bosc.rs index 1589ef3..3796c18 100644 --- a/src/dsp/node_bosc.rs +++ b/src/dsp/node_bosc.rs @@ -4,7 +4,7 @@ use crate::nodes::{NodeAudioContext, NodeExecContext}; use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext}; -use crate::dsp::helpers::{rand_01, PolyBlepOscillator}; +use crate::dsp::helpers::PolyBlepOscillator; #[macro_export] macro_rules! fa_bosc_wtype { ($formatter: expr, $v: expr, $denorm_v: expr) => { { @@ -28,13 +28,7 @@ pub struct BOsc { impl BOsc { pub fn new(nid: &NodeId) -> Self { - let init_phase = - if nid.instance() > 0 { - // 0.5 just to protect against sine cancellation - rand_01() * 0.5 - } else { - 0.0 - }; + let init_phase = nid.init_phase(); Self { osc: PolyBlepOscillator::new(init_phase), diff --git a/src/dsp/node_sin.rs b/src/dsp/node_sin.rs index 3611492..04b2535 100644 --- a/src/dsp/node_sin.rs +++ b/src/dsp/node_sin.rs @@ -16,15 +16,20 @@ pub struct Sin { srate: f32, /// Oscillator phase phase: f32, + /// Initial phase offset + init_phase: f32, } const TWOPI : f32 = 2.0 * std::f32::consts::PI; impl Sin { - pub fn new(_nid: &NodeId) -> Self { + pub fn new(nid: &NodeId) -> Self { + let init_phase = nid.init_phase(); + Self { srate: 44100.0, - phase: 0.0, + phase: init_phase, + init_phase, } } pub const freq : &'static str = @@ -70,7 +75,7 @@ impl DspNode for Sin { } fn reset(&mut self) { - self.phase = 0.0; + self.phase = self.init_phase; } #[inline] diff --git a/tests/basics.rs b/tests/basics.rs index d4fe558..231a138 100644 --- a/tests/basics.rs +++ b/tests/basics.rs @@ -45,8 +45,8 @@ fn check_matrix_sine() { let sin_led_val = matrix.led_value_for(&sin); let out_led_val = matrix.led_value_for(&out); - assert_float_eq!(sin_led_val, -0.057622954); - assert_float_eq!(out_led_val, -0.057622954); + assert_float_eq!(sin_led_val, 0.54018); + assert_float_eq!(out_led_val, 0.54018); } #[test] @@ -94,7 +94,7 @@ fn check_sine_pitch_change() { let (node_conf, mut node_exec) = new_node_engine(); let mut matrix = Matrix::new(node_conf, 3, 3); - let sin = NodeId::Sin(2); + let sin = NodeId::Sin(0); let out = NodeId::Out(0); matrix.place(0, 0, Cell::empty(sin) .out(None, sin.out("sig"), None)); @@ -255,7 +255,7 @@ fn check_matrix_monitor() { } let rms_mimax = calc_rms_mimax_each_ms(&out_l[..], 50.0); - assert_float_eq!(rms_mimax[0].0, 0.5013241); + assert_float_eq!(rms_mimax[0].0, 0.49901); // let ta = std::time::Instant::now(); @@ -1082,10 +1082,10 @@ fn check_matrix_node_feedback() { // The frequency will be established a bit later because // the parameter setting of 880 Hz will be smoothed: 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.6889244, 0.9872897, 0.40561166, -0.5643036, -0.99751425, - -0.42060927, 0.6112674, 0.979101, 0.21974884, -0.81355125, - -0.83687085, 0.23462467, 0.9970811, 0.35165882, -0.8186541, - -0.7396998, 0.5222105, 0.9234876, -0.2683919, -0.983062 ]); + 0.8791775, 0.8898413, 0.10330327, -0.79178804, -0.92698133, + -0.11967586, 0.8259115, 0.86836, -0.09246742, -0.9534301, + -0.62676203, 0.5235326, 0.9718173, 0.04517236, -0.9560416, + -0.49554884, 0.7601789, 0.75973713, -0.5529301, -0.8783003 ]); // Let the frequency settle... run_for_ms(&mut node_exec, 80.0); diff --git a/tests/modamt.rs b/tests/modamt.rs index 058cd6c..1d2ed50 100644 --- a/tests/modamt.rs +++ b/tests/modamt.rs @@ -42,7 +42,7 @@ fn check_param_mod_amt_with_input() { sin.inp_param("freq").unwrap(), Some(0.2)).unwrap(); let rms = run_and_get_first_rms_mimax(&mut node_exec, 50.0); - assert_rmsmima!(rms, (0.4992, -1.0, 1.0)); + assert_rmsmima!(rms, (0.48997, -1.0, 1.0)); } #[test] diff --git a/tests/node_delay.rs b/tests/node_delay.rs index bfe53e1..58057bc 100644 --- a/tests/node_delay.rs +++ b/tests/node_delay.rs @@ -83,7 +83,7 @@ fn check_node_delay_time_mod() { let (node_conf, mut node_exec) = new_node_engine(); let mut matrix = Matrix::new(node_conf, 4, 4); - let sin = NodeId::Sin(0); + let sin = NodeId::Sin(1); let dly = NodeId::Delay(0); let out = NodeId::Out(0); matrix.place(1, 1, Cell::empty(sin) @@ -106,7 +106,7 @@ fn check_node_delay_time_mod() { assert_eq!(fft[0], (431, 614)); assert_eq!(fft[1], (441, 1012)); - let sin2 = NodeId::Sin(1); + let sin2 = NodeId::Sin(0); matrix.place(0, 3, Cell::empty(sin2) .out(sin2.out("sig"), None, None)); @@ -122,15 +122,15 @@ fn check_node_delay_time_mod() { let fft = run_and_get_fft4096_now(&mut node_exec, 110); // Expect a sine sweep over a // range of low frequencies: - assert_eq!(fft[0], (108, 111)); - assert_eq!(fft[5], (312, 110)); - assert_eq!(fft[10], (700, 110)); + assert_eq!(fft[0], (86, 112)); + assert_eq!(fft[5], (237, 112)); + assert_eq!(fft[10], (517, 111)); // Sweep upwards: run_for_ms(&mut node_exec, 300.0); let fft = run_and_get_fft4096_now(&mut node_exec, 122); assert_eq!(fft[0], (2509, 123)); - assert_eq!(fft[8], (2821, 123)); + assert_eq!(fft[7], (2821, 123)); // Sweep at mostly highest point: run_for_ms(&mut node_exec, 700.0);