use super::audionode::*;
use super::buffer::*;
use super::math::*;
use super::signal::*;
use super::*;
use numeric_array::typenum::*;
pub trait Shape: Clone + Sync + Send {
fn shape(&mut self, input: f32) -> f32;
#[inline]
fn simd(&mut self, input: F32x) -> F32x {
F32x::new(core::array::from_fn(|i| {
self.shape(input.as_array_ref()[i])
}))
}
#[allow(unused_variables)]
fn set_sample_rate(&mut self, sample_rate: f64) {}
fn reset(&mut self) {}
}
#[derive(Clone)]
pub struct ShapeFn<S: Fn(f32) -> f32 + Clone + Sync + Send>(pub S);
impl<S: Fn(f32) -> f32 + Clone + Sync + Send> Shape for ShapeFn<S> {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
self.0(input)
}
}
#[derive(Clone)]
pub struct Clip(pub f32);
impl Shape for Clip {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
(input * self.0).clamp(-1.0, 1.0)
}
#[inline]
fn simd(&mut self, input: F32x) -> F32x {
(input * self.0).fast_max(-F32x::ONE).fast_min(F32x::ONE)
}
}
#[derive(Clone)]
pub struct ClipTo(pub f32, pub f32);
impl Shape for ClipTo {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
input.clamp(self.0, self.1)
}
#[inline]
fn simd(&mut self, input: F32x) -> F32x {
input
.fast_max(F32x::splat(self.0))
.fast_min(F32x::splat(self.1))
}
}
#[derive(Clone)]
pub struct Tanh(pub f32);
impl Shape for Tanh {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
(input * self.0).tanh()
}
}
#[derive(Clone)]
pub struct Atan(pub f32);
impl Shape for Atan {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
(input * (self.0 * f32::PI * 0.5)).atan() * (2.0 / f32::PI)
}
#[inline]
fn simd(&mut self, input: F32x) -> F32x {
(input * (self.0 * f32::PI * 0.5)).atan() * (2.0 / f32::PI)
}
}
#[derive(Clone)]
pub struct Softsign(pub f32);
impl Shape for Softsign {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
softsign(input * self.0)
}
#[inline]
fn simd(&mut self, input: F32x) -> F32x {
input * self.0 / (F32x::ONE + input.abs() * self.0)
}
}
#[derive(Clone)]
pub struct Crush(pub f32);
impl Shape for Crush {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
(input * self.0).round() / self.0
}
#[inline]
fn simd(&mut self, input: F32x) -> F32x {
(input * self.0).round() / self.0
}
}
#[derive(Clone)]
pub struct SoftCrush(pub f32);
impl Shape for SoftCrush {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
let x = input * self.0;
let y = floor(x);
(y + smooth9(x - y)) / self.0
}
#[inline]
fn simd(&mut self, input: F32x) -> F32x {
let x = input * self.0;
let y = floor(x);
(y + smooth9(x - y)) / self.0
}
}
#[derive(Clone)]
pub struct Adaptive<S: Shape> {
inner: S,
timescale: f32,
smoothing: f32,
state: f32,
}
impl<S: Shape> Adaptive<S> {
pub fn new(timescale: f32, inner: S) -> Self {
let mut adaptive = Self {
inner,
timescale,
smoothing: 0.0,
state: 0.0,
};
adaptive.set_sample_rate(DEFAULT_SR);
adaptive
}
}
impl<S: Shape> Shape for Adaptive<S> {
#[inline]
fn shape(&mut self, input: f32) -> f32 {
self.state =
self.smoothing * self.state + (1.0 - self.smoothing) * (1.0e-6 + squared(input));
self.inner.shape(input / sqrt(self.state))
}
fn reset(&mut self) {
self.state = 1.0e-3;
self.inner.reset();
}
fn set_sample_rate(&mut self, sample_rate: f64) {
self.smoothing = pow(0.5, 1.0 / (self.timescale.to_f64() * sample_rate)).to_f32();
self.inner.set_sample_rate(sample_rate);
}
}
#[derive(Clone)]
pub struct Shaper<S: Shape> {
shape: S,
}
impl<S: Shape> Shaper<S> {
pub fn new(shape: S) -> Self {
let mut shaper = Self { shape };
shaper.set_sample_rate(DEFAULT_SR);
shaper
}
}
impl<S: Shape> AudioNode for Shaper<S> {
const ID: u64 = 42;
type Inputs = U1;
type Outputs = U1;
fn reset(&mut self) {
self.shape.reset();
}
fn set_sample_rate(&mut self, sample_rate: f64) {
self.shape.set_sample_rate(sample_rate);
}
#[inline]
fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
Frame::from([self.shape.shape(input[0])])
}
fn process(&mut self, size: usize, input: &BufferRef, output: &mut BufferMut) {
for i in 0..full_simd_items(size) {
output.set(0, i, self.shape.simd(input.at(0, i)));
}
self.process_remainder(size, input, output);
}
fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
let mut output = SignalFrame::new(self.outputs());
output.set(0, input.at(0).distort(0.0));
output
}
}