Skip to main content

active_call/media/
denoiser.rs

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