HexoDSP/src/dsp/dattorro.rs

208 lines
6.4 KiB
Rust
Raw Normal View History

2021-08-06 03:49:03 +00:00
// Copyright (c) 2021 Weird Constructor <weirdconstructor@gmail.com>
// This file is a part of HexoDSP. Released under GPL-3.0-or-later.
// See README.md and COPYING for details.
// This file contains a reverb implementation that is based
// on Jon Dattorro's 1997 reverb algorithm. It's also largely
// based on the C++ implementation from ValleyAudio / ValleyRackFree
//
// ValleyRackFree Copyright (C) 2020, Valley Audio Soft, Dale Johnson
// Adapted under the GPL-3.0-or-later License.
2021-08-06 04:38:08 +00:00
//
// See also: https://github.com/ValleyAudio/ValleyRackFree/blob/v1.0/src/Plateau/Dattorro.cpp
// and: https://github.com/ValleyAudio/ValleyRackFree/blob/v1.0/src/Plateau/Dattorro.hpp
//
// And: https://ccrma.stanford.edu/~dattorro/music.html
// And: https://ccrma.stanford.edu/~dattorro/EffectDesignPart1.pdf
const DAT_SAMPLE_RATE : f32 = 29761.0;
const DAT_SAMPLES_PER_MS : f32 = DAT_SAMPLE_RATE / 1000.0;
const DAT_INPUT_APF_TIMES_MS : [f32; 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_RIGHT_APF1_TIME_MS : f32 = 908.0 / DAT_SAMPLES_PER_MS;
const DAT_RIGHT_APF2_TIME_MS : f32 = 2656.0 / DAT_SAMPLES_PER_MS;
2021-08-06 17:25:24 +00:00
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_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_TAPS_TIME_MS : [f32; 7] = [
266.0 / DAT_SAMPLES_PER_MS,
2974.0 / DAT_SAMPLES_PER_MS,
1913.0 / DAT_SAMPLES_PER_MS,
1996.0 / DAT_SAMPLES_PER_MS,
1990.0 / DAT_SAMPLES_PER_MS,
187.0 / DAT_SAMPLES_PER_MS,
1066.0 / DAT_SAMPLES_PER_MS,
];
const DAT_LFO_FREQS_HZ : [f32; 4] = [ 0.1, 0.15, 0.12, 0.18 ];
2021-08-06 04:38:08 +00:00
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;
2021-08-06 03:49:03 +00:00
2021-08-06 17:25:24 +00:00
const DAT_LFO_EXCURSION_MS : f32 = 16.0 / DAT_SAMPLES_PER_MS;
use crate::dsp::helpers::{
AllPass,
TriSawLFO,
OnePoleLPF,
OnePoleHPF,
DelayBuffer,
DCBlockFilter
};
2021-08-06 03:49:03 +00:00
pub struct DattorroReverb {
2021-08-06 04:38:08 +00:00
last_scale: f32,
inp_dc_block: [DCBlockFilter; 2],
out_dc_block: [DCBlockFilter; 2],
lfos: [TriSawLFO; 4],
input_hpf: OnePoleHPF,
input_lpf: OnePoleLPF,
pre_delay: DelayBuffer,
2021-08-06 17:25:24 +00:00
input_apfs: [(AllPass, f32, f32); 4],
2021-08-06 17:25:24 +00:00
apf1: [(AllPass, f32, f32); 2],
hpf: [OnePoleHPF; 2],
lpf: [OnePoleLPF; 2],
2021-08-06 17:25:24 +00:00
apf2: [(AllPass, f32, f32); 2],
delay1: [(DelayBuffer, f32); 2],
delay2: [(DelayBuffer, f32); 2],
2021-08-06 04:38:08 +00:00
}
pub trait DattorroReverbParams {
/// Time for the pre-delay of the reverb.
fn pre_delay_time_s(&self) -> f32;
2021-08-06 17:25:24 +00:00
fn time_scale(&self) -> f32;
2021-08-06 04:38:08 +00:00
}
impl DattorroReverb {
pub fn new() -> Self {
let mut this = Self {
last_scale: 1.0,
inp_dc_block: [DCBlockFilter::new(); 2],
out_dc_block: [DCBlockFilter::new(); 2],
lfos: [TriSawLFO::new(); 4],
input_hpf: OnePoleHPF::new(),
input_lpf: OnePoleLPF::new(),
pre_delay: DelayBuffer::new(),
2021-08-06 17:25:24 +00:00
input_apfs: Default::default(),
2021-08-06 04:38:08 +00:00
2021-08-06 17:25:24 +00:00
apf1: Default::default(),
2021-08-06 04:38:08 +00:00
hpf: [OnePoleHPF::new(); 2],
lpf: [OnePoleLPF::new(); 2],
2021-08-06 17:25:24 +00:00
apf2: Default::default(),
delay1: Default::default(),
delay2: Default::default(),
2021-08-06 04:38:08 +00:00
};
this.reset();
this
}
pub fn reset(&mut self) {
2021-08-06 17:25:24 +00:00
self.input_lpf.reset();
self.input_hpf.reset();
2021-08-06 04:38:08 +00:00
self.input_lpf.set_freq(22000.0);
self.input_hpf.set_freq(0.0);
2021-08-06 17:25:24 +00:00
self.input_apfs[0] =
(AllPass::new(), DAT_INPUT_APF_TIMES_MS[0], DAT_INPUT_DIFFUSION1);
self.input_apfs[1] =
(AllPass::new(), DAT_INPUT_APF_TIMES_MS[1], DAT_INPUT_DIFFUSION1);
self.input_apfs[2] =
(AllPass::new(), DAT_INPUT_APF_TIMES_MS[2], DAT_INPUT_DIFFUSION2);
self.input_apfs[3] =
(AllPass::new(), DAT_INPUT_APF_TIMES_MS[3], DAT_INPUT_DIFFUSION2);
self.apf1[0] =
(AllPass::new(), DAT_LEFT_APF1_TIME_MS, -DAT_PLATE_DIFFUSION1);
self.apf1[1] =
(AllPass::new(), DAT_RIGHT_APF1_TIME_MS, -DAT_PLATE_DIFFUSION1);
self.apf2[0] =
(AllPass::new(), DAT_LEFT_APF2_TIME_MS, -DAT_PLATE_DIFFUSION2);
self.apf2[1] =
(AllPass::new(), DAT_RIGHT_APF2_TIME_MS, -DAT_PLATE_DIFFUSION2);
self.delay1[0] = (DelayBuffer::new(), DAT_LEFT_DELAY1_TIME_MS);
self.delay1[1] = (DelayBuffer::new(), DAT_RIGHT_DELAY1_TIME_MS);
self.delay2[0] = (DelayBuffer::new(), DAT_LEFT_DELAY2_TIME_MS);
self.delay2[1] = (DelayBuffer::new(), DAT_RIGHT_DELAY2_TIME_MS);
self.lpf[0].reset();
self.lpf[1].reset();
self.lpf[0].set_freq(10000.0);
self.lpf[1].set_freq(10000.0);
self.hpf[0].reset();
self.hpf[1].reset();
self.hpf[0].set_freq(0.0);
self.hpf[1].set_freq(0.0);
self.lfos[0].set(DAT_LFO_FREQS_HZ[0], 0.5);
self.lfos[0].set_phase_offs(0.0);
self.lfos[0].reset();
self.lfos[1].set(DAT_LFO_FREQS_HZ[1], 0.5);
self.lfos[1].set_phase_offs(0.25);
self.lfos[1].reset();
self.lfos[2].set(DAT_LFO_FREQS_HZ[2], 0.5);
self.lfos[2].set_phase_offs(0.5);
self.lfos[2].reset();
self.lfos[3].set(DAT_LFO_FREQS_HZ[3], 0.5);
self.lfos[3].set_phase_offs(0.75);
self.lfos[3].reset();
2021-08-06 04:38:08 +00:00
self.set_time_scale(1.0);
}
#[inline]
pub fn set_time_scale(&mut self, scale: f32) {
2021-08-06 17:25:24 +00:00
if (self.last_scale - scale).abs() > std::f32::EPSILON {
2021-08-06 04:38:08 +00:00
let scale = scale.max(0.0001);
self.last_scale = scale;
self.apf1[0].1 = DAT_LEFT_APF1_TIME_MS * scale;
self.apf1[1].1 = DAT_RIGHT_APF1_TIME_MS * scale;
self.apf2[0].1 = DAT_LEFT_APF2_TIME_MS * scale;
self.apf2[1].1 = DAT_RIGHT_APF2_TIME_MS * scale;
}
}
pub fn set_sample_rate(&mut self, srate: f32) {
}
2021-08-06 17:25:24 +00:00
pub fn process(
&mut self,
params: &mut dyn DattorroReverbParams,
input_l: f32, input_r: f32
) -> (f32, f32)
{
self.set_time_scale(params.time_scale());
(0.0, 0.0)
2021-08-06 04:38:08 +00:00
}
}