Changed slew logix to a real slew rate limiter
This commit is contained in:
parent
99eead8402
commit
993c690bc4
3 changed files with 76 additions and 23 deletions
|
@ -705,8 +705,55 @@ impl TriggerSampleClock {
|
|||
}
|
||||
}
|
||||
|
||||
/// A slew rate limiter, with a configurable time per 1.0 increase.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct SlewValue<F: Flt> {
|
||||
current: F,
|
||||
slew_per_ms: F,
|
||||
}
|
||||
|
||||
impl<F: Flt> SlewValue<F> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
current: f(0.0),
|
||||
slew_per_ms: f(1000.0 / 44100.0),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.current = f(0.0);
|
||||
}
|
||||
|
||||
pub fn set_sample_rate(&mut self, srate: F) {
|
||||
self.slew_per_ms = f::<F>(1000.0) / srate;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn value(&self) -> F { self.current }
|
||||
|
||||
/// * `slew_ms_per_1` - The time (in milliseconds) it should take
|
||||
/// to get to 1.0 from 0.0.
|
||||
#[inline]
|
||||
pub fn next(&mut self, target: F, slew_ms_per_1: F) -> F {
|
||||
// at 0.11ms, there are barely enough samples for proper slew.
|
||||
if slew_ms_per_1 < f(0.11) {
|
||||
self.current = target;
|
||||
|
||||
} else {
|
||||
let max_delta = self.slew_per_ms / slew_ms_per_1;
|
||||
self.current =
|
||||
target
|
||||
.min(self.current + max_delta)
|
||||
.max(self.current - max_delta);
|
||||
}
|
||||
|
||||
self.current
|
||||
}
|
||||
}
|
||||
|
||||
/// A ramped value changer, with a configurable time to reach the target value.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct RampValue<F: Flt> {
|
||||
slew_count: u64,
|
||||
current: F,
|
||||
target: F,
|
||||
|
@ -714,7 +761,7 @@ pub struct SlewValue<F: Flt> {
|
|||
sr_ms: F,
|
||||
}
|
||||
|
||||
impl<F: Flt> SlewValue<F> {
|
||||
impl<F: Flt> RampValue<F> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
slew_count: 0,
|
||||
|
|
|
@ -610,7 +610,7 @@ define_exp!{n_env d_env 0.0, 1000.0}
|
|||
define_exp6!{n_lfot d_lfot 0.1,300000.0}
|
||||
define_exp!{n_time d_time 0.5, 5000.0}
|
||||
define_exp!{n_ftme d_ftme 0.1, 1000.0}
|
||||
define_exp!{n_ftmz d_ftmz 0.0, 1000.0}
|
||||
define_exp!{n_ftmz d_ftmz 0.0, 5000.0}
|
||||
|
||||
// Special linear gain factor for the Out node, to be able
|
||||
// to reach more exact "1.0".
|
||||
|
@ -760,7 +760,7 @@ macro_rules! node_list {
|
|||
(2 offs n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
(3 min n_id d_id r_id f_def stp_d 0.0, 1.0, 0.0)
|
||||
(4 max n_id d_id r_id f_def stp_d 0.0, 1.0, 1.0)
|
||||
(5 slewt n_ftmz d_ftmz r_fmz f_ms stp_m 0.0, 1.0, 10.0)
|
||||
(5 slew n_ftmz d_ftmz r_fmz f_ms stp_m 0.0, 1.0, 75.0)
|
||||
[0 sig],
|
||||
delay => Delay UIType::Generic UICategory::Signal
|
||||
(0 inp n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||
|
|
|
@ -13,8 +13,9 @@ use crate::dsp::{
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct RndWk {
|
||||
rng: Rng,
|
||||
slew_val: SlewValue<f32>,
|
||||
slew_val: SlewValue<f64>,
|
||||
trig: Trigger,
|
||||
target: f64,
|
||||
}
|
||||
|
||||
impl RndWk {
|
||||
|
@ -28,6 +29,7 @@ impl RndWk {
|
|||
rng,
|
||||
trig: Trigger::new(),
|
||||
slew_val: SlewValue::new(),
|
||||
target: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,16 +54,17 @@ impl RndWk {
|
|||
"RndWk max\nThe maximum of the new target value. If a value is drawn \
|
||||
that is outside of this range, it will be reflected back into it.\
|
||||
\nRange: (0..1)";
|
||||
pub const slewt : &'static str =
|
||||
"RndWk slewt\nThe slew time, the time it takes to reach the \
|
||||
new target value. This can be used to smooth off rough transitions and \
|
||||
clicky noises.\nRange: (0..1)";
|
||||
pub const slew : &'static str =
|
||||
"RndWk slew\nThe slew rate limiting time. Thats the time it takes to \
|
||||
get to 1.0 from 0.0. Useful for smoothing modulation of audio signals. \
|
||||
The higher the time, the smoother/slower the transition to new \
|
||||
target values will be.\nRange: (0..1)";
|
||||
pub const sig : &'static str =
|
||||
"RndWk sig\nOscillator output\nRange: (-1..1)\n";
|
||||
pub const DESC : &'static str =
|
||||
r#"Random Walker
|
||||
|
||||
This modulator generates a random number by walking a pre defined maximum random 'step' width. For smoother transitions a slew time is integrated.
|
||||
This modulator generates a random number by walking a pre defined maximum random 'step' width. For smoother transitions a slew rate limiter is integrated.
|
||||
"#;
|
||||
pub const HELP : &'static str =
|
||||
r#"RndWk - Random Walker
|
||||
|
@ -72,12 +75,12 @@ be folded within the defined 'min'/'max' range. The 'offs' parameter defines a
|
|||
minimal step width each 'trig' has to change the target value.
|
||||
|
||||
For smoother transitions, if you want to modulate an audio signal with this,
|
||||
a slew time ('slewt') is integrated.
|
||||
a slew rate limiter ('slew') is integrated.
|
||||
|
||||
You can disable all randomness by setting 'step' to 0.0.
|
||||
|
||||
Tip: Interesting and smooth results can be achieved if you set 'slewt'
|
||||
to a longer time than the interval in that you trigger 'trig'. It will smooth
|
||||
Tip: Interesting and smooth results can be achieved if you set 'slew'
|
||||
to a (way) longer time than the 'trig' interval. It will smooth
|
||||
off the step widths and the overall motion even more.
|
||||
"#;
|
||||
|
||||
|
@ -87,12 +90,13 @@ impl DspNode for RndWk {
|
|||
fn outputs() -> usize { 1 }
|
||||
|
||||
fn set_sample_rate(&mut self, srate: f32) {
|
||||
self.slew_val.set_sample_rate(srate);
|
||||
self.slew_val.set_sample_rate(srate as f64);
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.slew_val.reset();
|
||||
self.trig.reset();
|
||||
self.target = 0.0;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -109,7 +113,7 @@ impl DspNode for RndWk {
|
|||
let offs = inp::RndWk::offs(inputs);
|
||||
let min = inp::RndWk::min(inputs);
|
||||
let max = inp::RndWk::max(inputs);
|
||||
let slewt = inp::RndWk::slewt(inputs);
|
||||
let slew = inp::RndWk::slew(inputs);
|
||||
let out = out::RndWk::sig(outputs);
|
||||
|
||||
for frame in 0..ctx.nframes() {
|
||||
|
@ -125,17 +129,19 @@ impl DspNode for RndWk {
|
|||
let offs = denorm::RndWk::offs(offs, frame).clamp(-1.0, 1.0);
|
||||
|
||||
let target =
|
||||
self.slew_val.value()
|
||||
self.slew_val.value() as f32
|
||||
+ ((self.rng.next() * 2.0 * step) - step)
|
||||
+ offs;
|
||||
let target = ((target - min) % delta).abs() + min;
|
||||
|
||||
let slew_time_ms = denorm::RndWk::slewt(slewt, frame);
|
||||
|
||||
self.slew_val.set_target(target, slew_time_ms);
|
||||
self.target = (((target - min) % delta).abs() + min) as f64;
|
||||
}
|
||||
|
||||
out.write(frame, self.slew_val.next());
|
||||
let slew_time_ms = denorm::RndWk::slew(slew, frame);
|
||||
|
||||
out.write(
|
||||
frame,
|
||||
self.slew_val.next(
|
||||
self.target,
|
||||
slew_time_ms as f64) as f32);
|
||||
}
|
||||
|
||||
ctx_vals[0].set(out.read(ctx.nframes() - 1));
|
||||
|
|
Loading…
Reference in a new issue