use super::audionode::*;
use super::combinator::*;
use super::math::*;
use super::setting::*;
use super::signal::*;
use super::*;
use num_complex::Complex64;
use numeric_array::typenum::*;
#[inline]
fn logistic<T: Real>(x: T) -> T {
T::one() / (T::one() + exp(T::zero() - x))
}
fn halfway_coeff(samples: f64) -> f64 {
let r0 = log(max(1.0, samples)) - 0.861624594696583;
let r1 = logistic(r0);
let r2 = r1 * 1.13228543863477 - 0.1322853859;
1.0 - min(0.9999999, r2)
}
#[derive(Default, Clone)]
pub struct Follow<F: Real> {
v3: F,
v2: F,
v1: F,
coeff: F,
coeff_now: F,
response_time: F,
sample_rate: F,
}
impl<F: Real> Follow<F> {
pub fn new(response_time: F) -> Self {
let mut node = Self {
response_time,
..Follow::default()
};
node.reset();
node.set_sample_rate(DEFAULT_SR);
node
}
pub fn response_time(&self) -> F {
self.response_time
}
pub fn set_response_time(&mut self, response_time: F) {
self.response_time = response_time;
self.coeff = F::from_f64(halfway_coeff((response_time * self.sample_rate).to_f64()));
if self.coeff_now < F::one() {
self.coeff_now = self.coeff;
}
}
pub fn value(&self) -> F {
self.v3
}
pub fn set_value(&mut self, x: F) {
self.v3 = x;
self.v2 = x;
self.v1 = x;
}
}
impl<F: Real> AudioNode for Follow<F> {
const ID: u64 = 24;
type Inputs = U1;
type Outputs = U1;
fn reset(&mut self) {
self.v3 = F::zero();
self.v2 = F::zero();
self.v1 = F::zero();
self.coeff_now = F::one();
}
fn set_sample_rate(&mut self, sample_rate: f64) {
self.sample_rate = convert(sample_rate);
self.set_response_time(self.response_time);
}
#[inline]
fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
let rcoeff = F::one() - self.coeff_now;
self.v1 = self.coeff_now * convert(input[0]) + rcoeff * self.v1;
self.v2 = self.coeff_now * self.v1 + rcoeff * self.v2;
self.v3 = self.coeff_now * self.v2 + rcoeff * self.v3;
self.coeff_now = self.coeff;
[convert(self.v3)].into()
}
fn set(&mut self, setting: Setting) {
if let Parameter::Time(time) = setting.parameter() {
self.set_response_time(F::from_f32(*time));
}
}
fn route(&mut self, input: &SignalFrame, frequency: f64) -> SignalFrame {
let mut output = SignalFrame::new(self.outputs());
output.set(
0,
input.at(0).filter(0.0, |r| {
let c = 1.0 - self.coeff.to_f64();
let f = frequency * f64::TAU / self.sample_rate.to_f64();
let z1 = Complex64::from_polar(1.0, -f);
let pole = (1.0 - c) / (1.0 - c * z1);
r * pole * pole * pole
}),
);
output
}
}
#[derive(Default, Clone)]
pub struct AFollow<F: Real> {
v3: F,
v2: F,
v1: F,
acoeff: F,
rcoeff: F,
acoeff_now: F,
rcoeff_now: F,
atime: F,
rtime: F,
sample_rate: F,
}
impl<F: Real> AFollow<F> {
pub fn new(attack_time: F, release_time: F) -> Self {
let mut node = Self {
atime: attack_time,
rtime: release_time,
..AFollow::default()
};
node.reset();
node.set_sample_rate(DEFAULT_SR);
node
}
pub fn attack_time(&self) -> F {
self.atime
}
pub fn release_time(&self) -> F {
self.rtime
}
pub fn set_time(&mut self, attack_time: F, release_time: F) {
self.atime = attack_time;
self.rtime = release_time;
self.acoeff = F::from_f64(halfway_coeff(
(self.attack_time() * self.sample_rate).to_f64(),
));
self.rcoeff = F::from_f64(halfway_coeff(
(self.release_time() * self.sample_rate).to_f64(),
));
if self.acoeff_now < F::one() {
self.acoeff_now = self.acoeff;
self.rcoeff_now = self.rcoeff;
}
}
pub fn value(&self) -> F {
self.v3
}
pub fn set_value(&mut self, x: F) {
self.v3 = x;
self.v2 = x;
self.v1 = x;
}
}
impl<F: Real> AudioNode for AFollow<F> {
const ID: u64 = 29;
type Inputs = U1;
type Outputs = U1;
fn reset(&mut self) {
self.v3 = F::zero();
self.v2 = F::zero();
self.v1 = F::zero();
self.acoeff_now = F::one();
self.rcoeff_now = F::one();
}
fn set_sample_rate(&mut self, sample_rate: f64) {
self.sample_rate = convert(sample_rate);
self.set_time(self.atime, self.rtime);
}
#[inline]
fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
let v0: F = convert(input[0]);
self.v1 =
(self.atime, self.rtime).filter_pole(v0, self.v1, self.acoeff_now, self.rcoeff_now);
self.v2 = (self.atime, self.rtime).filter_pole(
self.v1,
self.v2,
self.acoeff_now,
self.rcoeff_now,
);
self.v3 = (self.atime, self.rtime).filter_pole(
self.v2,
self.v3,
self.acoeff_now,
self.rcoeff_now,
);
self.acoeff_now = self.acoeff;
self.rcoeff_now = self.rcoeff;
[convert(self.v3)].into()
}
fn set(&mut self, setting: Setting) {
if let Parameter::AttackRelease(attack, release) = setting.parameter() {
self.set_time(F::from_f32(*attack), F::from_f32(*release));
}
}
fn route(&mut self, input: &SignalFrame, frequency: f64) -> SignalFrame {
let mut output = SignalFrame::new(self.outputs());
if self.acoeff == self.rcoeff {
output.set(
0,
input.at(0).filter(0.0, |r| {
let c = 1.0 - self.acoeff.to_f64();
let f = frequency * f64::TAU / self.sample_rate.to_f64();
let z1 = Complex64::from_polar(1.0, -f);
let pole = (1.0 - c) / (1.0 - c * z1);
r * pole * pole * pole
}),
);
} else {
output.set(0, input.at(0).distort(0.0));
}
output
}
}