use crate::{AnalysisConfig, Result};
pub struct DistortionDetector {
#[allow(dead_code)]
config: AnalysisConfig,
}
impl DistortionDetector {
#[must_use]
pub fn new(config: AnalysisConfig) -> Self {
Self { config }
}
pub fn detect(&self, samples: &[f32], sample_rate: f32) -> Result<DistortionResult> {
let clipping = super::clipping::detect_clipping(samples, 0.99);
let thd = super::thd::total_harmonic_distortion(samples, sample_rate);
let distortion_score = (clipping.clipping_ratio * 0.5 + thd * 0.5).min(1.0);
Ok(DistortionResult {
has_distortion: distortion_score > 0.05,
distortion_score,
thd,
clipping_detected: clipping.has_clipping,
})
}
}
#[derive(Debug, Clone)]
pub struct DistortionResult {
pub has_distortion: bool,
pub distortion_score: f32,
pub thd: f32,
pub clipping_detected: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_distortion_detector() {
let config = AnalysisConfig::default();
let detector = DistortionDetector::new(config);
let sample_rate = 44100.0;
let samples: Vec<f32> = (0..4096)
.map(|i| (2.0 * std::f32::consts::PI * 440.0 * i as f32 / sample_rate).sin() * 0.5)
.collect();
let result = detector
.detect(&samples, sample_rate)
.expect("detection should succeed");
assert!(!result.has_distortion || result.distortion_score < 0.1);
}
}