From d6c1a381029fbabb928ddb2f95c8ecb63c0f59d9 Mon Sep 17 00:00:00 2001 From: Weird Constructor Date: Sun, 8 Aug 2021 00:56:10 +0200 Subject: [PATCH] Working on making the stuff in hexodsp::dsp::helpers f32/f64 agnostic --- Cargo.toml | 1 + src/dsp/dattorro.rs | 126 ++++++++++++++++----------------- src/dsp/helpers.rs | 161 ++++++++++++++++++++++-------------------- src/dsp/node_allp.rs | 10 +-- src/dsp/node_delay.rs | 2 +- src/dsp/node_pverb.rs | 58 +++++++-------- src/dsp/node_tslfo.rs | 8 +-- 7 files changed, 187 insertions(+), 179 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index eb17156..5b05932 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ lazy_static = "1.4.0" #hexotk = { optional = true, git = "https://github.com/WeirdConstructor/HexoTK.git" } #hexotk = { optional = true, path = "../hexotk" } hound = "3.4.0" +num-traits = "0.2.14" [dev-dependencies] num-complex = "0.2" diff --git a/src/dsp/dattorro.rs b/src/dsp/dattorro.rs index dd67a7a..985f251 100644 --- a/src/dsp/dattorro.rs +++ b/src/dsp/dattorro.rs @@ -17,29 +17,29 @@ use crate::dsp::helpers::crossfade; -const DAT_SAMPLE_RATE : f32 = 29761.0; -const DAT_SAMPLES_PER_MS : f32 = DAT_SAMPLE_RATE / 1000.0; +const DAT_SAMPLE_RATE : f64 = 29761.0; +const DAT_SAMPLES_PER_MS : f64 = DAT_SAMPLE_RATE / 1000.0; -const DAT_INPUT_APF_TIMES_MS : [f32; 4] = [ +const DAT_INPUT_APF_TIMES_MS : [f64; 4] = [ 141.0 / DAT_SAMPLES_PER_MS, 107.0 / DAT_SAMPLES_PER_MS, 379.0 / DAT_SAMPLES_PER_MS, 277.0 / DAT_SAMPLES_PER_MS, ]; -const DAT_LEFT_APF1_TIME_MS : f32 = 672.0 / DAT_SAMPLES_PER_MS; -const DAT_LEFT_APF2_TIME_MS : f32 = 1800.0 / DAT_SAMPLES_PER_MS; +const DAT_LEFT_APF1_TIME_MS : f64 = 672.0 / DAT_SAMPLES_PER_MS; +const DAT_LEFT_APF2_TIME_MS : f64 = 1800.0 / DAT_SAMPLES_PER_MS; -const DAT_RIGHT_APF1_TIME_MS : f32 = 908.0 / DAT_SAMPLES_PER_MS; -const DAT_RIGHT_APF2_TIME_MS : f32 = 2656.0 / DAT_SAMPLES_PER_MS; +const DAT_RIGHT_APF1_TIME_MS : f64 = 908.0 / DAT_SAMPLES_PER_MS; +const DAT_RIGHT_APF2_TIME_MS : f64 = 2656.0 / DAT_SAMPLES_PER_MS; -const DAT_LEFT_DELAY1_TIME_MS : f32 = 4453.0 / DAT_SAMPLES_PER_MS; -const DAT_LEFT_DELAY2_TIME_MS : f32 = 3720.0 / DAT_SAMPLES_PER_MS; +const DAT_LEFT_DELAY1_TIME_MS : f64 = 4453.0 / DAT_SAMPLES_PER_MS; +const DAT_LEFT_DELAY2_TIME_MS : f64 = 3720.0 / DAT_SAMPLES_PER_MS; -const DAT_RIGHT_DELAY1_TIME_MS : f32 = 4217.0 / DAT_SAMPLES_PER_MS; -const DAT_RIGHT_DELAY2_TIME_MS : f32 = 3163.0 / DAT_SAMPLES_PER_MS; +const DAT_RIGHT_DELAY1_TIME_MS : f64 = 4217.0 / DAT_SAMPLES_PER_MS; +const DAT_RIGHT_DELAY2_TIME_MS : f64 = 3163.0 / DAT_SAMPLES_PER_MS; -const DAT_LEFT_TAPS_TIME_MS : [f32; 7] = [ +const DAT_LEFT_TAPS_TIME_MS : [f64; 7] = [ 266.0 / DAT_SAMPLES_PER_MS, 2974.0 / DAT_SAMPLES_PER_MS, 1913.0 / DAT_SAMPLES_PER_MS, @@ -49,7 +49,7 @@ const DAT_LEFT_TAPS_TIME_MS : [f32; 7] = [ 1066.0 / DAT_SAMPLES_PER_MS, ]; -const DAT_RIGHT_TAPS_TIME_MS : [f32; 7] = [ +const DAT_RIGHT_TAPS_TIME_MS : [f64; 7] = [ 353.0 / DAT_SAMPLES_PER_MS, 3627.0 / DAT_SAMPLES_PER_MS, 1228.0 / DAT_SAMPLES_PER_MS, @@ -59,15 +59,15 @@ const DAT_RIGHT_TAPS_TIME_MS : [f32; 7] = [ 121.0 / DAT_SAMPLES_PER_MS, ]; -const DAT_LFO_FREQS_HZ : [f32; 4] = [ 0.1, 0.15, 0.12, 0.18 ]; +const DAT_LFO_FREQS_HZ : [f64; 4] = [ 0.1, 0.15, 0.12, 0.18 ]; -const DAT_INPUT_DIFFUSION1 : f32 = 0.75; -const DAT_INPUT_DIFFUSION2 : f32 = 0.625; -const DAT_PLATE_DIFFUSION1 : f32 = 0.7; -const DAT_PLATE_DIFFUSION2 : f32 = 0.5; +const DAT_INPUT_DIFFUSION1 : f64 = 0.75; +const DAT_INPUT_DIFFUSION2 : f64 = 0.625; +const DAT_PLATE_DIFFUSION1 : f64 = 0.7; +const DAT_PLATE_DIFFUSION2 : f64 = 0.5; -const DAT_LFO_EXCURSION_MS : f32 = 16.0 / DAT_SAMPLES_PER_MS; -const DAT_LFO_EXCURSION_MOD_MAX : f32 = 16.0; +const DAT_LFO_EXCURSION_MS : f64 = 16.0 / DAT_SAMPLES_PER_MS; +const DAT_LFO_EXCURSION_MOD_MAX : f64 = 16.0; use crate::dsp::helpers::{ AllPass, @@ -80,28 +80,28 @@ use crate::dsp::helpers::{ #[derive(Debug, Clone)] pub struct DattorroReverb { - last_scale: f32, + last_scale: f64, - inp_dc_block: [DCBlockFilter; 2], - out_dc_block: [DCBlockFilter; 2], + inp_dc_block: [DCBlockFilter; 2], + out_dc_block: [DCBlockFilter; 2], - lfos: [TriSawLFO; 4], + lfos: [TriSawLFO; 4], - input_hpf: OnePoleHPF, - input_lpf: OnePoleLPF, + input_hpf: OnePoleHPF, + input_lpf: OnePoleLPF, - pre_delay: DelayBuffer, - input_apfs: [(AllPass, f32, f32); 4], + pre_delay: DelayBuffer, + input_apfs: [(AllPass, f64, f64); 4], - apf1: [(AllPass, f32, f32); 2], - hpf: [OnePoleHPF; 2], - lpf: [OnePoleLPF; 2], - apf2: [(AllPass, f32, f32); 2], - delay1: [(DelayBuffer, f32); 2], - delay2: [(DelayBuffer, f32); 2], + apf1: [(AllPass, f64, f64); 2], + hpf: [OnePoleHPF; 2], + lpf: [OnePoleLPF; 2], + apf2: [(AllPass, f64, f64); 2], + delay1: [(DelayBuffer, f64); 2], + delay2: [(DelayBuffer, f64); 2], - left_sum: f32, - right_sum: f32, + left_sum: f64, + right_sum: f64, dbg_count: usize, } @@ -109,30 +109,30 @@ pub struct DattorroReverb { pub trait DattorroReverbParams { /// Time for the pre-delay of the reverb. Any sensible `ms` that fits /// into a delay buffer of 5 seconds. - fn pre_delay_time_ms(&self) -> f32; + fn pre_delay_time_ms(&self) -> f64; /// The size of the reverb, values go from 0.0 to 1.0. - fn time_scale(&self) -> f32; + fn time_scale(&self) -> f64; /// High-pass input filter cutoff freq in Hz, range: 0.0 to 22000.0 - fn input_high_cutoff_hz(&self) -> f32; + fn input_high_cutoff_hz(&self) -> f64; /// Low-pass input filter cutoff freq in Hz, range: 0.0 to 22000.0 - fn input_low_cutoff_hz(&self) -> f32; + fn input_low_cutoff_hz(&self) -> f64; /// High-pass reverb filter cutoff freq in Hz, range: 0.0 to 22000.0 - fn reverb_high_cutoff_hz(&self) -> f32; + fn reverb_high_cutoff_hz(&self) -> f64; /// Low-pass reverb filter cutoff freq in Hz, range: 0.0 to 22000.0 - fn reverb_low_cutoff_hz(&self) -> f32; + fn reverb_low_cutoff_hz(&self) -> f64; /// Modulation speed factor, range: 0.0 to 1.0 - fn mod_speed(&self) -> f32; + fn mod_speed(&self) -> f64; /// Modulation depth from the LFOs, range: 0.0 to 1.0 - fn mod_depth(&self) -> f32; + fn mod_depth(&self) -> f64; /// Modulation shape (from saw to tri to saw), range: 0.0 to 1.0 - fn mod_shape(&self) -> f32; + fn mod_shape(&self) -> f64; /// The mix between output from the pre-delay and the input diffusion. /// range: 0.0 to 1.0. Default should be 1.0 - fn input_diffusion_mix(&self) -> f32; + fn input_diffusion_mix(&self) -> f64; /// The amount of plate diffusion going on, range: 0.0 to 1.0 - fn diffusion(&self) -> f32; + fn diffusion(&self) -> f64; /// Internal tank decay time, range: 0.0 to 1.0 - fn decay(&self) -> f32; + fn decay(&self) -> f64; } impl DattorroReverb { @@ -236,8 +236,8 @@ impl DattorroReverb { } #[inline] - pub fn set_time_scale(&mut self, scale: f32) { - if (self.last_scale - scale).abs() > std::f32::EPSILON { + pub fn set_time_scale(&mut self, scale: f64) { + if (self.last_scale - scale).abs() > std::f64::EPSILON { let scale = scale.max(0.0001); self.last_scale = scale; @@ -253,7 +253,7 @@ impl DattorroReverb { } } - pub fn set_sample_rate(&mut self, srate: f32) { + pub fn set_sample_rate(&mut self, srate: f64) { self.inp_dc_block[0].set_sample_rate(srate); self.inp_dc_block[1].set_sample_rate(srate); self.out_dc_block[0].set_sample_rate(srate); @@ -292,29 +292,29 @@ impl DattorroReverb { #[inline] fn calc_apf_delay_times(&mut self, params: &mut dyn DattorroReverbParams) - -> (f32, f32, f32, f32) + -> (f64, f64, f64, f64) { let left_apf1_delay_ms = self.apf1[0].1 - + (self.lfos[0].next_unipolar() as f32 + + (self.lfos[0].next_unipolar() as f64 * DAT_LFO_EXCURSION_MS * DAT_LFO_EXCURSION_MOD_MAX * params.mod_depth()); let right_apf1_delay_ms = self.apf1[1].1 - + (self.lfos[1].next_unipolar() as f32 + + (self.lfos[1].next_unipolar() as f64 * DAT_LFO_EXCURSION_MS * DAT_LFO_EXCURSION_MOD_MAX * params.mod_depth()); let left_apf2_delay_ms = self.apf2[0].1 - + (self.lfos[2].next_unipolar() as f32 + + (self.lfos[2].next_unipolar() as f64 * DAT_LFO_EXCURSION_MS * DAT_LFO_EXCURSION_MOD_MAX * params.mod_depth()); let right_apf2_delay_ms = self.apf2[1].1 - + (self.lfos[3].next_unipolar() as f32 + + (self.lfos[3].next_unipolar() as f64 * DAT_LFO_EXCURSION_MS * DAT_LFO_EXCURSION_MOD_MAX * params.mod_depth()); @@ -326,8 +326,8 @@ impl DattorroReverb { pub fn process( &mut self, params: &mut dyn DattorroReverbParams, - input_l: f32, input_r: f32 - ) -> (f32, f32) + input_l: f64, input_r: f64 + ) -> (f64, f64) { // Some parameter setup... let timescale = 0.0025 + (4.0 - 0.0025) * params.time_scale(); @@ -373,9 +373,9 @@ impl DattorroReverb { let out_hpf = self.input_hpf.process(out_lpf); // HPF => Pre-Delay - let out_pre_delay = - self.pre_delay.cubic_interpolate_at(params.pre_delay_time_ms()); - self.pre_delay.feed(out_hpf); + let out_pre_delay = out_hpf; +// self.pre_delay.cubic_interpolate_at(params.pre_delay_time_ms()); +// self.pre_delay.feed(out_hpf); // Pre-Delay => 4 All-Pass filters let mut diffused = out_pre_delay; @@ -384,8 +384,8 @@ impl DattorroReverb { } // Mix between diffused and pre-delayed intput for further processing - let tank_feed = - crossfade(out_pre_delay, diffused, params.input_diffusion_mix()); + let tank_feed = out_pre_delay; +// crossfade(out_pre_delay, diffused, params.input_diffusion_mix()); // First tap for the output self.left_sum += tank_feed; diff --git a/src/dsp/helpers.rs b/src/dsp/helpers.rs index 93fc1bb..b3d2ff9 100644 --- a/src/dsp/helpers.rs +++ b/src/dsp/helpers.rs @@ -3,6 +3,7 @@ // See README.md and COPYING for details. use std::cell::RefCell; +use num_traits::{Float, FloatConst, cast::FromPrimitive}; /// Logarithmic table size of the table in [fast_cos] / [fast_sin]. static FAST_COS_TAB_LOG2_SIZE : usize = 9; @@ -698,31 +699,35 @@ impl TriggerSampleClock { /// Default size of the delay buffer: 5 seconds at 8 times 48kHz const DEFAULT_DELAY_BUFFER_SAMPLES : usize = 8 * 48000 * 5; -#[derive(Debug, Clone, Default)] -pub struct DelayBuffer { - data: Vec, - wr: usize, - srate: f32, +macro_rules! fc { + ($F: ident, $e: expr) => { F::from_f64($e).unwrap() } } -impl DelayBuffer { +#[derive(Debug, Clone, Default)] +pub struct DelayBuffer { + data: Vec, + wr: usize, + srate: F, +} + +impl DelayBuffer { pub fn new() -> Self { Self { - data: vec![0.0; DEFAULT_DELAY_BUFFER_SAMPLES], + data: vec![fc!(F,0.0); DEFAULT_DELAY_BUFFER_SAMPLES], wr: 0, - srate: 44100.0, + srate: fc!(F, 44100.0), } } pub fn new_with_size(size: usize) -> Self { Self { - data: vec![0.0; size], + data: vec![fc!(F, 0.0); size], wr: 0, - srate: 44100.0, + srate: fc!(F, 44100.0), } } - pub fn set_sample_rate(&mut self, srate: f32) { + pub fn set_sample_rate(&mut self, srate: F) { self.srate = srate; } @@ -735,7 +740,7 @@ impl DelayBuffer { /// Please note: For sample accurate feedback you need to retrieve the /// output of the delay line before feeding in a new signal. #[inline] - pub fn feed(&mut self, input: f32) { + pub fn feed(&mut self, input: F) { self.data[self.wr] = input; self.wr = (self.wr + 1) % self.data.len(); } @@ -743,7 +748,7 @@ impl DelayBuffer { /// Combines [DelayBuffer::cubic_interpolate_at] and [DelayBuffer::feed] /// into one convenient function. #[inline] - pub fn next_cubic(&mut self, delay_time_ms: f32, input: f32) -> f32 { + pub fn next_cubic(&mut self, delay_time_ms: F, input: F) -> F { let res = self.cubic_interpolate_at(delay_time_ms); self.feed(input); res @@ -751,26 +756,26 @@ impl DelayBuffer { /// Shorthand for [DelayBuffer::cubic_interpolate_at]. #[inline] - pub fn tap_c(&self, delay_time_ms: f32) -> f32 { + pub fn tap_c(&self, delay_time_ms: F) -> F { self.cubic_interpolate_at(delay_time_ms) } /// Shorthand for [DelayBuffer::cubic_interpolate_at]. #[inline] - pub fn tap_n(&self, delay_time_ms: f32) -> f32 { + pub fn tap_n(&self, delay_time_ms: F) -> F { self.nearest_at(delay_time_ms) } /// Shorthand for [DelayBuffer::cubic_interpolate_at]. #[inline] - pub fn tap_l(&self, delay_time_ms: f32) -> f32 { + pub fn tap_l(&self, delay_time_ms: F) -> F { self.linear_interpolate_at(delay_time_ms) } /// Fetch a sample from the delay buffer at the given time. /// /// * `delay_time_ms` - Delay time in milliseconds. - pub fn linear_interpolate_at(&self, delay_time_ms: f32) -> f32 { + pub fn linear_interpolate_at(&self, delay_time_ms: F) -> F { let data = &self.data[..]; let len = data.len(); let s_offs = (delay_time_ms * self.srate) / 1000.0; @@ -781,7 +786,7 @@ impl DelayBuffer { let x0 = data[i % len]; let x1 = data[(i + 1) % len]; - let fract = fract as f32; + let fract = fract as F; x0 * (1.0 - fract) + x1 * fract } @@ -789,7 +794,7 @@ impl DelayBuffer { /// /// * `delay_time_ms` - Delay time in milliseconds. #[inline] - pub fn cubic_interpolate_at(&self, delay_time_ms: f32) -> f32 { + pub fn cubic_interpolate_at(&self, delay_time_ms: F) -> F { let data = &self.data[..]; let len = data.len(); let s_offs = (delay_time_ms * self.srate) / 1000.0; @@ -816,12 +821,12 @@ impl DelayBuffer { let a = w + v + (x2 - x0) * 0.5; let b_neg = w + a; - let fract = fract as f32; + let fract = fract as F; (((a * fract) - b_neg) * fract + c) * fract + x0 } #[inline] - pub fn nearest_at(&self, delay_time_ms: f32) -> f32 { + pub fn nearest_at(&self, delay_time_ms: F) -> F { let len = self.data.len(); let offs = ((delay_time_ms * self.srate) / 1000.0).floor() as usize % len; let idx = ((self.wr + len) - offs) % len; @@ -829,7 +834,7 @@ impl DelayBuffer { } #[inline] - pub fn at(&self, delay_sample_count: usize) -> f32 { + pub fn at(&self, delay_sample_count: usize) -> F { let len = self.data.len(); let idx = ((self.wr + len) - delay_sample_count) % len; self.data[idx] @@ -840,18 +845,18 @@ impl DelayBuffer { const DEFAULT_ALLPASS_COMB_SAMPLES : usize = 8 * 48000; #[derive(Debug, Clone, Default)] -pub struct AllPass { - delay: DelayBuffer, +pub struct AllPass { + delay: DelayBuffer, } -impl AllPass { +impl AllPass { pub fn new() -> Self { Self { delay: DelayBuffer::new_with_size(DEFAULT_ALLPASS_COMB_SAMPLES), } } - pub fn set_sample_rate(&mut self, srate: f32) { + pub fn set_sample_rate(&mut self, srate: F) { self.delay.set_sample_rate(srate); } @@ -860,13 +865,13 @@ impl AllPass { } #[inline] - pub fn delay_tap_n(&self, time_ms: f32) -> f32 { + pub fn delay_tap_n(&self, time_ms: F) -> F { self.delay.tap_n(time_ms) } #[inline] - pub fn next(&mut self, time_ms: f32, g: f32, v: f32) -> f32 { - let s = self.delay.linear_interpolate_at(time_ms); + pub fn next(&mut self, time_ms: F, g: F, v: F) -> F { + let s = self.delay.nearest_at(time_ms); let input = v + -g * s; self.delay.feed(input); input * g + s @@ -875,7 +880,7 @@ impl AllPass { #[derive(Debug, Clone)] pub struct Comb { - delay: DelayBuffer, + delay: DelayBuffer, } impl Comb { @@ -951,15 +956,15 @@ pub fn process_1pole_lowpass(input: f32, freq: f32, israte: f32, z: &mut f32) -> } #[derive(Debug, Clone, Copy, Default)] -pub struct OnePoleLPF { - israte: f32, - a: f32, - b: f32, - freq: f32, - z: f32, +pub struct OnePoleLPF { + israte: F, + a: F, + b: F, + freq: F, + z: F, } -impl OnePoleLPF { +impl OnePoleLPF { pub fn new() -> Self { Self { israte: 1.0 / 44100.0, @@ -976,17 +981,17 @@ impl OnePoleLPF { #[inline] fn recalc(&mut self) { - self.b = (-std::f32::consts::TAU * self.freq * self.israte).exp(); + self.b = (-F::TAU * self.freq * self.israte).exp(); self.a = 1.0 - self.b; } - pub fn set_sample_rate(&mut self, srate: f32) { + pub fn set_sample_rate(&mut self, srate: F) { self.israte = 1.0 / srate; self.recalc(); } #[inline] - pub fn set_freq(&mut self, freq: f32) { + pub fn set_freq(&mut self, freq: F) { if freq != self.freq { self.freq = freq; self.recalc(); @@ -994,7 +999,7 @@ impl OnePoleLPF { } #[inline] - pub fn process(&mut self, input: f32) -> f32 { + pub fn process(&mut self, input: F) -> F { self.z = self.a * input + self.z * self.b; self.z } @@ -1040,16 +1045,16 @@ pub fn process_1pole_highpass(input: f32, freq: f32, israte: f32, z: &mut f32, y } #[derive(Debug, Clone, Copy, Default)] -pub struct OnePoleHPF { - israte: f32, - a: f32, - b: f32, - freq: f32, - z: f32, - y: f32, +pub struct OnePoleHPF { + israte: F, + a: F, + b: F, + freq: F, + z: F, + y: F, } -impl OnePoleHPF { +impl OnePoleHPF { pub fn new() -> Self { Self { israte: 1.0 / 44100.0, @@ -1068,18 +1073,18 @@ impl OnePoleHPF { #[inline] fn recalc(&mut self) { - self.b = (-std::f32::consts::TAU * self.freq * self.israte).exp(); + self.b = (-F::TAU * self.freq * self.israte).exp(); self.a = (1.0 + self.b) / 2.0; } - pub fn set_sample_rate(&mut self, srate: f32) { + pub fn set_sample_rate(&mut self, srate: F) { self.israte = 1.0 / srate; self.recalc(); } #[inline] - pub fn set_freq(&mut self, freq: f32) { + pub fn set_freq(&mut self, freq: F) { if freq != self.freq { self.freq = freq; self.recalc(); @@ -1087,7 +1092,7 @@ impl OnePoleHPF { } #[inline] - pub fn process(&mut self, input: f32) -> f32 { + pub fn process(&mut self, input: F) -> F { let v = self.a * input - self.a * self.z @@ -1396,13 +1401,13 @@ pub fn process_stilson_moog( // Copyright (C) 2020 TheWaveWarden // under GPLv3 or any later #[derive(Debug, Clone, Copy)] -pub struct DCBlockFilter { - xm1: f64, - ym1: f64, - r: f64, +pub struct DCBlockFilter { + xm1: F, + ym1: F, + r: F, } -impl DCBlockFilter { +impl DCBlockFilter { pub fn new() -> Self { Self { xm1: 0.0, @@ -1416,7 +1421,7 @@ impl DCBlockFilter { self.ym1 = 0.0; } - pub fn set_sample_rate(&mut self, srate: f32) { + pub fn set_sample_rate(&mut self, srate: F) { self.r = 0.995; if srate > 90000.0 { self.r = 0.9965; @@ -1425,11 +1430,11 @@ impl DCBlockFilter { } } - pub fn next(&mut self, input: f32) -> f32 { + pub fn next(&mut self, input: F) -> F { let y = input as f64 - self.xm1 + self.r * self.ym1; self.xm1 = input as f64; self.ym1 = y; - y as f32 + y as F } } @@ -1878,25 +1883,25 @@ impl VPSOscillator { /// An LFO with a variable reverse point, which can go from reverse Saw, to Tri /// and to Saw, depending on the reverse point. #[derive(Debug, Clone, Copy)] -pub struct TriSawLFO { +pub struct TriSawLFO { /// The (inverse) sample rate. Eg. 1.0 / 44100.0. - israte: f64, + israte: F, /// The current oscillator phase. - phase: f64, + phase: F, /// The point from where the falling edge will be used. - rev: f64, + rev: F, /// Whether the LFO is currently rising rising: bool, /// The frequency. - freq: f64, + freq: F, /// Precomputed rise/fall rate of the LFO. - rise_r: f64, - fall_r: f64, + rise_r: F, + fall_r: F, /// Initial phase offset. - init_phase: f64, + init_phase: F, } -impl TriSawLFO { +impl TriSawLFO { pub fn new() -> Self { let mut this = Self { israte: 1.0 / 44100.0, @@ -1912,7 +1917,7 @@ impl TriSawLFO { this } - pub fn set_phase_offs(&mut self, phase: f64) { + pub fn set_phase_offs(&mut self, phase: F) { self.init_phase = phase; self.phase = phase; } @@ -1924,8 +1929,8 @@ impl TriSawLFO { self.fall_r = -1.0 / (1.0 - self.rev); } - pub fn set_sample_rate(&mut self, srate: f32) { - self.israte = 1.0 / (srate as f64); + pub fn set_sample_rate(&mut self, srate: F) { + self.israte = 1.0 / (srate as F); self.recalc(); } @@ -1936,14 +1941,14 @@ impl TriSawLFO { } #[inline] - pub fn set(&mut self, freq: f32, rev: f32) { - self.freq = freq as f64; - self.rev = rev as f64; + pub fn set(&mut self, freq: F, rev: F) { + self.freq = freq as F; + self.rev = rev as F; self.recalc(); } #[inline] - pub fn next_unipolar(&mut self) -> f64 { + pub fn next_unipolar(&mut self) -> F { if self.phase >= 1.0 { self.phase -= 1.0; self.rising = true; @@ -1966,7 +1971,7 @@ impl TriSawLFO { } #[inline] - pub fn next_bipolar(&mut self) -> f64 { + pub fn next_bipolar(&mut self) -> F { (self.next_unipolar() * 2.0) - 1.0 } } diff --git a/src/dsp/node_allp.rs b/src/dsp/node_allp.rs index 4953bd7..a17c19e 100644 --- a/src/dsp/node_allp.rs +++ b/src/dsp/node_allp.rs @@ -9,7 +9,7 @@ use crate::dsp::helpers::AllPass; /// A simple amplifier #[derive(Debug, Clone)] pub struct AllP { - allpass: Box, + allpass: Box>, } impl AllP { @@ -72,7 +72,7 @@ impl DspNode for AllP { fn outputs() -> usize { 1 } fn set_sample_rate(&mut self, srate: f32) { - self.allpass.set_sample_rate(srate); + self.allpass.set_sample_rate(srate as f64); } fn reset(&mut self) { @@ -100,9 +100,9 @@ impl DspNode for AllP { out.write(frame, ap.next( - denorm::AllP::time(time, frame), - denorm::AllP::g(g, frame), - v)); + denorm::AllP::time(time, frame) as f64, + denorm::AllP::g(g, frame) as f64, + v as f64) as f32); } let last_frame = ctx.nframes() - 1; diff --git a/src/dsp/node_delay.rs b/src/dsp/node_delay.rs index 9c403f3..b887707 100644 --- a/src/dsp/node_delay.rs +++ b/src/dsp/node_delay.rs @@ -20,7 +20,7 @@ macro_rules! fa_delay_mode { ($formatter: expr, $v: expr, $denorm_v: expr) => { /// A simple amplifier #[derive(Debug, Clone)] pub struct Delay { - buffer: Box, + buffer: Box>, clock: TriggerSampleClock, } diff --git a/src/dsp/node_pverb.rs b/src/dsp/node_pverb.rs index bc90288..619d2be 100644 --- a/src/dsp/node_pverb.rs +++ b/src/dsp/node_pverb.rs @@ -36,41 +36,41 @@ impl DatParams { } impl DattorroReverbParams for DatParams { - fn pre_delay_time_ms(&self) -> f32 { - denorm::PVerb::predly(&self.predly, self.frame) + fn pre_delay_time_ms(&self) -> f64 { + denorm::PVerb::predly(&self.predly, self.frame) as f64 } - fn time_scale(&self) -> f32 { - denorm::PVerb::size(&self.size, self.frame) + fn time_scale(&self) -> f64 { + denorm::PVerb::size(&self.size, self.frame) as f64 } - fn decay(&self) -> f32 { - denorm::PVerb::dcy(&self.dcy, self.frame) + fn decay(&self) -> f64 { + denorm::PVerb::dcy(&self.dcy, self.frame) as f64 } - fn input_low_cutoff_hz(&self) -> f32 { - denorm::PVerb::ilpf(&self.ilpf, self.frame) + fn input_low_cutoff_hz(&self) -> f64 { + denorm::PVerb::ilpf(&self.ilpf, self.frame) as f64 } - fn input_high_cutoff_hz(&self) -> f32 { - denorm::PVerb::ihpf(&self.ihpf, self.frame) + fn input_high_cutoff_hz(&self) -> f64 { + denorm::PVerb::ihpf(&self.ihpf, self.frame) as f64 } - fn diffusion(&self) -> f32 { - denorm::PVerb::idif(&self.idif, self.frame) + fn diffusion(&self) -> f64 { + denorm::PVerb::idif(&self.idif, self.frame) as f64 } - fn input_diffusion_mix(&self) -> f32 { - denorm::PVerb::dmix(&self.dmix, self.frame) + fn input_diffusion_mix(&self) -> f64 { + denorm::PVerb::dmix(&self.dmix, self.frame) as f64 } - fn mod_speed(&self) -> f32 { - denorm::PVerb::mspeed(&self.mspeed, self.frame) + fn mod_speed(&self) -> f64 { + denorm::PVerb::mspeed(&self.mspeed, self.frame) as f64 } - fn mod_depth(&self) -> f32 { - denorm::PVerb::mdepth(&self.mdepth, self.frame) + fn mod_depth(&self) -> f64 { + denorm::PVerb::mdepth(&self.mdepth, self.frame) as f64 } - fn mod_shape(&self) -> f32 { - denorm::PVerb::mshp(&self.mshp, self.frame) + fn mod_shape(&self) -> f64 { + denorm::PVerb::mshp(&self.mshp, self.frame) as f64 } - fn reverb_low_cutoff_hz(&self) -> f32 { - denorm::PVerb::rlpf(&self.rlpf, self.frame) + fn reverb_low_cutoff_hz(&self) -> f64 { + denorm::PVerb::rlpf(&self.rlpf, self.frame) as f64 } - fn reverb_high_cutoff_hz(&self) -> f32 { - denorm::PVerb::rhpf(&self.rhpf, self.frame) + fn reverb_high_cutoff_hz(&self) -> f64 { + denorm::PVerb::rhpf(&self.rhpf, self.frame) as f64 } } @@ -147,7 +147,7 @@ impl DspNode for PVerb { fn outputs() -> usize { 1 } fn set_sample_rate(&mut self, srate: f32) { - self.verb.set_sample_rate(srate); + self.verb.set_sample_rate(srate as f64); } fn reset(&mut self) { @@ -196,10 +196,12 @@ impl DspNode for PVerb { let (i_l, i_r) = (in_l.read(frame), in_r.read(frame)); params.set_frame(frame); - let (l, r) = verb.process(&mut params, i_l, i_r); + let (l, r) = verb.process(&mut params, i_l as f64, i_r as f64); - out_l.write(frame, crossfade(i_l, l, denorm::PVerb::mix(mix, frame))); - out_r.write(frame, crossfade(i_r, r, denorm::PVerb::mix(mix, frame))); + out_l.write( + frame, crossfade(i_l, l as f32, denorm::PVerb::mix(mix, frame))); + out_r.write( + frame, crossfade(i_r, r as f32, denorm::PVerb::mix(mix, frame))); } ctx_vals[0].set( diff --git a/src/dsp/node_tslfo.rs b/src/dsp/node_tslfo.rs index e140111..d524236 100644 --- a/src/dsp/node_tslfo.rs +++ b/src/dsp/node_tslfo.rs @@ -11,7 +11,7 @@ use super::helpers::{TriSawLFO, Trigger}; #[derive(Debug, Clone)] pub struct TsLfo { - lfo: Box, + lfo: Box>, trig: Trigger, } @@ -58,7 +58,7 @@ impl DspNode for TsLfo { fn outputs() -> usize { 1 } fn set_sample_rate(&mut self, srate: f32) { - self.lfo.set_sample_rate(srate); + self.lfo.set_sample_rate(srate as f64); } fn reset(&mut self) { @@ -90,8 +90,8 @@ impl DspNode for TsLfo { let time_ms = denorm::TsLfo::time(time, frame).clamp(0.1, 300000.0); lfo.set( - 1000.0 / time_ms, - denorm::TsLfo::rev(rev, frame)); + (1000.0 / time_ms) as f64, + denorm::TsLfo::rev(rev, frame) as f64); out.write(frame, lfo.next_unipolar() as f32); }