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