zk-audio 0.1.0

Audio processing library for voice recording and enhancement
Documentation
use crate::core::AudioResult;
use crate::mic_sim::contracts::MicrophoneSimProcessor;
use crate::mic_sim::core::MicrophoneSimConfig;
use crate::mic_sim::processors::{SaturationProcessor, VoicingContourProcessor};
use crate::mic_sim::voicing::voicing_for;

pub struct MicrophoneSimulatorFactory;

impl MicrophoneSimulatorFactory {
    pub fn new() -> Self {
        Self
    }

    pub fn build_processors(
        &self,
        config: MicrophoneSimConfig,
    ) -> AudioResult<Vec<Box<dyn MicrophoneSimProcessor>>> {
        let Some(model) = config.active_model() else {
            return Ok(Vec::new());
        };
        let Some(voicing) = voicing_for(model) else {
            return Ok(Vec::new());
        };

        Ok(vec![
            Box::new(VoicingContourProcessor::new(voicing)),
            Box::new(SaturationProcessor::new(voicing.saturation_amount)),
        ])
    }
}

impl Default for MicrophoneSimulatorFactory {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::mic_sim::MicrophoneSimModel;

    #[test]
    fn factory_returns_empty_chain_when_disabled() {
        let factory = MicrophoneSimulatorFactory::new();
        let processors = factory
            .build_processors(MicrophoneSimConfig::default())
            .unwrap();
        assert!(processors.is_empty());
    }

    #[test]
    fn factory_builds_u87_chain() {
        let factory = MicrophoneSimulatorFactory::new();
        let processors = factory
            .build_processors(MicrophoneSimConfig {
                enabled: true,
                model: MicrophoneSimModel::U87,
            })
            .unwrap();

        let names = processors
            .iter()
            .map(|processor| processor.name())
            .collect::<Vec<_>>();
        assert_eq!(names, vec!["voicing_contour", "saturation"]);
    }

    #[test]
    fn factory_builds_c414_xlii_chain() {
        let factory = MicrophoneSimulatorFactory::new();
        let processors = factory
            .build_processors(MicrophoneSimConfig {
                enabled: true,
                model: MicrophoneSimModel::C414Xlii,
            })
            .unwrap();

        let names = processors
            .iter()
            .map(|processor| processor.name())
            .collect::<Vec<_>>();
        assert_eq!(names, vec!["voicing_contour", "saturation"]);
    }

    #[test]
    fn factory_builds_tlm103_chain() {
        let factory = MicrophoneSimulatorFactory::new();
        let processors = factory
            .build_processors(MicrophoneSimConfig {
                enabled: true,
                model: MicrophoneSimModel::Tlm103,
            })
            .unwrap();

        let names = processors
            .iter()
            .map(|processor| processor.name())
            .collect::<Vec<_>>();
        assert_eq!(names, vec!["voicing_contour", "saturation"]);
    }

    #[test]
    fn factory_builds_sm7b_chain() {
        let factory = MicrophoneSimulatorFactory::new();
        let processors = factory
            .build_processors(MicrophoneSimConfig {
                enabled: true,
                model: MicrophoneSimModel::SM7B,
            })
            .unwrap();

        let names = processors
            .iter()
            .map(|processor| processor.name())
            .collect::<Vec<_>>();
        assert_eq!(names, vec!["voicing_contour", "saturation"]);
    }

    #[test]
    fn factory_builds_rca44_chain() {
        let factory = MicrophoneSimulatorFactory::new();
        let processors = factory
            .build_processors(MicrophoneSimConfig {
                enabled: true,
                model: MicrophoneSimModel::Rca44,
            })
            .unwrap();

        let names = processors
            .iter()
            .map(|processor| processor.name())
            .collect::<Vec<_>>();
        assert_eq!(names, vec!["voicing_contour", "saturation"]);
    }
}