Skip to main content

audio_codec/
opus.rs

1use super::{Decoder, Encoder, PcmBuf, Sample};
2pub use opus_rs::Application as OpusApplication;
3use opus_rs::{Application, OpusDecoder as OpusDecoderRaw, OpusEncoder as OpusEncoderRaw};
4
5pub struct OpusDecoder {
6    decoder: OpusDecoderRaw,
7    sample_rate: u32,
8    channels: u16,
9    w_output_f32: Vec<f32>,
10    w_pcm_i16: Vec<i16>,
11}
12
13impl OpusDecoder {
14    /// Create a new Opus decoder instance
15    pub fn new(sample_rate: u32, channels: u16) -> Self {
16        let decoder = OpusDecoderRaw::new(sample_rate as i32, channels as usize)
17            .expect("Failed to create Opus decoder");
18
19        Self {
20            decoder,
21            sample_rate,
22            channels,
23            w_output_f32: Vec::new(),
24            w_pcm_i16: Vec::new(),
25        }
26    }
27
28    /// Create a default Opus decoder (48kHz, stereo)
29    pub fn new_default() -> Self {
30        Self::new(48000, 2)
31    }
32
33    pub fn decode_into(&mut self, data: &[u8], output: &mut [i16]) -> usize {
34        let channels = usize::from(self.channels);
35        if channels == 0 || data.is_empty() {
36            return 0;
37        }
38
39        // opus-rs currently handles up to 20ms frames reliably; use that as the decode frame size
40        let frame_size = (self.sample_rate as usize * 20) / 1000;
41        let max_samples = frame_size * channels;
42        if self.w_output_f32.len() < max_samples {
43            self.w_output_f32.resize(max_samples, 0.0);
44        }
45
46        match self
47            .decoder
48            .decode(data, frame_size, &mut self.w_output_f32[..max_samples])
49        {
50            Ok(len) => {
51                let total_samples = len * channels;
52                if total_samples == 0 {
53                    return 0;
54                }
55
56                if self.w_pcm_i16.len() < total_samples {
57                    self.w_pcm_i16.resize(total_samples, 0);
58                }
59
60                for i in 0..total_samples {
61                    self.w_pcm_i16[i] =
62                        (self.w_output_f32[i] * 32768.0).clamp(-32768.0, 32767.0) as i16;
63                }
64
65                let n = total_samples.min(output.len());
66                output[..n].copy_from_slice(&self.w_pcm_i16[..n]);
67                n
68            }
69            Err(_) => 0,
70        }
71    }
72}
73
74impl Decoder for OpusDecoder {
75    fn decode(&mut self, data: &[u8]) -> PcmBuf {
76        let channels = usize::from(self.channels);
77        if channels == 0 || data.is_empty() {
78            return Vec::new();
79        }
80
81        let frame_size = (self.sample_rate as usize * 20) / 1000;
82        let max_samples = frame_size * channels;
83        let mut pcm = vec![0i16; max_samples];
84        let n = self.decode_into(data, &mut pcm);
85        pcm.truncate(n);
86        pcm
87    }
88
89    fn sample_rate(&self) -> u32 {
90        self.sample_rate
91    }
92
93    fn channels(&self) -> u16 {
94        self.channels
95    }
96}
97
98pub struct OpusEncoder {
99    encoder: OpusEncoderRaw,
100    sample_rate: u32,
101    channels: u16,
102    w_input_f32: Vec<f32>,
103    w_packet: Vec<u8>,
104}
105
106impl OpusEncoder {
107    pub fn new_with_application(sample_rate: u32, channels: u16, application: Application) -> Self {
108        let encoder = OpusEncoderRaw::new(sample_rate as i32, channels as usize, application)
109            .expect("Failed to create Opus encoder");
110
111        Self {
112            encoder,
113            sample_rate,
114            channels,
115            w_input_f32: Vec::new(),
116            w_packet: vec![0u8; 1275],
117        }
118    }
119
120    /// Create a new Opus encoder instance.
121    ///
122    /// Keep backward-compatible defaults with pre-0.3.31 behavior:
123    /// - VoIP application
124    /// - caller can provide mono PCM even when encoder is configured as stereo;
125    ///   `encode()` duplicates mono samples to stereo.
126    pub fn new(sample_rate: u32, channels: u16) -> Self {
127        let mut enc = Self::new_with_application(sample_rate, channels, Application::Voip);
128        enc.encoder.bitrate_bps = if channels == 2 { 64000 } else { 48000 };
129        enc.encoder.complexity = 5;
130        enc.encoder.use_cbr = true;
131        enc
132    }
133
134    /// Create a default Opus encoder (48kHz, stereo)
135    pub fn new_default() -> Self {
136        Self::new(48000, 2)
137    }
138
139    /// Set the encoder bitrate in bits per second.
140    pub fn set_bitrate(&mut self, bitrate_bps: i32) {
141        self.encoder.bitrate_bps = bitrate_bps;
142    }
143
144    /// Set the encoder complexity (0-10).
145    pub fn set_complexity(&mut self, complexity: i32) {
146        self.encoder.complexity = complexity;
147    }
148
149    /// Enable or disable constant bitrate (CBR) mode.
150    pub fn set_cbr(&mut self, cbr: bool) {
151        self.encoder.use_cbr = cbr;
152    }
153
154    /// Encode into a caller-provided packet buffer.
155    ///
156    /// Returns `Some(bytes_written)` on success.
157    pub fn encode_into(&mut self, samples: &[Sample], output: &mut [u8]) -> Option<usize> {
158        let channels = usize::from(self.channels);
159        if samples.is_empty() || channels == 0 || samples.len() % channels != 0 {
160            return None;
161        }
162
163        let frame_size = samples.len() / channels;
164
165        if self.w_input_f32.len() < samples.len() {
166            self.w_input_f32.resize(samples.len(), 0.0);
167        }
168
169        for (dst, &s) in self.w_input_f32[..samples.len()]
170            .iter_mut()
171            .zip(samples.iter())
172        {
173            *dst = s as f32 / 32768.0;
174        }
175
176        self.encoder
177            .encode(&self.w_input_f32[..samples.len()], frame_size, output)
178            .ok()
179    }
180
181    fn encode_raw(&mut self, samples: &[Sample]) -> Vec<u8> {
182        let channels = usize::from(self.channels);
183        if samples.is_empty() || channels == 0 || samples.len() % channels != 0 {
184            return Vec::new();
185        }
186
187        let frame_size = samples.len() / channels;
188
189        if self.w_input_f32.len() < samples.len() {
190            self.w_input_f32.resize(samples.len(), 0.0);
191        }
192
193        for (dst, &s) in self.w_input_f32[..samples.len()]
194            .iter_mut()
195            .zip(samples.iter())
196        {
197            *dst = s as f32 / 32768.0;
198        }
199
200        match self.encoder.encode(
201            &self.w_input_f32[..samples.len()],
202            frame_size,
203            &mut self.w_packet,
204        ) {
205            Ok(len) => {
206                let mut out = Vec::with_capacity(len);
207                out.extend_from_slice(&self.w_packet[..len]);
208                out
209            }
210            Err(_) => Vec::new(),
211        }
212    }
213}
214
215impl Encoder for OpusEncoder {
216    fn encode(&mut self, samples: &[Sample]) -> Vec<u8> {
217        if self.channels == 2 {
218            let frame_20ms = (self.sample_rate as usize * 20) / 1000;
219            if samples.len() == frame_20ms {
220                let mut stereo_samples = Vec::with_capacity(samples.len() * 2);
221                for &sample in samples {
222                    stereo_samples.push(sample);
223                    stereo_samples.push(sample);
224                }
225                return self.encode_raw(&stereo_samples);
226            }
227        }
228        self.encode_raw(samples)
229    }
230
231    fn sample_rate(&self) -> u32 {
232        self.sample_rate
233    }
234
235    fn channels(&self) -> u16 {
236        self.channels
237    }
238}