From b7c302e22872afc9462cead672dd2a244e31c51d Mon Sep 17 00:00:00 2001 From: Sami Perttu Date: Thu, 1 Aug 2024 08:22:28 +0300 Subject: [PATCH] Add hardness parameter to Clip. --- CHANGES.md | 1 + README.md | 17 +++++++++-------- src/hacker.rs | 2 +- src/hacker32.rs | 2 +- src/prelude.rs | 2 +- src/shape.rs | 6 +++--- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ac46883..2056546 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ - Clarified latency: it only applies to involuntary causal latencies. - `AdaptiveTanh` is now generic `Adaptive` distortion with an inner shape. To migrate, try `Adaptive::new(timescale, Tanh(hardness))`. +- `Clip` shape now has a hardness parameter. `Clip(1.0)` to migrate. ### Version 0.18.2 diff --git a/README.md b/README.md index 8ecd2f6..3563356 100644 --- a/README.md +++ b/README.md @@ -1256,18 +1256,19 @@ let partials = busf::(|f| noise() >> resonator_hz(xerp(1_000.0, 2_000 #### Waveshaping Modes -These are arguments to the `shape` opcode. +These are arguments to the `shape` opcode. Shapes `Atan`, `Clip`, `Softsign` and `Tanh` +all have a slope of 1 at the origin when hardness is 1 and saturate in the range -1...1. -- `Clip`: Clip signal to -1...1. -- `ClipTo(minimum, maximum)`: Clip signal between the two arguments. -- `Tanh(hardness)`: Apply `tanh` distortion with configurable hardness. Argument to `tanh` is multiplied by the hardness value. +- `Adaptive::new(timescale, inner)`: Apply adaptive normalizing distortion with smoothing `timescale` in seconds. +Smoothing timescale is the time it takes for level estimation to move halfway to a new value. +The argument to the `inner` shape is divided by the RMS level of the signal. - `Atan(hardness)`: Apply `atan` distortion with configurable hardness, with the output range scaled to -1...1. Argument to `atan` is multiplied by the hardness value. -- `Softsign(hardness)`: Apply `softsign` distortion with configurable hardness. Argument to `softsign` is multiplied by the hardness value. +- `Clip(hardness)`: Multiply signal with hardness and then clamp it to -1...1. +- `ClipTo(minimum, maximum)`: Clip signal between the two arguments. - `Crush(levels)`: Apply a staircase function with configurable number of levels per unit. - `SoftCrush(levels)`: Apply a smooth staircase function with configurable number of levels per unit. -- `AdaptiveTanh::new(timescale, hardness)`: Apply adaptive normalizing distortion with smoothing `timescale` in seconds. -Smoothing timescale is the time it takes for level estimation to move halfway to a new value. -Argument to `tanh` is multiplied by the hardness value and divided by the RMS level of the signal. +- `Softsign(hardness)`: Apply `softsign` distortion with configurable hardness. Argument to `softsign` is multiplied by the hardness value. +- `Tanh(hardness)`: Apply `tanh` distortion with configurable hardness. Argument to `tanh` is multiplied by the hardness value. #### Metering Modes diff --git a/src/hacker.rs b/src/hacker.rs index 42dd3c8..762976b 100644 --- a/src/hacker.rs +++ b/src/hacker.rs @@ -1170,7 +1170,7 @@ pub fn shape(mode: S) -> An> { /// - Input 0: input signal /// - Output 0: clipped signal pub fn clip() -> An> { - An(Shaper::new(Clip)) + An(Shaper::new(Clip(1.0))) } /// Clip signal to `minimum`...`maximum`. diff --git a/src/hacker32.rs b/src/hacker32.rs index 463590b..b11df0b 100644 --- a/src/hacker32.rs +++ b/src/hacker32.rs @@ -1170,7 +1170,7 @@ pub fn shape(mode: S) -> An> { /// - Input 0: input signal /// - Output 0: clipped signal pub fn clip() -> An> { - An(Shaper::new(Clip)) + An(Shaper::new(Clip(1.0))) } /// Clip signal to `minimum`...`maximum`. diff --git a/src/prelude.rs b/src/prelude.rs index cf40472..e1e4888 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1184,7 +1184,7 @@ pub fn shape(mode: S) -> An> { /// - Input 0: input signal /// - Output 0: clipped signal pub fn clip() -> An> { - An(Shaper::new(Clip)) + An(Shaper::new(Clip(1.0))) } /// Clip signal to `minimum`...`maximum`. diff --git a/src/shape.rs b/src/shape.rs index a1d6be2..6cc8f83 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -45,16 +45,16 @@ impl f32 + Clone + Sync + Send> Shape for ShapeFn { /// Clip signal to -1...1. #[derive(Clone)] -pub struct Clip; +pub struct Clip(pub f32); impl Shape for Clip { #[inline] fn shape(&mut self, input: f32) -> f32 { - input.clamp(-1.0, 1.0) + (input * self.0).clamp(-1.0, 1.0) } #[inline] fn simd(&mut self, input: F32x) -> F32x { - input.fast_max(-F32x::ONE).fast_min(F32x::ONE) + (input * self.0).fast_max(-F32x::ONE).fast_min(F32x::ONE) } }