mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-28 12:36:47 -06:00
fix(dsp): chorus and flanger tails follow their feedback (#242)
This commit is contained in:
@@ -316,7 +316,15 @@ impl Plugin for ModFx {
|
||||
}
|
||||
|
||||
fn tail_samples(&self) -> usize {
|
||||
ms_to_samples(200.0, self.sr) as usize
|
||||
// Time for feedback to fall by 60 dB at the longest delay of the sweep, as for the delay
|
||||
// above; never shorter than the 200 ms this used to report.
|
||||
let longest = match self.kind {
|
||||
ModKind::Chorus => self.p.v(2) + self.p.v(1) / 100.0 * 6.0,
|
||||
ModKind::Flanger => self.p.v(2),
|
||||
};
|
||||
let fb = (self.p.v(3).abs() / 100.0).clamp(0.0, 0.99);
|
||||
let repeats = if fb < 1e-3 { 1.0 } else { (-60.0 / (20.0 * fb.log10())).min(500.0) + 1.0 };
|
||||
ms_to_samples((longest * repeats).max(200.0), self.sr) as usize
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -329,6 +329,23 @@ fn delay_repeats_at_time() {
|
||||
assert!((pos as i64 - 4800).abs() <= 2, "echo at {pos}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn modulation_tail_covers_feedback_echoes() {
|
||||
for (id, delay, feedback) in [("chorus", 30.0, 90.0), ("flanger", 10.0, 95.0), ("flanger", 10.0, -95.0)] {
|
||||
let mut p = prepared(id);
|
||||
for (param, v) in [("delay", delay), ("feedback", feedback), ("depth", 0.0), ("mix", 100.0)] {
|
||||
assert!(p.set_param(param, v));
|
||||
}
|
||||
p.reset();
|
||||
let mut x = vec![0.0f32; 48_000 * 5];
|
||||
x[0] = 0.5;
|
||||
let out = run(p.as_mut(), &[x]);
|
||||
let floor = peak(&out[0]) * 1e-3;
|
||||
let last = out[0].iter().rposition(|v| v.abs() > floor).unwrap();
|
||||
assert!(last < p.tail_samples(), "{id} feedback {feedback}: echo at {last}, tail {}", p.tail_samples());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trim_and_invert() {
|
||||
let mut p = prepared("invert");
|
||||
|
||||
Reference in New Issue
Block a user