active_call/media/
denoiser.rs

1use crate::media::{AudioFrame, PcmBuf, Sample, Samples, processor::Processor};
2use anyhow::Result;
3use audio_codec::Resampler;
4use nnnoiseless::DenoiseState;
5
6pub struct NoiseReducer {
7    resampler_target: Resampler,
8    resampler_source: Resampler,
9    denoiser: Box<DenoiseState<'static>>,
10}
11
12impl NoiseReducer {
13    pub fn new(input_sample_rate: usize) -> Self {
14        let resampler48k = Resampler::new(48000, input_sample_rate);
15        let resampler16k = Resampler::new(input_sample_rate, 48000 as usize);
16        let denoiser = DenoiseState::new();
17        Self {
18            resampler_target: resampler48k,
19            resampler_source: resampler16k,
20            denoiser,
21        }
22    }
23}
24unsafe impl Send for NoiseReducer {}
25unsafe impl Sync for NoiseReducer {}
26
27impl Processor for NoiseReducer {
28    fn process_frame(&mut self, frame: &mut AudioFrame) -> Result<()> {
29        // If empty frame, nothing to do
30        if frame.samples.is_empty() {
31            return Ok(());
32        }
33
34        let samples = match &frame.samples {
35            Samples::PCM { samples } => samples,
36            _ => return Ok(()),
37        };
38        let samples = self.resampler_source.resample(samples);
39        let input_size = samples.len();
40
41        let output_padding_size = input_size + DenoiseState::FRAME_SIZE;
42        let mut output_buf = vec![0.0; output_padding_size];
43        let input_f32: Vec<f32> = samples.iter().map(|&s| s.into()).collect();
44
45        let mut offset = 0;
46        let mut buf;
47
48        while offset < input_size {
49            let remaining_size = input_size - offset;
50            let chunk_len = remaining_size.min(DenoiseState::FRAME_SIZE);
51            let end_offset = offset + chunk_len;
52
53            let input_chunk = if chunk_len < DenoiseState::FRAME_SIZE {
54                buf = vec![0.0; DenoiseState::FRAME_SIZE];
55                buf[..chunk_len].copy_from_slice(&input_f32[offset..end_offset]);
56                &buf
57            } else {
58                &input_f32[offset..end_offset]
59            };
60
61            // Process the current frame
62            self.denoiser.process_frame(
63                &mut output_buf[offset..offset + DenoiseState::FRAME_SIZE],
64                &input_chunk,
65            );
66
67            offset += chunk_len;
68        }
69
70        let samples = output_buf[..input_size]
71            .iter()
72            .map(|&s| s as Sample)
73            .collect::<PcmBuf>();
74
75        frame.samples = Samples::PCM {
76            samples: self.resampler_target.resample(&samples),
77        };
78
79        Ok(())
80    }
81}