use super::audionode::*;
use super::combinator::*;
use super::delay::{AllNest, Delay};
use super::math::*;
use super::signal::*;
use super::wave::*;
use super::*;
use funutd::dna::*;
use numeric_array::typenum::*;
extern crate alloc;
use alloc::format;
use alloc::vec::Vec;
pub fn generate_reverb(dna: &mut Dna) -> An<impl AudioNode<Inputs = U2, Outputs = U2>> {
let mut times = [0.0; 32];
for i in 0..32 {
let name = format!("Delay {}", i);
if i < 32 {
times[i] = dna.f32_in(&name, 0.030, 0.070);
} else {
times[i] = dna.f32_in(&name, 0.001, 0.030);
}
}
super::prelude::reverb4_stereo_delays(times, 100.0)
}
pub fn reverb_fitness(reverb: An<impl AudioNode<Inputs = U2, Outputs = U2>>) -> f32 {
let mut response = Wave::render(
44100.0,
32768.0 / 44100.0,
&mut (An(Impulse::new()) >> reverb),
);
let mut fitness = 0.0;
for channel in 0..=1 {
if channel == 0 || channel == 1 {
let echo_weight = 1.0;
for i in 1..response.length() {
let weight = 1.0 / (i as f32);
let r = response.at(channel, i);
let threshold = 1.0e-9;
if abs(r) >= threshold {
fitness += weight * echo_weight;
}
}
}
for i in 0..response.length() {
let w = 0.5
+ 0.5
* cos(
(i as i64 - (response.length() as i64 >> 1)) as f32 * f32::TAU
/ response.length() as f32,
);
response.set(channel, i, response.at(channel, i) * w);
}
let mut data = match channel {
0 | 1 => response.channel(channel).clone(),
_ => {
let mut stereo = response.channel(0).clone();
for i in 0..stereo.len() {
stereo[i] += response.at(1, i);
}
stereo
}
};
let spectrum = super::fft::real_fft(&mut data);
let outlier_weight = 0.1;
let outlier_samples = 50;
let mut sum = 0.0;
for i in 1..=outlier_samples {
sum += spectrum[i].norm();
}
for i in outlier_samples + 1..spectrum.len() {
let norm0 = spectrum[i - outlier_samples].norm();
let norm1 = spectrum[i].norm();
let mean = sum / outlier_samples as f32;
if norm1 > mean {
fitness -= squared(norm1 - mean) * outlier_weight;
}
sum -= norm0;
sum += norm1;
}
}
fitness
}
type Schroeder = AllNest<U1, Delay>;
#[derive(Clone)]
struct ReverbBlock<F: AudioNode<Inputs = U1, Outputs = U1>> {
allpass0: [Schroeder; 4],
allpass1: [Schroeder; 4],
filter0: F,
filter1: F,
delay: Delay,
}
#[derive(Clone)]
pub struct Reverb<F: AudioNode<Inputs = U1, Outputs = U1>> {
pre: [Schroeder; 4],
block: Vec<ReverbBlock<F>>,
feedback: f32,
a: f32,
}
impl<F: AudioNode<Inputs = U1, Outputs = U1>> Reverb<F> {
pub fn new(time: f64, diffusion: f64, filter: F) -> Self {
let ldelays = [
401, 421, 443, 463, 487, 503, 523, 547, 563, 587, 607, 619, 643, 661, 683, 701, 727,
743, 761, 787, 809, 823, 839, 863, 883, 907, 929, 947, 967, 983, 1009, 1021,
];
let rdelays = [
419, 433, 457, 479, 491, 509, 541, 557, 577, 593, 613, 631, 653, 673, 691, 719, 733,
757, 773, 797, 811, 829, 853, 877, 887, 911, 937, 953, 977, 997, 1013, 1033,
];
let delays = [1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123];
let coeff = lerp(0.5, 0.9, diffusion) as f32;
let mut block = Vec::with_capacity(8);
for i in 0..8 {
let allpass0 = core::array::from_fn(|j| {
Schroeder::new(
coeff,
Delay::new((ldelays[i + j * 8] - 1) as f64 / DEFAULT_SR),
)
});
let allpass1 = core::array::from_fn(|j| {
Schroeder::new(
coeff,
Delay::new((rdelays[i + j * 8] - 1) as f64 / DEFAULT_SR),
)
});
let delay = Delay::new(delays[7 - i] as f64 / DEFAULT_SR);
block.push(ReverbBlock::<F> {
allpass0,
allpass1,
filter0: filter.clone(),
filter1: filter.clone(),
delay,
});
}
let a = pow(db_amp(-60.0), 0.035 / time) as f32;
let predelay = [245, 367, 263, 349];
let pre = core::array::from_fn(|i| {
Schroeder::new(coeff, Delay::new((predelay[i] - 1) as f64 / DEFAULT_SR))
});
Self {
pre,
block,
feedback: 0.0,
a,
}
}
}
impl<F: AudioNode<Inputs = U1, Outputs = U1>> AudioNode for Reverb<F> {
const ID: u64 = 85;
type Inputs = U2;
type Outputs = U2;
fn reset(&mut self) {
for block in self.block.iter_mut() {
for x in block.allpass0.iter_mut() {
x.reset();
}
for x in block.allpass1.iter_mut() {
x.reset();
}
block.filter0.reset();
block.filter1.reset();
block.delay.reset();
}
self.feedback = 0.0;
}
fn set_sample_rate(&mut self, sample_rate: f64) {
for block in self.block.iter_mut() {
for x in block.allpass0.iter_mut() {
x.set_sample_rate(sample_rate);
}
for x in block.allpass1.iter_mut() {
x.set_sample_rate(sample_rate);
}
block.filter0.set_sample_rate(sample_rate);
block.filter1.set_sample_rate(sample_rate);
block.delay.set_sample_rate(sample_rate);
}
}
#[inline]
fn tick(&mut self, input: &Frame<f32, Self::Inputs>) -> Frame<f32, Self::Outputs> {
let mut v0 = self.feedback;
let mut output0 = 0.0;
let mut output1 = 0.0;
let input0 = self.pre[0].filter_mono(input[0] * 0.5);
let input0 = self.pre[1].filter_mono(input0);
let input1 = self.pre[2].filter_mono(input[1] * 0.5);
let input1 = self.pre[3].filter_mono(input1);
for block in self.block.iter_mut() {
v0 = block.delay.filter_mono(v0);
v0 = block.allpass0[0].filter_mono(self.a * v0 + input0);
v0 = block.allpass0[1].filter_mono(v0);
v0 = block.allpass0[2].filter_mono(v0);
v0 = block.allpass0[3].filter_mono(v0);
v0 = block.filter0.filter_mono(v0);
output0 = v0;
v0 = block.allpass1[0].filter_mono(self.a * v0 + input1);
v0 = block.allpass1[1].filter_mono(v0);
v0 = block.allpass1[2].filter_mono(v0);
v0 = block.allpass1[3].filter_mono(v0);
v0 = block.filter1.filter_mono(v0);
output1 = v0;
}
self.feedback = v0;
[output0, output1].into()
}
fn route(&mut self, input: &SignalFrame, _frequency: f64) -> SignalFrame {
Routing::Arbitrary(0.0).route(input, 2)
}
}