use ndarray::Array1;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BassBoostCurve {
Linear,
Harman,
Custom,
}
#[derive(Debug, Clone)]
pub struct BassBoostConfig {
pub enabled: bool,
pub start_freq: f64,
pub peak_freq: f64,
pub end_freq: f64,
pub max_boost_db: f64,
pub curve_type: BassBoostCurve,
}
impl Default for BassBoostConfig {
fn default() -> Self {
Self {
enabled: false,
start_freq: 20.0,
peak_freq: 60.0,
end_freq: 200.0,
max_boost_db: 4.0,
curve_type: BassBoostCurve::Harman,
}
}
}
pub fn compute_bass_boost_curve(freqs: &Array1<f64>, config: &BassBoostConfig) -> Array1<f64> {
if !config.enabled {
return Array1::zeros(freqs.len());
}
freqs.mapv(|f| match config.curve_type {
BassBoostCurve::Linear => compute_linear_bass_boost(f, config),
BassBoostCurve::Harman => compute_harman_bass_boost(f, config),
BassBoostCurve::Custom => compute_linear_bass_boost(f, config), })
}
fn compute_linear_bass_boost(f: f64, config: &BassBoostConfig) -> f64 {
if f < config.start_freq {
0.0
} else if f < config.peak_freq {
let t = (f - config.start_freq) / (config.peak_freq - config.start_freq);
config.max_boost_db * t
} else if f < config.end_freq {
let t = (f - config.peak_freq) / (config.end_freq - config.peak_freq);
config.max_boost_db * (1.0 - t)
} else {
0.0
}
}
fn compute_harman_bass_boost(f: f64, config: &BassBoostConfig) -> f64 {
if f < config.start_freq || f > config.end_freq {
return 0.0;
}
let peak = config.peak_freq;
let width = (config.end_freq - config.start_freq) / 2.0;
let z = (f - peak) / width;
config.max_boost_db * (-0.5 * z * z).exp()
}
pub fn create_bass_boosted_target(
base_target: &Array1<f64>,
freqs: &Array1<f64>,
config: &BassBoostConfig,
) -> Array1<f64> {
let bass_boost = compute_bass_boost_curve(freqs, config);
base_target + &bass_boost
}