mod atomic_state;
mod info;
mod limiter;
mod meter;
mod normalizer;
mod ramp;
pub use atomic_state::AtomicLoudnessState;
pub use info::LoudnessInfo;
pub use limiter::PeakLimiter;
pub use meter::{LoudnessMeter, TruePeakDetector};
pub use normalizer::LoudnessNormalizer;
pub use ramp::GainRamp;
#[cfg(test)]
mod tests {
use super::*;
use crate::processor::dsp::{db_to_linear, linear_to_db};
#[test]
fn test_db_conversion() {
assert!((db_to_linear(0.0) - 1.0).abs() < 1e-10);
assert!((db_to_linear(-6.0) - 0.501).abs() < 0.01);
assert!((linear_to_db(1.0) - 0.0).abs() < 1e-10);
assert!((linear_to_db(0.5) - (-6.02)).abs() < 0.1);
}
#[test]
fn test_gain_ramp() {
let mut ramp = GainRamp::new(0.0, 1.0, 44100, 100);
assert!(!ramp.is_done());
let mut samples = vec![1.0; 5000];
ramp.apply(&mut samples);
assert!(ramp.remaining_samples() < 1000);
assert!(ramp.current() > 0.9);
}
#[test]
fn test_gain_ramp_current_is_cached_accessor() {
let mut ramp = GainRamp::new(0.0, 1.0, 10, 100);
assert_eq!(ramp.current(), 0.0);
assert_eq!(ramp.next_gain(), 0.0);
assert_eq!(ramp.current(), 1.0);
assert!(ramp.is_done());
ramp.retarget(0.0, 10, 100);
assert_eq!(ramp.current(), 1.0);
assert_eq!(ramp.next_gain(), 1.0);
assert_eq!(ramp.current(), 0.0);
ramp.jump(0.5);
assert_eq!(ramp.current(), 0.5);
assert_eq!(ramp.next_gain(), 0.5);
}
#[test]
fn test_peak_limiter() {
let mut limiter = PeakLimiter::new(2, 44100, -1.0, 10.0, 100.0);
let mut samples = vec![0.0; 4096];
for i in 0..2048 {
samples[i * 2] = 1.5; samples[i * 2 + 1] = 1.5; }
limiter.process(&mut samples);
let max_out = samples.iter().map(|s| s.abs()).fold(0.0_f64, f64::max);
let threshold = db_to_linear(-1.0);
assert!(
max_out < threshold * 1.01,
"Max output {} exceeds threshold {}",
max_out,
threshold
);
}
#[test]
fn test_true_peak_detector() {
let mut detector = TruePeakDetector::new();
let samples: Vec<f64> = (0..100).map(|i| (i as f64 * 0.1).sin()).collect();
detector.process(&samples);
let max_sample = samples.iter().map(|s| s.abs()).fold(0.0_f64, f64::max);
assert!(detector.max_true_peak() >= max_sample * 0.99);
}
}