Fixed a bug in the allpass filter, and the dattorro reverb sounds better and better, still some weird glitchy stuff in the modulation

This commit is contained in:
Weird Constructor 2021-08-07 19:18:54 +02:00
parent e45b8a5ebd
commit c57274bfe4
3 changed files with 66 additions and 30 deletions

View file

@ -419,26 +419,27 @@ impl DattorroReverb {
self.left_sum = right * decay;
let mut left_accum = left_apf_tap;
left_accum += self.delay1[0].0.tap( DAT_LEFT_TAPS_TIME_MS[0]);
left_accum += self.delay1[0].0.tap( DAT_LEFT_TAPS_TIME_MS[1]);
left_accum -= self.apf2[0].0.delay_tap(DAT_LEFT_TAPS_TIME_MS[2]);
left_accum += self.delay2[0].0.tap( DAT_LEFT_TAPS_TIME_MS[3]);
left_accum -= self.delay1[1].0.tap( DAT_LEFT_TAPS_TIME_MS[4]);
left_accum -= self.apf2[1].0.delay_tap(DAT_LEFT_TAPS_TIME_MS[5]);
left_accum -= self.delay2[1].0.tap( DAT_LEFT_TAPS_TIME_MS[6]);
left_accum += self.delay1[0].0.tap_n( DAT_LEFT_TAPS_TIME_MS[0]);
left_accum += self.delay1[0].0.tap_n( DAT_LEFT_TAPS_TIME_MS[1]);
left_accum -= self.apf2[0].0.delay_tap_n(DAT_LEFT_TAPS_TIME_MS[2]);
left_accum += self.delay2[0].0.tap_n( DAT_LEFT_TAPS_TIME_MS[3]);
left_accum -= self.delay1[1].0.tap_n( DAT_LEFT_TAPS_TIME_MS[4]);
left_accum -= self.apf2[1].0.delay_tap_n(DAT_LEFT_TAPS_TIME_MS[5]);
left_accum -= self.delay2[1].0.tap_n( DAT_LEFT_TAPS_TIME_MS[6]);
let mut right_accum = right_apf_tap;
right_accum += self.delay1[1].0.tap( DAT_RIGHT_TAPS_TIME_MS[0]);
right_accum += self.delay1[1].0.tap( DAT_RIGHT_TAPS_TIME_MS[1]);
right_accum -= self.apf2[1].0.delay_tap(DAT_RIGHT_TAPS_TIME_MS[2]);
right_accum += self.delay2[1].0.tap( DAT_RIGHT_TAPS_TIME_MS[3]);
right_accum -= self.delay1[0].0.tap( DAT_RIGHT_TAPS_TIME_MS[4]);
right_accum -= self.apf2[0].0.delay_tap(DAT_RIGHT_TAPS_TIME_MS[5]);
right_accum -= self.delay2[0].0.tap( DAT_RIGHT_TAPS_TIME_MS[6]);
right_accum += self.delay1[1].0.tap_n( DAT_RIGHT_TAPS_TIME_MS[0]);
right_accum += self.delay1[1].0.tap_n( DAT_RIGHT_TAPS_TIME_MS[1]);
right_accum -= self.apf2[1].0.delay_tap_n(DAT_RIGHT_TAPS_TIME_MS[2]);
right_accum += self.delay2[1].0.tap_n( DAT_RIGHT_TAPS_TIME_MS[3]);
right_accum -= self.delay1[0].0.tap_n( DAT_RIGHT_TAPS_TIME_MS[4]);
right_accum -= self.apf2[0].0.delay_tap_n(DAT_RIGHT_TAPS_TIME_MS[5]);
right_accum -= self.delay2[0].0.tap_n( DAT_RIGHT_TAPS_TIME_MS[6]);
let left_out = self.out_dc_block[0].next(left_accum);
let right_out = self.out_dc_block[1].next(right_accum);
// (left_out * 0.5, right_out * 0.5)
(left_out * 0.5, right_out * 0.5)
}
}

View file

@ -751,10 +751,40 @@ impl DelayBuffer {
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
#[inline]
pub fn tap(&self, delay_time_ms: f32) -> f32 {
pub fn tap_c(&self, delay_time_ms: f32) -> f32 {
self.cubic_interpolate_at(delay_time_ms)
}
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
#[inline]
pub fn tap_n(&self, delay_time_ms: f32) -> f32 {
self.nearest_at(delay_time_ms)
}
/// Shorthand for [DelayBuffer::cubic_interpolate_at].
#[inline]
pub fn tap_l(&self, delay_time_ms: f32) -> f32 {
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 {
let data = &self.data[..];
let len = data.len();
let s_offs = (delay_time_ms * self.srate) / 1000.0;
let offs = s_offs.floor() as usize % len;
let fract = s_offs.fract();
let i = (self.wr + len) - offs;
let x0 = data[i % len];
let x1 = data[(i + 1) % len];
let fract = fract as f32;
x0 * (1.0 - fract) + x1 * fract
}
/// Fetch a sample from the delay buffer at the given time.
///
/// * `delay_time_ms` - Delay time in milliseconds.
@ -830,15 +860,16 @@ impl AllPass {
}
#[inline]
pub fn delay_tap(&self, time: f32) -> f32 {
self.delay.cubic_interpolate_at(time)
pub fn delay_tap_n(&self, time: f32) -> f32 {
self.delay.tap_n(time)
}
#[inline]
pub fn next(&mut self, time: f32, g: f32, v: f32) -> f32 {
let s = self.delay.cubic_interpolate_at(time);
self.delay.feed(v + s * g);
s + -1.0 * g * v
let input = v + -g * s;
self.delay.feed(input);
input * g + s
}
}
@ -863,8 +894,13 @@ impl Comb {
}
#[inline]
pub fn delay_tap(&self, time: f32) -> f32 {
self.delay.cubic_interpolate_at(time)
pub fn delay_tap_c(&self, time: f32) -> f32 {
self.delay.tap_c(time)
}
#[inline]
pub fn delay_tap_n(&self, time: f32) -> f32 {
self.delay.tap_n(time)
}
#[inline]
@ -877,8 +913,7 @@ impl Comb {
#[inline]
pub fn next_feedforward(&mut self, time: f32, g: f32, v: f32) -> f32 {
let s = self.delay.cubic_interpolate_at(time);
self.delay.feed(v);
let s = self.delay.next_cubic(time, v);
v + s * g
}
}

View file

@ -40,24 +40,24 @@ fn check_node_allp() {
// now signal on ch1 from the allpass:
// starts with original signal * -0.7
let mut v = vec![-0.7; (2.0 * 44.1_f32).ceil() as usize];
let mut v = vec![0.7; (2.0 * 44.1_f32).ceil() as usize];
// silence for 1ms, which is the internal delay of the allpass
v.append(&mut vec![0.0; (1.0 * 44.1_f32).floor() as usize - 3]);
// allpass feedback of the original signal for 2ms:
// XXX: the smearing before and after the allpass is due to the
// cubic interpolation!
v.append(&mut vec![-0.03150302, 0.25802, 1.0735]);
v.append(&mut vec![1.0; (2.0 * 44.1_f32).ceil() as usize - 3]);
v.append(&mut vec![1.0315, 0.7419, -0.0735]);
v.append(&mut vec![-0.01606654, 0.13159, 0.54748535]);
v.append(&mut vec![0.51; (2.0 * 44.1_f32).ceil() as usize - 3]);
v.append(&mut vec![0.52606, 0.37840945, -0.037485]);
// 1ms allpass silence like before:
v.append(&mut vec![0.0; (1.0 * 44.1_f32).floor() as usize - 6]);
// 2ms the previous 1.0 * 0.7 fed back into the filter,
// including even more smearing due to cubic interpolation:
v.append(&mut vec![0.0006, -0.0120, 0.0106, 0.3444, 0.7801, 0.6962]);
v.append(&mut vec![0.7; (2.0 * 44.1_f32).floor() as usize - 5]);
v.append(&mut vec![0.6993, 0.712, 0.6893, 0.3555, -0.0801, 0.0037]);
v.append(&mut vec![-0.000354, 0.00615, -0.005424, -0.17565, -0.39786, -0.3550714]);
v.append(&mut vec![-0.357; (2.0 * 44.1_f32).floor() as usize - 5]);
v.append(&mut vec![-0.3566457, -0.363158, -0.35157552, -0.18134634, 0.040867306, -0.0019286368]);
//d// println!("res={:?}", res.1);
assert_vec_feq!(res.0, v);