Skip to main content

gosuto_libwebrtc/native/
apm.rs

1// Copyright 2025 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use cxx::UniquePtr;
16use gosuto_webrtc_sys::apm::ffi as sys_apm;
17
18use crate::{RtcError, RtcErrorType};
19
20pub struct AudioProcessingModule {
21    sys_handle: UniquePtr<sys_apm::AudioProcessingModule>,
22}
23
24impl AudioProcessingModule {
25    pub fn new(
26        echo_canceller_enabled: bool,
27        gain_controller_enabled: bool,
28        high_pass_filter_enabled: bool,
29        noise_suppression_enabled: bool,
30    ) -> Self {
31        Self {
32            sys_handle: unsafe {
33                sys_apm::create_apm(
34                    echo_canceller_enabled,
35                    gain_controller_enabled,
36                    high_pass_filter_enabled,
37                    noise_suppression_enabled,
38                )
39            },
40        }
41    }
42
43    pub fn process_stream(
44        &mut self,
45        data: &mut [i16],
46        sample_rate: i32,
47        num_channels: i32,
48    ) -> Result<(), RtcError> {
49        let samples_per_10ms = (sample_rate as usize / 100) * num_channels as usize;
50        assert!(
51            data.len() % samples_per_10ms == 0 && data.len() >= samples_per_10ms,
52            "slice must have a multiple of 10ms worth of samples"
53        );
54
55        for chunk in data.chunks_mut(samples_per_10ms) {
56            if unsafe {
57                self.sys_handle.pin_mut().process_stream(
58                    chunk.as_mut_ptr(),
59                    chunk.len(),
60                    chunk.as_mut_ptr(),
61                    chunk.len(),
62                    sample_rate,
63                    num_channels,
64                )
65            } != 0
66            {
67                return Err(RtcError {
68                    error_type: RtcErrorType::Internal,
69                    message: "Failed to process stream".to_string(),
70                });
71            }
72        }
73
74        Ok(())
75    }
76
77    pub fn process_reverse_stream(
78        &mut self,
79        data: &mut [i16],
80        sample_rate: i32,
81        num_channels: i32,
82    ) -> Result<(), RtcError> {
83        let samples_per_10ms = (sample_rate as usize / 100) * num_channels as usize;
84        assert!(
85            data.len() % samples_per_10ms == 0 && data.len() >= samples_per_10ms,
86            "slice must have a multiple of 10ms worth of samples"
87        );
88
89        for chunk in data.chunks_mut(samples_per_10ms) {
90            if unsafe {
91                self.sys_handle.pin_mut().process_reverse_stream(
92                    chunk.as_mut_ptr(),
93                    chunk.len(),
94                    chunk.as_mut_ptr(),
95                    chunk.len(),
96                    sample_rate,
97                    num_channels,
98                )
99            } != 0
100            {
101                return Err(RtcError {
102                    error_type: RtcErrorType::Internal,
103                    message: "Failed to process reverse stream".to_string(),
104                });
105            }
106        }
107
108        Ok(())
109    }
110
111    pub fn set_stream_delay_ms(&mut self, delay_ms: i32) -> Result<(), RtcError> {
112        if self.sys_handle.pin_mut().set_stream_delay_ms(delay_ms) == 0 {
113            Ok(())
114        } else {
115            Err(RtcError {
116                error_type: RtcErrorType::Internal,
117                message: "Failed to set stream delay".to_string(),
118            })
119        }
120    }
121}