use crate::core::{AudioError, AudioFrame, AudioResult, AudioSpec};
use crate::mic_sim::contracts::MicrophoneSimProcessor;
use crate::types::{AudioBlock, ProcessContext};
#[allow(dead_code)]
pub struct MicrophoneSimPipeline {
spec: AudioSpec,
frame_size: usize,
frame_index: u64,
processors: Vec<Box<dyn MicrophoneSimProcessor>>,
}
#[allow(dead_code)]
impl MicrophoneSimPipeline {
pub fn new(
spec: AudioSpec,
mut processors: Vec<Box<dyn MicrophoneSimProcessor>>,
) -> AudioResult<Self> {
let frame_size = (spec.sample_rate as usize / 100)
.max(160)
.next_power_of_two();
let prepare_ctx = ProcessContext {
spec,
frame_size,
frame_index: 0,
};
for processor in &mut processors {
let _ = processor.prepare_with_context(&prepare_ctx)?;
}
Ok(Self {
spec,
frame_size,
frame_index: 0,
processors,
})
}
pub fn process_frame(&mut self, frame: &mut AudioFrame) -> AudioResult<()> {
if frame.spec.sample_rate != self.spec.sample_rate
|| frame.spec.channels != self.spec.channels
{
return Err(AudioError::new(
"Microphone simulation received frame with unexpected spec",
));
}
let mut block = AudioBlock::new(std::mem::take(&mut frame.samples), frame.spec);
let ctx = ProcessContext {
spec: self.spec,
frame_size: self.frame_size,
frame_index: self.frame_index,
};
for processor in &mut self.processors {
processor.process_block(&mut block, &ctx)?;
}
self.frame_index += 1;
frame.samples = block.samples;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::core::AudioSpec;
use crate::mic_sim::contracts::MicrophoneSimProcessor;
struct MultiplyProcessor(f32);
impl MicrophoneSimProcessor for MultiplyProcessor {
fn name(&self) -> &'static str {
"multiply"
}
fn prepare(&mut self, _spec: AudioSpec) -> AudioResult<()> {
Ok(())
}
fn process(&mut self, frame: &mut AudioFrame) -> AudioResult<()> {
for sample in &mut frame.samples {
*sample *= self.0;
}
Ok(())
}
}
#[test]
fn microphone_sim_pipeline_processes_audio() {
let mut pipeline = MicrophoneSimPipeline::new(
AudioSpec {
sample_rate: 48_000,
channels: 1,
},
vec![Box::new(MultiplyProcessor(0.5))],
)
.unwrap();
let mut frame = AudioFrame {
samples: vec![0.8, -0.4],
spec: AudioSpec {
sample_rate: 48_000,
channels: 1,
},
};
pipeline.process_frame(&mut frame).unwrap();
assert_eq!(frame.samples, vec![0.4, -0.2]);
}
}