Working on making the stuff in hexodsp::dsp::helpers f32/f64 agnostic
This commit is contained in:
parent
525c8d8c1b
commit
d6c1a38102
7 changed files with 187 additions and 179 deletions
|
@ -20,6 +20,7 @@ lazy_static = "1.4.0"
|
||||||
#hexotk = { optional = true, git = "https://github.com/WeirdConstructor/HexoTK.git" }
|
#hexotk = { optional = true, git = "https://github.com/WeirdConstructor/HexoTK.git" }
|
||||||
#hexotk = { optional = true, path = "../hexotk" }
|
#hexotk = { optional = true, path = "../hexotk" }
|
||||||
hound = "3.4.0"
|
hound = "3.4.0"
|
||||||
|
num-traits = "0.2.14"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
num-complex = "0.2"
|
num-complex = "0.2"
|
||||||
|
|
|
@ -17,29 +17,29 @@
|
||||||
|
|
||||||
use crate::dsp::helpers::crossfade;
|
use crate::dsp::helpers::crossfade;
|
||||||
|
|
||||||
const DAT_SAMPLE_RATE : f32 = 29761.0;
|
const DAT_SAMPLE_RATE : f64 = 29761.0;
|
||||||
const DAT_SAMPLES_PER_MS : f32 = DAT_SAMPLE_RATE / 1000.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,
|
141.0 / DAT_SAMPLES_PER_MS,
|
||||||
107.0 / DAT_SAMPLES_PER_MS,
|
107.0 / DAT_SAMPLES_PER_MS,
|
||||||
379.0 / DAT_SAMPLES_PER_MS,
|
379.0 / DAT_SAMPLES_PER_MS,
|
||||||
277.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_APF1_TIME_MS : f64 = 672.0 / DAT_SAMPLES_PER_MS;
|
||||||
const DAT_LEFT_APF2_TIME_MS : f32 = 1800.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_APF1_TIME_MS : f64 = 908.0 / DAT_SAMPLES_PER_MS;
|
||||||
const DAT_RIGHT_APF2_TIME_MS : f32 = 2656.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_DELAY1_TIME_MS : f64 = 4453.0 / DAT_SAMPLES_PER_MS;
|
||||||
const DAT_LEFT_DELAY2_TIME_MS : f32 = 3720.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_DELAY1_TIME_MS : f64 = 4217.0 / DAT_SAMPLES_PER_MS;
|
||||||
const DAT_RIGHT_DELAY2_TIME_MS : f32 = 3163.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,
|
266.0 / DAT_SAMPLES_PER_MS,
|
||||||
2974.0 / DAT_SAMPLES_PER_MS,
|
2974.0 / DAT_SAMPLES_PER_MS,
|
||||||
1913.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,
|
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,
|
353.0 / DAT_SAMPLES_PER_MS,
|
||||||
3627.0 / DAT_SAMPLES_PER_MS,
|
3627.0 / DAT_SAMPLES_PER_MS,
|
||||||
1228.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,
|
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_DIFFUSION1 : f64 = 0.75;
|
||||||
const DAT_INPUT_DIFFUSION2 : f32 = 0.625;
|
const DAT_INPUT_DIFFUSION2 : f64 = 0.625;
|
||||||
const DAT_PLATE_DIFFUSION1 : f32 = 0.7;
|
const DAT_PLATE_DIFFUSION1 : f64 = 0.7;
|
||||||
const DAT_PLATE_DIFFUSION2 : f32 = 0.5;
|
const DAT_PLATE_DIFFUSION2 : f64 = 0.5;
|
||||||
|
|
||||||
const DAT_LFO_EXCURSION_MS : f32 = 16.0 / DAT_SAMPLES_PER_MS;
|
const DAT_LFO_EXCURSION_MS : f64 = 16.0 / DAT_SAMPLES_PER_MS;
|
||||||
const DAT_LFO_EXCURSION_MOD_MAX : f32 = 16.0;
|
const DAT_LFO_EXCURSION_MOD_MAX : f64 = 16.0;
|
||||||
|
|
||||||
use crate::dsp::helpers::{
|
use crate::dsp::helpers::{
|
||||||
AllPass,
|
AllPass,
|
||||||
|
@ -80,28 +80,28 @@ use crate::dsp::helpers::{
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct DattorroReverb {
|
pub struct DattorroReverb {
|
||||||
last_scale: f32,
|
last_scale: f64,
|
||||||
|
|
||||||
inp_dc_block: [DCBlockFilter; 2],
|
inp_dc_block: [DCBlockFilter<f64>; 2],
|
||||||
out_dc_block: [DCBlockFilter; 2],
|
out_dc_block: [DCBlockFilter<f64>; 2],
|
||||||
|
|
||||||
lfos: [TriSawLFO; 4],
|
lfos: [TriSawLFO<f64>; 4],
|
||||||
|
|
||||||
input_hpf: OnePoleHPF,
|
input_hpf: OnePoleHPF<f64>,
|
||||||
input_lpf: OnePoleLPF,
|
input_lpf: OnePoleLPF<f64>,
|
||||||
|
|
||||||
pre_delay: DelayBuffer,
|
pre_delay: DelayBuffer<f64>,
|
||||||
input_apfs: [(AllPass, f32, f32); 4],
|
input_apfs: [(AllPass<f64>, f64, f64); 4],
|
||||||
|
|
||||||
apf1: [(AllPass, f32, f32); 2],
|
apf1: [(AllPass<f64>, f64, f64); 2],
|
||||||
hpf: [OnePoleHPF; 2],
|
hpf: [OnePoleHPF<f64>; 2],
|
||||||
lpf: [OnePoleLPF; 2],
|
lpf: [OnePoleLPF<f64>; 2],
|
||||||
apf2: [(AllPass, f32, f32); 2],
|
apf2: [(AllPass<f64>, f64, f64); 2],
|
||||||
delay1: [(DelayBuffer, f32); 2],
|
delay1: [(DelayBuffer<f64>, f64); 2],
|
||||||
delay2: [(DelayBuffer, f32); 2],
|
delay2: [(DelayBuffer<f64>, f64); 2],
|
||||||
|
|
||||||
left_sum: f32,
|
left_sum: f64,
|
||||||
right_sum: f32,
|
right_sum: f64,
|
||||||
|
|
||||||
dbg_count: usize,
|
dbg_count: usize,
|
||||||
}
|
}
|
||||||
|
@ -109,30 +109,30 @@ pub struct DattorroReverb {
|
||||||
pub trait DattorroReverbParams {
|
pub trait DattorroReverbParams {
|
||||||
/// Time for the pre-delay of the reverb. Any sensible `ms` that fits
|
/// Time for the pre-delay of the reverb. Any sensible `ms` that fits
|
||||||
/// into a delay buffer of 5 seconds.
|
/// 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.
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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
|
/// 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.
|
/// The mix between output from the pre-delay and the input diffusion.
|
||||||
/// range: 0.0 to 1.0. Default should be 1.0
|
/// 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
|
/// 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
|
/// Internal tank decay time, range: 0.0 to 1.0
|
||||||
fn decay(&self) -> f32;
|
fn decay(&self) -> f64;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DattorroReverb {
|
impl DattorroReverb {
|
||||||
|
@ -236,8 +236,8 @@ impl DattorroReverb {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_time_scale(&mut self, scale: f32) {
|
pub fn set_time_scale(&mut self, scale: f64) {
|
||||||
if (self.last_scale - scale).abs() > std::f32::EPSILON {
|
if (self.last_scale - scale).abs() > std::f64::EPSILON {
|
||||||
let scale = scale.max(0.0001);
|
let scale = scale.max(0.0001);
|
||||||
self.last_scale = scale;
|
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[0].set_sample_rate(srate);
|
||||||
self.inp_dc_block[1].set_sample_rate(srate);
|
self.inp_dc_block[1].set_sample_rate(srate);
|
||||||
self.out_dc_block[0].set_sample_rate(srate);
|
self.out_dc_block[0].set_sample_rate(srate);
|
||||||
|
@ -292,29 +292,29 @@ impl DattorroReverb {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn calc_apf_delay_times(&mut self, params: &mut dyn DattorroReverbParams)
|
fn calc_apf_delay_times(&mut self, params: &mut dyn DattorroReverbParams)
|
||||||
-> (f32, f32, f32, f32)
|
-> (f64, f64, f64, f64)
|
||||||
{
|
{
|
||||||
let left_apf1_delay_ms =
|
let left_apf1_delay_ms =
|
||||||
self.apf1[0].1
|
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_MS
|
||||||
* DAT_LFO_EXCURSION_MOD_MAX
|
* DAT_LFO_EXCURSION_MOD_MAX
|
||||||
* params.mod_depth());
|
* params.mod_depth());
|
||||||
let right_apf1_delay_ms =
|
let right_apf1_delay_ms =
|
||||||
self.apf1[1].1
|
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_MS
|
||||||
* DAT_LFO_EXCURSION_MOD_MAX
|
* DAT_LFO_EXCURSION_MOD_MAX
|
||||||
* params.mod_depth());
|
* params.mod_depth());
|
||||||
let left_apf2_delay_ms =
|
let left_apf2_delay_ms =
|
||||||
self.apf2[0].1
|
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_MS
|
||||||
* DAT_LFO_EXCURSION_MOD_MAX
|
* DAT_LFO_EXCURSION_MOD_MAX
|
||||||
* params.mod_depth());
|
* params.mod_depth());
|
||||||
let right_apf2_delay_ms =
|
let right_apf2_delay_ms =
|
||||||
self.apf2[1].1
|
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_MS
|
||||||
* DAT_LFO_EXCURSION_MOD_MAX
|
* DAT_LFO_EXCURSION_MOD_MAX
|
||||||
* params.mod_depth());
|
* params.mod_depth());
|
||||||
|
@ -326,8 +326,8 @@ impl DattorroReverb {
|
||||||
pub fn process(
|
pub fn process(
|
||||||
&mut self,
|
&mut self,
|
||||||
params: &mut dyn DattorroReverbParams,
|
params: &mut dyn DattorroReverbParams,
|
||||||
input_l: f32, input_r: f32
|
input_l: f64, input_r: f64
|
||||||
) -> (f32, f32)
|
) -> (f64, f64)
|
||||||
{
|
{
|
||||||
// Some parameter setup...
|
// Some parameter setup...
|
||||||
let timescale = 0.0025 + (4.0 - 0.0025) * params.time_scale();
|
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);
|
let out_hpf = self.input_hpf.process(out_lpf);
|
||||||
|
|
||||||
// HPF => Pre-Delay
|
// HPF => Pre-Delay
|
||||||
let out_pre_delay =
|
let out_pre_delay = out_hpf;
|
||||||
self.pre_delay.cubic_interpolate_at(params.pre_delay_time_ms());
|
// self.pre_delay.cubic_interpolate_at(params.pre_delay_time_ms());
|
||||||
self.pre_delay.feed(out_hpf);
|
// self.pre_delay.feed(out_hpf);
|
||||||
|
|
||||||
// Pre-Delay => 4 All-Pass filters
|
// Pre-Delay => 4 All-Pass filters
|
||||||
let mut diffused = out_pre_delay;
|
let mut diffused = out_pre_delay;
|
||||||
|
@ -384,8 +384,8 @@ impl DattorroReverb {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mix between diffused and pre-delayed intput for further processing
|
// Mix between diffused and pre-delayed intput for further processing
|
||||||
let tank_feed =
|
let tank_feed = out_pre_delay;
|
||||||
crossfade(out_pre_delay, diffused, params.input_diffusion_mix());
|
// crossfade(out_pre_delay, diffused, params.input_diffusion_mix());
|
||||||
|
|
||||||
// First tap for the output
|
// First tap for the output
|
||||||
self.left_sum += tank_feed;
|
self.left_sum += tank_feed;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// See README.md and COPYING for details.
|
// See README.md and COPYING for details.
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
use num_traits::{Float, FloatConst, cast::FromPrimitive};
|
||||||
|
|
||||||
/// Logarithmic table size of the table in [fast_cos] / [fast_sin].
|
/// Logarithmic table size of the table in [fast_cos] / [fast_sin].
|
||||||
static FAST_COS_TAB_LOG2_SIZE : usize = 9;
|
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
|
/// Default size of the delay buffer: 5 seconds at 8 times 48kHz
|
||||||
const DEFAULT_DELAY_BUFFER_SAMPLES : usize = 8 * 48000 * 5;
|
const DEFAULT_DELAY_BUFFER_SAMPLES : usize = 8 * 48000 * 5;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
macro_rules! fc {
|
||||||
pub struct DelayBuffer {
|
($F: ident, $e: expr) => { F::from_f64($e).unwrap() }
|
||||||
data: Vec<f32>,
|
|
||||||
wr: usize,
|
|
||||||
srate: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DelayBuffer {
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct DelayBuffer<F: Float> {
|
||||||
|
data: Vec<F>,
|
||||||
|
wr: usize,
|
||||||
|
srate: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F: Float + FromPrimitive> DelayBuffer<F> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: vec![0.0; DEFAULT_DELAY_BUFFER_SAMPLES],
|
data: vec![fc!(F,0.0); DEFAULT_DELAY_BUFFER_SAMPLES],
|
||||||
wr: 0,
|
wr: 0,
|
||||||
srate: 44100.0,
|
srate: fc!(F, 44100.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_with_size(size: usize) -> Self {
|
pub fn new_with_size(size: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
data: vec![0.0; size],
|
data: vec![fc!(F, 0.0); size],
|
||||||
wr: 0,
|
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;
|
self.srate = srate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -735,7 +740,7 @@ impl DelayBuffer {
|
||||||
/// Please note: For sample accurate feedback you need to retrieve the
|
/// Please note: For sample accurate feedback you need to retrieve the
|
||||||
/// output of the delay line before feeding in a new signal.
|
/// output of the delay line before feeding in a new signal.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn feed(&mut self, input: f32) {
|
pub fn feed(&mut self, input: F) {
|
||||||
self.data[self.wr] = input;
|
self.data[self.wr] = input;
|
||||||
self.wr = (self.wr + 1) % self.data.len();
|
self.wr = (self.wr + 1) % self.data.len();
|
||||||
}
|
}
|
||||||
|
@ -743,7 +748,7 @@ impl DelayBuffer {
|
||||||
/// Combines [DelayBuffer::cubic_interpolate_at] and [DelayBuffer::feed]
|
/// Combines [DelayBuffer::cubic_interpolate_at] and [DelayBuffer::feed]
|
||||||
/// into one convenient function.
|
/// into one convenient function.
|
||||||
#[inline]
|
#[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);
|
let res = self.cubic_interpolate_at(delay_time_ms);
|
||||||
self.feed(input);
|
self.feed(input);
|
||||||
res
|
res
|
||||||
|
@ -751,26 +756,26 @@ impl DelayBuffer {
|
||||||
|
|
||||||
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
|
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
|
||||||
#[inline]
|
#[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)
|
self.cubic_interpolate_at(delay_time_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
|
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
|
||||||
#[inline]
|
#[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)
|
self.nearest_at(delay_time_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
|
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
|
||||||
#[inline]
|
#[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)
|
self.linear_interpolate_at(delay_time_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fetch a sample from the delay buffer at the given time.
|
/// Fetch a sample from the delay buffer at the given time.
|
||||||
///
|
///
|
||||||
/// * `delay_time_ms` - Delay time in milliseconds.
|
/// * `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 data = &self.data[..];
|
||||||
let len = data.len();
|
let len = data.len();
|
||||||
let s_offs = (delay_time_ms * self.srate) / 1000.0;
|
let s_offs = (delay_time_ms * self.srate) / 1000.0;
|
||||||
|
@ -781,7 +786,7 @@ impl DelayBuffer {
|
||||||
let x0 = data[i % len];
|
let x0 = data[i % len];
|
||||||
let x1 = data[(i + 1) % len];
|
let x1 = data[(i + 1) % len];
|
||||||
|
|
||||||
let fract = fract as f32;
|
let fract = fract as F;
|
||||||
x0 * (1.0 - fract) + x1 * fract
|
x0 * (1.0 - fract) + x1 * fract
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,7 +794,7 @@ impl DelayBuffer {
|
||||||
///
|
///
|
||||||
/// * `delay_time_ms` - Delay time in milliseconds.
|
/// * `delay_time_ms` - Delay time in milliseconds.
|
||||||
#[inline]
|
#[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 data = &self.data[..];
|
||||||
let len = data.len();
|
let len = data.len();
|
||||||
let s_offs = (delay_time_ms * self.srate) / 1000.0;
|
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 a = w + v + (x2 - x0) * 0.5;
|
||||||
let b_neg = w + a;
|
let b_neg = w + a;
|
||||||
|
|
||||||
let fract = fract as f32;
|
let fract = fract as F;
|
||||||
(((a * fract) - b_neg) * fract + c) * fract + x0
|
(((a * fract) - b_neg) * fract + c) * fract + x0
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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 len = self.data.len();
|
||||||
let offs = ((delay_time_ms * self.srate) / 1000.0).floor() as usize % len;
|
let offs = ((delay_time_ms * self.srate) / 1000.0).floor() as usize % len;
|
||||||
let idx = ((self.wr + len) - offs) % len;
|
let idx = ((self.wr + len) - offs) % len;
|
||||||
|
@ -829,7 +834,7 @@ impl DelayBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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 len = self.data.len();
|
||||||
let idx = ((self.wr + len) - delay_sample_count) % len;
|
let idx = ((self.wr + len) - delay_sample_count) % len;
|
||||||
self.data[idx]
|
self.data[idx]
|
||||||
|
@ -840,18 +845,18 @@ impl DelayBuffer {
|
||||||
const DEFAULT_ALLPASS_COMB_SAMPLES : usize = 8 * 48000;
|
const DEFAULT_ALLPASS_COMB_SAMPLES : usize = 8 * 48000;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
pub struct AllPass {
|
pub struct AllPass<F: Float> {
|
||||||
delay: DelayBuffer,
|
delay: DelayBuffer<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AllPass {
|
impl<F: Float> AllPass<F> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
delay: DelayBuffer::new_with_size(DEFAULT_ALLPASS_COMB_SAMPLES),
|
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);
|
self.delay.set_sample_rate(srate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,13 +865,13 @@ impl AllPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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)
|
self.delay.tap_n(time_ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn next(&mut self, time_ms: f32, g: f32, v: f32) -> f32 {
|
pub fn next(&mut self, time_ms: F, g: F, v: F) -> F {
|
||||||
let s = self.delay.linear_interpolate_at(time_ms);
|
let s = self.delay.nearest_at(time_ms);
|
||||||
let input = v + -g * s;
|
let input = v + -g * s;
|
||||||
self.delay.feed(input);
|
self.delay.feed(input);
|
||||||
input * g + s
|
input * g + s
|
||||||
|
@ -875,7 +880,7 @@ impl AllPass {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Comb {
|
pub struct Comb {
|
||||||
delay: DelayBuffer,
|
delay: DelayBuffer<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Comb {
|
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)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
pub struct OnePoleLPF {
|
pub struct OnePoleLPF<F: Float> {
|
||||||
israte: f32,
|
israte: F,
|
||||||
a: f32,
|
a: F,
|
||||||
b: f32,
|
b: F,
|
||||||
freq: f32,
|
freq: F,
|
||||||
z: f32,
|
z: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OnePoleLPF {
|
impl<F: Float + FloatConst> OnePoleLPF<F> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
israte: 1.0 / 44100.0,
|
israte: 1.0 / 44100.0,
|
||||||
|
@ -976,17 +981,17 @@ impl OnePoleLPF {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn recalc(&mut self) {
|
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;
|
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.israte = 1.0 / srate;
|
||||||
self.recalc();
|
self.recalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_freq(&mut self, freq: f32) {
|
pub fn set_freq(&mut self, freq: F) {
|
||||||
if freq != self.freq {
|
if freq != self.freq {
|
||||||
self.freq = freq;
|
self.freq = freq;
|
||||||
self.recalc();
|
self.recalc();
|
||||||
|
@ -994,7 +999,7 @@ impl OnePoleLPF {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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 = self.a * input + self.z * self.b;
|
||||||
self.z
|
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)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
pub struct OnePoleHPF {
|
pub struct OnePoleHPF<F: Float> {
|
||||||
israte: f32,
|
israte: F,
|
||||||
a: f32,
|
a: F,
|
||||||
b: f32,
|
b: F,
|
||||||
freq: f32,
|
freq: F,
|
||||||
z: f32,
|
z: F,
|
||||||
y: f32,
|
y: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OnePoleHPF {
|
impl<F: Float + FloatConst> OnePoleHPF<F> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
israte: 1.0 / 44100.0,
|
israte: 1.0 / 44100.0,
|
||||||
|
@ -1068,18 +1073,18 @@ impl OnePoleHPF {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn recalc(&mut self) {
|
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;
|
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.israte = 1.0 / srate;
|
||||||
self.recalc();
|
self.recalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_freq(&mut self, freq: f32) {
|
pub fn set_freq(&mut self, freq: F) {
|
||||||
if freq != self.freq {
|
if freq != self.freq {
|
||||||
self.freq = freq;
|
self.freq = freq;
|
||||||
self.recalc();
|
self.recalc();
|
||||||
|
@ -1087,7 +1092,7 @@ impl OnePoleHPF {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn process(&mut self, input: f32) -> f32 {
|
pub fn process(&mut self, input: F) -> F {
|
||||||
let v =
|
let v =
|
||||||
self.a * input
|
self.a * input
|
||||||
- self.a * self.z
|
- self.a * self.z
|
||||||
|
@ -1396,13 +1401,13 @@ pub fn process_stilson_moog(
|
||||||
// Copyright (C) 2020 TheWaveWarden
|
// Copyright (C) 2020 TheWaveWarden
|
||||||
// under GPLv3 or any later
|
// under GPLv3 or any later
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct DCBlockFilter {
|
pub struct DCBlockFilter<F: Float> {
|
||||||
xm1: f64,
|
xm1: F,
|
||||||
ym1: f64,
|
ym1: F,
|
||||||
r: f64,
|
r: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DCBlockFilter {
|
impl<F: Float> DCBlockFilter<F> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
xm1: 0.0,
|
xm1: 0.0,
|
||||||
|
@ -1416,7 +1421,7 @@ impl DCBlockFilter {
|
||||||
self.ym1 = 0.0;
|
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;
|
self.r = 0.995;
|
||||||
if srate > 90000.0 {
|
if srate > 90000.0 {
|
||||||
self.r = 0.9965;
|
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;
|
let y = input as f64 - self.xm1 + self.r * self.ym1;
|
||||||
self.xm1 = input as f64;
|
self.xm1 = input as f64;
|
||||||
self.ym1 = y;
|
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
|
/// An LFO with a variable reverse point, which can go from reverse Saw, to Tri
|
||||||
/// and to Saw, depending on the reverse point.
|
/// and to Saw, depending on the reverse point.
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct TriSawLFO {
|
pub struct TriSawLFO<F: Float> {
|
||||||
/// The (inverse) sample rate. Eg. 1.0 / 44100.0.
|
/// The (inverse) sample rate. Eg. 1.0 / 44100.0.
|
||||||
israte: f64,
|
israte: F,
|
||||||
/// The current oscillator phase.
|
/// The current oscillator phase.
|
||||||
phase: f64,
|
phase: F,
|
||||||
/// The point from where the falling edge will be used.
|
/// The point from where the falling edge will be used.
|
||||||
rev: f64,
|
rev: F,
|
||||||
/// Whether the LFO is currently rising
|
/// Whether the LFO is currently rising
|
||||||
rising: bool,
|
rising: bool,
|
||||||
/// The frequency.
|
/// The frequency.
|
||||||
freq: f64,
|
freq: F,
|
||||||
/// Precomputed rise/fall rate of the LFO.
|
/// Precomputed rise/fall rate of the LFO.
|
||||||
rise_r: f64,
|
rise_r: F,
|
||||||
fall_r: f64,
|
fall_r: F,
|
||||||
/// Initial phase offset.
|
/// Initial phase offset.
|
||||||
init_phase: f64,
|
init_phase: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TriSawLFO {
|
impl<F: Float> TriSawLFO<F> {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
israte: 1.0 / 44100.0,
|
israte: 1.0 / 44100.0,
|
||||||
|
@ -1912,7 +1917,7 @@ impl TriSawLFO {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_phase_offs(&mut self, phase: f64) {
|
pub fn set_phase_offs(&mut self, phase: F) {
|
||||||
self.init_phase = phase;
|
self.init_phase = phase;
|
||||||
self.phase = phase;
|
self.phase = phase;
|
||||||
}
|
}
|
||||||
|
@ -1924,8 +1929,8 @@ impl TriSawLFO {
|
||||||
self.fall_r = -1.0 / (1.0 - self.rev);
|
self.fall_r = -1.0 / (1.0 - self.rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_sample_rate(&mut self, srate: f32) {
|
pub fn set_sample_rate(&mut self, srate: F) {
|
||||||
self.israte = 1.0 / (srate as f64);
|
self.israte = 1.0 / (srate as F);
|
||||||
self.recalc();
|
self.recalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1936,14 +1941,14 @@ impl TriSawLFO {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set(&mut self, freq: f32, rev: f32) {
|
pub fn set(&mut self, freq: F, rev: F) {
|
||||||
self.freq = freq as f64;
|
self.freq = freq as F;
|
||||||
self.rev = rev as f64;
|
self.rev = rev as F;
|
||||||
self.recalc();
|
self.recalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn next_unipolar(&mut self) -> f64 {
|
pub fn next_unipolar(&mut self) -> F {
|
||||||
if self.phase >= 1.0 {
|
if self.phase >= 1.0 {
|
||||||
self.phase -= 1.0;
|
self.phase -= 1.0;
|
||||||
self.rising = true;
|
self.rising = true;
|
||||||
|
@ -1966,7 +1971,7 @@ impl TriSawLFO {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn next_bipolar(&mut self) -> f64 {
|
pub fn next_bipolar(&mut self) -> F {
|
||||||
(self.next_unipolar() * 2.0) - 1.0
|
(self.next_unipolar() * 2.0) - 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::dsp::helpers::AllPass;
|
||||||
/// A simple amplifier
|
/// A simple amplifier
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct AllP {
|
pub struct AllP {
|
||||||
allpass: Box<AllPass>,
|
allpass: Box<AllPass<f64>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AllP {
|
impl AllP {
|
||||||
|
@ -72,7 +72,7 @@ impl DspNode for AllP {
|
||||||
fn outputs() -> usize { 1 }
|
fn outputs() -> usize { 1 }
|
||||||
|
|
||||||
fn set_sample_rate(&mut self, srate: f32) {
|
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) {
|
fn reset(&mut self) {
|
||||||
|
@ -100,9 +100,9 @@ impl DspNode for AllP {
|
||||||
|
|
||||||
out.write(frame,
|
out.write(frame,
|
||||||
ap.next(
|
ap.next(
|
||||||
denorm::AllP::time(time, frame),
|
denorm::AllP::time(time, frame) as f64,
|
||||||
denorm::AllP::g(g, frame),
|
denorm::AllP::g(g, frame) as f64,
|
||||||
v));
|
v as f64) as f32);
|
||||||
}
|
}
|
||||||
|
|
||||||
let last_frame = ctx.nframes() - 1;
|
let last_frame = ctx.nframes() - 1;
|
||||||
|
|
|
@ -20,7 +20,7 @@ macro_rules! fa_delay_mode { ($formatter: expr, $v: expr, $denorm_v: expr) => {
|
||||||
/// A simple amplifier
|
/// A simple amplifier
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Delay {
|
pub struct Delay {
|
||||||
buffer: Box<DelayBuffer>,
|
buffer: Box<DelayBuffer<f32>>,
|
||||||
clock: TriggerSampleClock,
|
clock: TriggerSampleClock,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,41 +36,41 @@ impl DatParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DattorroReverbParams for DatParams {
|
impl DattorroReverbParams for DatParams {
|
||||||
fn pre_delay_time_ms(&self) -> f32 {
|
fn pre_delay_time_ms(&self) -> f64 {
|
||||||
denorm::PVerb::predly(&self.predly, self.frame)
|
denorm::PVerb::predly(&self.predly, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn time_scale(&self) -> f32 {
|
fn time_scale(&self) -> f64 {
|
||||||
denorm::PVerb::size(&self.size, self.frame)
|
denorm::PVerb::size(&self.size, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn decay(&self) -> f32 {
|
fn decay(&self) -> f64 {
|
||||||
denorm::PVerb::dcy(&self.dcy, self.frame)
|
denorm::PVerb::dcy(&self.dcy, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn input_low_cutoff_hz(&self) -> f32 {
|
fn input_low_cutoff_hz(&self) -> f64 {
|
||||||
denorm::PVerb::ilpf(&self.ilpf, self.frame)
|
denorm::PVerb::ilpf(&self.ilpf, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn input_high_cutoff_hz(&self) -> f32 {
|
fn input_high_cutoff_hz(&self) -> f64 {
|
||||||
denorm::PVerb::ihpf(&self.ihpf, self.frame)
|
denorm::PVerb::ihpf(&self.ihpf, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn diffusion(&self) -> f32 {
|
fn diffusion(&self) -> f64 {
|
||||||
denorm::PVerb::idif(&self.idif, self.frame)
|
denorm::PVerb::idif(&self.idif, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn input_diffusion_mix(&self) -> f32 {
|
fn input_diffusion_mix(&self) -> f64 {
|
||||||
denorm::PVerb::dmix(&self.dmix, self.frame)
|
denorm::PVerb::dmix(&self.dmix, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn mod_speed(&self) -> f32 {
|
fn mod_speed(&self) -> f64 {
|
||||||
denorm::PVerb::mspeed(&self.mspeed, self.frame)
|
denorm::PVerb::mspeed(&self.mspeed, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn mod_depth(&self) -> f32 {
|
fn mod_depth(&self) -> f64 {
|
||||||
denorm::PVerb::mdepth(&self.mdepth, self.frame)
|
denorm::PVerb::mdepth(&self.mdepth, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn mod_shape(&self) -> f32 {
|
fn mod_shape(&self) -> f64 {
|
||||||
denorm::PVerb::mshp(&self.mshp, self.frame)
|
denorm::PVerb::mshp(&self.mshp, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn reverb_low_cutoff_hz(&self) -> f32 {
|
fn reverb_low_cutoff_hz(&self) -> f64 {
|
||||||
denorm::PVerb::rlpf(&self.rlpf, self.frame)
|
denorm::PVerb::rlpf(&self.rlpf, self.frame) as f64
|
||||||
}
|
}
|
||||||
fn reverb_high_cutoff_hz(&self) -> f32 {
|
fn reverb_high_cutoff_hz(&self) -> f64 {
|
||||||
denorm::PVerb::rhpf(&self.rhpf, self.frame)
|
denorm::PVerb::rhpf(&self.rhpf, self.frame) as f64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ impl DspNode for PVerb {
|
||||||
fn outputs() -> usize { 1 }
|
fn outputs() -> usize { 1 }
|
||||||
|
|
||||||
fn set_sample_rate(&mut self, srate: f32) {
|
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) {
|
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));
|
let (i_l, i_r) = (in_l.read(frame), in_r.read(frame));
|
||||||
|
|
||||||
params.set_frame(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_l.write(
|
||||||
out_r.write(frame, crossfade(i_r, r, denorm::PVerb::mix(mix, frame)));
|
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(
|
ctx_vals[0].set(
|
||||||
|
|
|
@ -11,7 +11,7 @@ use super::helpers::{TriSawLFO, Trigger};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TsLfo {
|
pub struct TsLfo {
|
||||||
lfo: Box<TriSawLFO>,
|
lfo: Box<TriSawLFO<f64>>,
|
||||||
trig: Trigger,
|
trig: Trigger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ impl DspNode for TsLfo {
|
||||||
fn outputs() -> usize { 1 }
|
fn outputs() -> usize { 1 }
|
||||||
|
|
||||||
fn set_sample_rate(&mut self, srate: f32) {
|
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) {
|
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);
|
let time_ms = denorm::TsLfo::time(time, frame).clamp(0.1, 300000.0);
|
||||||
|
|
||||||
lfo.set(
|
lfo.set(
|
||||||
1000.0 / time_ms,
|
(1000.0 / time_ms) as f64,
|
||||||
denorm::TsLfo::rev(rev, frame));
|
denorm::TsLfo::rev(rev, frame) as f64);
|
||||||
|
|
||||||
out.write(frame, lfo.next_unipolar() as f32);
|
out.write(frame, lfo.next_unipolar() as f32);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue