// Subhoofer's main inspiration - ABass Algorithm mimicking a bass plugin of Renaissance
// Ardura 2023
use nih_plug::util;
// Subhoofer's default harmonic_strength was 0.0011 and hardness 0.04
pub fn a_bass_saturation(signal: f32, harmonic_strength: f32) -> f32 {
let num_harmonics: usize = 4;
let mut summed: f32 = 0.0;
for j in 1..=num_harmonics {
match j {
1 => {
let harmonic_component: f32 =
harmonic_strength * 170.0 * (signal * j as f32).cos() - signal;
summed += harmonic_component;
}
2 => {
let harmonic_component: f32 =
harmonic_strength * 25.0 * (signal * j as f32).sin() - signal;
summed += harmonic_component;
}
3 => {
let harmonic_component: f32 =
harmonic_strength * 150.0 * (signal * j as f32).cos() - signal;
summed += harmonic_component;
}
4 => {
let harmonic_component2: f32 =
harmonic_strength * 80.0 * (signal * j as f32).sin() - signal;
summed += harmonic_component2;
}
_ => unreachable!(),
}
}
if harmonic_strength > 0.0 {
chebyshev_tape(summed, 0.04) * util::db_to_gain(-9.0)
} else {
0.0
}
}
// Modified function from Duro Console for different behavior - hoof hardness
fn chebyshev_tape(sample: f32, drive: f32) -> f32 {
let dry = 1.0 - drive;
let peak = f32::max(sample.abs(), 1.0);
let x = sample / peak;
let x2 = x * x;
let x3 = x * x2;
let x5 = x3 * x2;
let x6 = x3 * x3;
let y = x - 0.166667 * x3 + 0.00833333 * x5 - 0.000198413 * x6 + 0.0000000238 * x6 * drive;
dry * sample + (1.0 - dry) * y / (1.0 + y.abs())
}