use super::audionode::*;
use super::combinator::*;
use super::follow::*;
use super::math::*;
use super::shared::*;
use super::signal::*;
use super::*;
use numeric_array::typenum::*;
use std::sync::Arc;
pub trait Monoidal<T>: Clone {
fn binop(&self, x: T, y: T) -> T;
}
#[derive(Default, Clone)]
pub struct Amplitude<T: Num> {
_marker: std::marker::PhantomData<T>,
}
impl<T: Num> Amplitude<T> {
pub fn new() -> Self {
Amplitude::default()
}
}
impl<T: Num> Monoidal<T> for Amplitude<T> {
fn binop(&self, x: T, y: T) -> T {
max(abs(x), abs(y))
}
}
#[derive(Default, Clone)]
pub struct Maximum<T: Num> {
_marker: std::marker::PhantomData<T>,
}
impl<T: Num> Maximum<T> {
pub fn new() -> Self {
Maximum::default()
}
}
impl<T: Num> Monoidal<T> for Maximum<T> {
fn binop(&self, x: T, y: T) -> T {
max(x, y)
}
}
#[derive(Clone)]
pub struct ReduceBuffer<T, B>
where
T: Num,
B: Monoidal<T>,
{
buffer: Vec<T>,
length: usize,
leaf_offset: usize,
binop: B,
}
impl<T, B> ReduceBuffer<T, B>
where
T: Num,
B: Monoidal<T>,
{
fn get_index(&self, i: usize) -> usize {
self.leaf_offset + i
}
pub fn new(length: usize, binop: B) -> Self {
let leaf_offset = length.next_power_of_two();
ReduceBuffer {
buffer: vec![T::zero(); leaf_offset + length + (length & 1)],
length,
leaf_offset,
binop,
}
}
pub fn length(&self) -> usize {
self.length
}
pub fn total(&self) -> T {
self.buffer[1]
}
pub fn set(&mut self, index: usize, value: T) {
let mut i = self.get_index(index);
self.buffer[i] = value;
while i > 1 {
let reduced = self.binop.binop(self.buffer[i], self.buffer[i ^ 1]);
i >>= 1;
self.buffer[i] = reduced;
}
}
pub fn clear(&mut self) {
for i in 0..self.buffer.len() {
self.buffer[i] = T::zero();
}
}
}
#[derive(Clone)]
pub struct Limiter<T, N, S>
where
T: Real,
N: Size<T>,
S: ScalarOrPair<Sample = T>,
{
lookahead: f64,
#[allow(dead_code)]
release: f64,
sample_rate: f64,
reducer: ReduceBuffer<T, Maximum<T>>,
follower: AFollow<T, T, S>,
buffer: Vec<Frame<T, N>>,
index: usize,
}
impl<T, N, S> Limiter<T, N, S>
where
T: Real,
N: Size<T>,
S: ScalarOrPair<Sample = T>,
{
fn advance(&mut self) {
self.index += 1;
if self.index >= self.reducer.length() {
self.index = 0;
}
}
fn buffer_length(sample_rate: f64, lookahead: f64) -> usize {
max(1, round(sample_rate * lookahead) as usize)
}
fn new_buffer(sample_rate: f64, lookahead: f64) -> ReduceBuffer<T, Maximum<T>> {
ReduceBuffer::new(Self::buffer_length(sample_rate, lookahead), Maximum::new())
}
pub fn new(sample_rate: f64, time: S) -> Self {
let (lookahead, release) = time.broadcast();
Limiter {
lookahead: lookahead.to_f64(),
release: release.to_f64(),
sample_rate,
follower: AFollow::new(
sample_rate,
S::construct(
lookahead * convert::<f64, T>(0.4),
release * convert::<f64, T>(0.4),
),
),
buffer: vec![],
reducer: Self::new_buffer(sample_rate, lookahead.to_f64()),
index: 0,
}
}
}
impl<T, N, S> AudioNode for Limiter<T, N, S>
where
T: Real,
N: Size<T>,
S: ScalarOrPair<Sample = T>,
{
const ID: u64 = 25;
type Sample = T;
type Inputs = N;
type Outputs = N;
type Setting = ();
fn reset(&mut self, sample_rate: Option<f64>) {
self.index = 0;
if let Some(sample_rate) = sample_rate {
self.sample_rate = sample_rate;
let length = Self::buffer_length(sample_rate, self.lookahead);
if length != self.reducer.length {
self.reducer = Self::new_buffer(sample_rate, self.lookahead);
return;
}
}
self.follower.reset(sample_rate);
self.reducer.clear();
self.buffer.clear();
}
#[inline]
fn tick(
&mut self,
input: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
let amplitude = input.iter().fold(T::zero(), |amp, &x| max(amp, abs(x)));
self.reducer.set(self.index, amplitude);
if self.buffer.len() < self.reducer.length() {
self.buffer.push(input.clone());
if self.buffer.len() == self.reducer.length() {
self.follower.set_value(self.reducer.total());
}
self.advance();
Frame::default()
} else {
let output = self.buffer[self.index].clone();
self.buffer[self.index] = input.clone();
self.follower
.filter_mono(max(T::one(), self.reducer.total() * T::from_f64(1.10)));
self.advance();
let limit = self.follower.value();
output * Frame::splat(T::from_f64(1.0) / limit)
}
}
fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
let mut output = new_signal_frame(self.outputs());
for i in 0..N::USIZE {
output[i] = input[i].delay(self.reducer.length() as f64);
}
output
}
}
#[derive(Default, Clone)]
pub struct Declick<T: Float, F: Real> {
_marker: std::marker::PhantomData<T>,
t: F,
duration: F,
sample_duration: F,
}
impl<T: Float, F: Real> Declick<T, F> {
pub fn new(sample_rate: f64, duration: F) -> Self {
let mut node = Declick::<T, F> {
duration,
..Default::default()
};
node.reset(Some(sample_rate));
node
}
}
impl<T: Float, F: Real> AudioNode for Declick<T, F> {
const ID: u64 = 23;
type Sample = T;
type Inputs = U1;
type Outputs = U1;
type Setting = ();
fn reset(&mut self, sample_rate: Option<f64>) {
if let Some(sample_rate) = sample_rate {
self.sample_duration = F::from_f64(1.0 / sample_rate);
}
self.t = F::zero();
}
#[inline]
fn tick(
&mut self,
input: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
if self.t < self.duration {
let phase = delerp(F::zero(), self.duration, self.t);
let value = smooth5(phase);
self.t += self.sample_duration;
[input[0] * convert(value)].into()
} else {
[input[0]].into()
}
}
fn process(
&mut self,
size: usize,
input: &[&[Self::Sample]],
output: &mut [&mut [Self::Sample]],
) {
output[0][..size].clone_from_slice(&input[0][..size]);
if self.t < self.duration {
let mut phase = delerp(F::zero(), self.duration, self.t);
let phase_d = self.sample_duration / self.duration;
let end_time = self.t + F::new(size as i64) * self.sample_duration;
let end_index = if self.duration < end_time {
ceil((self.duration - self.t) / self.sample_duration).to_i64() as usize
} else {
size
};
for i in 0..end_index {
output[0][i] *= convert(smooth5(phase));
phase += phase_d;
}
self.t = end_time;
}
}
fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
let mut output = new_signal_frame(self.outputs());
output[0] = input[0];
output
}
}
#[derive(Copy, Clone)]
pub enum Meter {
Sample,
Peak(f64),
Rms(f64),
}
impl Meter {
pub fn latest_only(&self) -> bool {
matches!(self, Meter::Sample)
}
}
#[derive(Clone)]
pub struct MeterState<T: Real> {
state: T,
}
impl<T: Real> MeterState<T> {
pub fn new(_meter: Meter, _sample_rate: f64) -> Self {
Self { state: T::zero() }
}
pub fn reset(&mut self, _meter: Meter, _sample_rate: Option<f64>) {
self.state = T::zero();
}
pub fn tick(&mut self, meter: Meter, value: T) {
match meter {
Meter::Sample => self.state = value,
Meter::Peak(smoothing) => self.state = max(self.state * convert(smoothing), abs(value)),
Meter::Rms(smoothing) => {
self.state =
self.state * convert(smoothing) + value * value * convert(1.0 - smoothing)
}
}
}
pub fn value(&self, meter: Meter) -> T {
match meter {
Meter::Sample => self.state,
Meter::Peak(_) => self.state,
Meter::Rms(_) => sqrt(self.state),
}
}
}
#[derive(Clone)]
pub struct MeterNode<T: Real> {
meter: Meter,
state: MeterState<T>,
sample_rate: f64,
}
impl<T: Real> MeterNode<T> {
pub fn new(sample_rate: f64, meter: Meter) -> Self {
Self {
meter,
state: MeterState::new(meter, sample_rate),
sample_rate,
}
}
}
impl<T: Real> AudioNode for MeterNode<T> {
const ID: u64 = 61;
type Sample = T;
type Inputs = U1;
type Outputs = U1;
type Setting = ();
fn reset(&mut self, sample_rate: Option<f64>) {
if let Some(sr) = sample_rate {
self.sample_rate = sr;
}
self.state.reset(self.meter, sample_rate);
}
#[inline]
fn tick(
&mut self,
input: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
self.state.tick(self.meter, input[0]);
[convert(self.state.value(self.meter))].into()
}
fn process(
&mut self,
size: usize,
input: &[&[Self::Sample]],
output: &mut [&mut [Self::Sample]],
) {
for i in 0..size {
self.state.tick(self.meter, input[0][i]);
output[0][i] = convert(self.state.value(self.meter));
}
}
fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
let mut output = new_signal_frame(self.outputs());
output[0] = input[0].distort(0.0);
output
}
}
pub struct Monitor<T: Real + Atomic> {
meter: Meter,
state: MeterState<T>,
sample_rate: f64,
shared: Arc<T::Storage>,
}
impl<T: Real + Atomic> Clone for Monitor<T> {
fn clone(&self) -> Self {
Self {
meter: self.meter,
state: self.state.clone(),
sample_rate: self.sample_rate,
shared: Arc::clone(&self.shared),
}
}
}
impl<T: Real + Atomic> Monitor<T> {
pub fn new(sample_rate: f64, shared: &Shared<T>, meter: Meter) -> Self {
Self {
meter,
state: MeterState::new(meter, sample_rate),
sample_rate,
shared: Arc::clone(shared.get_shared()),
}
}
}
impl<T: Real + Atomic> AudioNode for Monitor<T> {
const ID: u64 = 56;
type Sample = T;
type Inputs = U1;
type Outputs = U1;
type Setting = ();
fn reset(&mut self, sample_rate: Option<f64>) {
if let Some(sr) = sample_rate {
self.sample_rate = sr;
}
self.state.reset(self.meter, sample_rate);
}
#[inline]
fn tick(
&mut self,
input: &Frame<Self::Sample, Self::Inputs>,
) -> Frame<Self::Sample, Self::Outputs> {
self.state.tick(self.meter, input[0]);
T::store(&self.shared, self.state.value(self.meter));
*input
}
fn process(
&mut self,
size: usize,
input: &[&[Self::Sample]],
output: &mut [&mut [Self::Sample]],
) {
if size == 0 {
return;
}
if self.meter.latest_only() {
self.state.tick(self.meter, input[0][size - 1]);
} else {
for i in 0..size {
self.state.tick(self.meter, input[0][i]);
}
}
T::store(&self.shared, self.state.value(self.meter));
output[0][..size].clone_from_slice(&input[0][..size]);
}
fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
input.clone()
}
}