use crate::{AnalysisConfig, Result};
pub struct AuthenticityVerifier {
config: AnalysisConfig,
edit_detector: super::edit::EditDetector,
}
impl AuthenticityVerifier {
#[must_use]
pub fn new(config: AnalysisConfig) -> Self {
let edit_detector = super::edit::EditDetector::new(config.clone());
Self {
config,
edit_detector,
}
}
pub fn verify(&self, samples: &[f32], sample_rate: f32) -> Result<AuthenticityResult> {
let edit_result = self.edit_detector.detect(samples, sample_rate)?;
let compression = super::compression::detect_compression_history(samples, sample_rate);
let noise_analyzer = super::noise::NoiseAnalyzer::new(self.config.clone());
let noise_consistency = noise_analyzer.analyze_consistency(samples, sample_rate)?;
let mut authenticity_score = 1.0;
if edit_result.num_edits > 0 {
authenticity_score *= 1.0 - (edit_result.num_edits as f32 * 0.1).min(0.5);
}
if !noise_consistency.is_consistent {
authenticity_score *= 0.7;
}
if compression.num_compressions > 1 {
authenticity_score *= 0.8;
}
let is_authentic = authenticity_score > 0.7;
Ok(AuthenticityResult {
is_authentic,
authenticity_score,
detected_edits: edit_result.num_edits,
noise_consistent: noise_consistency.is_consistent,
compression_count: compression.num_compressions,
})
}
}
#[derive(Debug, Clone)]
pub struct AuthenticityResult {
pub is_authentic: bool,
pub authenticity_score: f32,
pub detected_edits: usize,
pub noise_consistent: bool,
pub compression_count: usize,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_authenticity_verifier() {
let config = AnalysisConfig::default();
let verifier = AuthenticityVerifier::new(config);
let sample_rate = 44100.0;
let samples: Vec<f32> = (0..44100)
.map(|i| (2.0 * std::f32::consts::PI * 440.0 * i as f32 / sample_rate).sin() * 0.3)
.collect();
let result = verifier.verify(&samples, sample_rate);
assert!(result.is_ok());
}
}