1#![allow(clippy::cast_possible_truncation)]
4#![allow(clippy::cast_possible_wrap)]
5
6use crate::bindings::{
7 OPUS_BANDWIDTH_FULLBAND, OPUS_BANDWIDTH_MEDIUMBAND, OPUS_BANDWIDTH_NARROWBAND,
8 OPUS_BANDWIDTH_SUPERWIDEBAND, OPUS_BANDWIDTH_WIDEBAND, opus_multistream_packet_pad,
9 opus_multistream_packet_unpad, opus_packet_get_bandwidth, opus_packet_get_nb_channels,
10 opus_packet_get_nb_frames, opus_packet_get_nb_samples, opus_packet_get_samples_per_frame,
11 opus_packet_has_lbrr, opus_packet_pad, opus_packet_parse, opus_packet_unpad,
12 opus_pcm_soft_clip,
13};
14use crate::error::{Error, Result};
15use crate::types::{Bandwidth, Channels, SampleRate};
16
17pub fn packet_bandwidth(packet: &[u8]) -> Result<Bandwidth> {
22 if packet.is_empty() {
23 return Err(Error::BadArg);
24 }
25 let bw = unsafe { opus_packet_get_bandwidth(packet.as_ptr()) };
26 match bw {
27 x if x == OPUS_BANDWIDTH_NARROWBAND as i32 => Ok(Bandwidth::Narrowband),
28 x if x == OPUS_BANDWIDTH_MEDIUMBAND as i32 => Ok(Bandwidth::Mediumband),
29 x if x == OPUS_BANDWIDTH_WIDEBAND as i32 => Ok(Bandwidth::Wideband),
30 x if x == OPUS_BANDWIDTH_SUPERWIDEBAND as i32 => Ok(Bandwidth::SuperWideband),
31 x if x == OPUS_BANDWIDTH_FULLBAND as i32 => Ok(Bandwidth::Fullband),
32 _ => Err(Error::InvalidPacket),
33 }
34}
35
36pub fn packet_channels(packet: &[u8]) -> Result<Channels> {
41 if packet.is_empty() {
42 return Err(Error::BadArg);
43 }
44 let ch = unsafe { opus_packet_get_nb_channels(packet.as_ptr()) };
45 match ch {
46 1 => Ok(Channels::Mono),
47 2 => Ok(Channels::Stereo),
48 _ => Err(Error::InvalidPacket),
49 }
50}
51
52pub fn packet_nb_frames(packet: &[u8]) -> Result<usize> {
57 if packet.is_empty() {
58 return Err(Error::BadArg);
59 }
60 let len_i32 = i32::try_from(packet.len()).map_err(|_| Error::BadArg)?;
61 let n = unsafe { opus_packet_get_nb_frames(packet.as_ptr(), len_i32) };
62 if n < 0 {
63 return Err(Error::from_code(n));
64 }
65 usize::try_from(n).map_err(|_| Error::InternalError)
66}
67
68pub fn packet_nb_samples(packet: &[u8], sample_rate: SampleRate) -> Result<usize> {
73 if packet.is_empty() {
74 return Err(Error::BadArg);
75 }
76 let len_i32 = i32::try_from(packet.len()).map_err(|_| Error::BadArg)?;
77 let n = unsafe { opus_packet_get_nb_samples(packet.as_ptr(), len_i32, sample_rate.as_i32()) };
78 if n < 0 {
79 return Err(Error::from_code(n));
80 }
81 usize::try_from(n).map_err(|_| Error::InternalError)
82}
83
84pub fn packet_samples_per_frame(packet: &[u8], sample_rate: SampleRate) -> Result<usize> {
89 if packet.is_empty() {
90 return Err(Error::BadArg);
91 }
92 let n = unsafe { opus_packet_get_samples_per_frame(packet.as_ptr(), sample_rate.as_i32()) };
93 if n <= 0 {
94 return Err(Error::InvalidPacket);
95 }
96 usize::try_from(n).map_err(|_| Error::InternalError)
97}
98
99pub fn packet_has_lbrr(packet: &[u8]) -> Result<bool> {
104 if packet.is_empty() {
105 return Err(Error::BadArg);
106 }
107 let len_i32 = i32::try_from(packet.len()).map_err(|_| Error::BadArg)?;
108 let v = unsafe { opus_packet_has_lbrr(packet.as_ptr(), len_i32) };
109 if v < 0 {
110 return Err(Error::from_code(v));
111 }
112 Ok(v != 0)
113}
114
115pub fn soft_clip(
124 pcm: &mut [f32],
125 frame_size_per_ch: usize,
126 channels: i32,
127 softclip_mem: &mut [f32],
128) -> Result<()> {
129 if frame_size_per_ch == 0 {
130 return Err(Error::BadArg);
131 }
132 let channels_usize = usize::try_from(channels).map_err(|_| Error::BadArg)?;
133 if channels_usize == 0 {
134 return Err(Error::BadArg);
135 }
136 if softclip_mem.len() < channels_usize {
137 return Err(Error::BadArg);
138 }
139 let needed_samples = frame_size_per_ch
140 .checked_mul(channels_usize)
141 .ok_or(Error::BadArg)?;
142 if pcm.len() < needed_samples {
143 return Err(Error::BadArg);
144 }
145 let frame_i32 = i32::try_from(frame_size_per_ch).map_err(|_| Error::BadArg)?;
146 unsafe {
147 opus_pcm_soft_clip(
148 pcm.as_mut_ptr(),
149 frame_i32,
150 channels,
151 softclip_mem.as_mut_ptr(),
152 );
153 }
154 Ok(())
155}
156
157pub fn packet_parse(packet: &[u8]) -> Result<(u8, usize, Vec<&[u8]>)> {
163 if packet.is_empty() {
164 return Err(Error::BadArg);
165 }
166 let mut out_toc: u8 = 0;
167 let mut payload_offset: i32 = 0;
168 let mut frames_ptrs: [*const u8; 48] = [std::ptr::null(); 48];
170 let mut sizes: [i16; 48] = [0; 48];
171 let len_i32 = i32::try_from(packet.len()).map_err(|_| Error::BadArg)?;
172 let n = unsafe {
173 opus_packet_parse(
174 packet.as_ptr(),
175 len_i32,
176 &raw mut out_toc,
177 frames_ptrs.as_mut_ptr().cast::<*const u8>(),
178 sizes.as_mut_ptr(),
179 &raw mut payload_offset,
180 )
181 };
182 if n < 0 {
183 return Err(Error::from_code(n));
184 }
185 let count = usize::try_from(n).map_err(|_| Error::InternalError)?;
186 let mut frames = Vec::with_capacity(count);
187 for i in 0..count {
188 let size = usize::try_from(sizes[i]).map_err(|_| Error::InternalError)?;
189 if size == 0 {
190 continue;
191 }
192 let ptr = frames_ptrs[i];
193 if ptr.is_null() {
194 return Err(Error::InvalidPacket);
195 }
196 let ptr_addr = ptr as usize;
197 let base_addr = packet.as_ptr() as usize;
198 if ptr_addr < base_addr {
199 return Err(Error::InvalidPacket);
200 }
201 let start = ptr_addr - base_addr;
203 let end = start + size;
204 if end > packet.len() {
205 return Err(Error::InvalidPacket);
206 }
207 frames.push(&packet[start..end]);
208 }
209 Ok((
210 out_toc,
211 usize::try_from(payload_offset).map_err(|_| Error::InternalError)?,
212 frames,
213 ))
214}
215
216pub fn packet_pad(packet: &mut [u8], len: usize, new_len: usize) -> Result<()> {
221 if new_len < len || new_len > packet.len() {
222 return Err(Error::BadArg);
223 }
224 let len_i32 = i32::try_from(len).map_err(|_| Error::BadArg)?;
225 let new_len_i32 = i32::try_from(new_len).map_err(|_| Error::BadArg)?;
226 let r = unsafe { opus_packet_pad(packet.as_mut_ptr(), len_i32, new_len_i32) };
227 if r != 0 {
228 return Err(Error::from_code(r));
229 }
230 Ok(())
231}
232
233pub fn packet_unpad(packet: &mut [u8], len: usize) -> Result<usize> {
238 if len > packet.len() {
239 return Err(Error::BadArg);
240 }
241 let len_i32 = i32::try_from(len).map_err(|_| Error::BadArg)?;
242 let n = unsafe { opus_packet_unpad(packet.as_mut_ptr(), len_i32) };
243 if n < 0 {
244 return Err(Error::from_code(n));
245 }
246 usize::try_from(n).map_err(|_| Error::InternalError)
247}
248
249pub fn multistream_packet_pad(
254 packet: &mut [u8],
255 len: usize,
256 new_len: usize,
257 nb_streams: i32,
258) -> Result<()> {
259 if new_len < len || new_len > packet.len() {
260 return Err(Error::BadArg);
261 }
262 let len_i32 = i32::try_from(len).map_err(|_| Error::BadArg)?;
263 let new_len_i32 = i32::try_from(new_len).map_err(|_| Error::BadArg)?;
264 let r = unsafe {
265 opus_multistream_packet_pad(packet.as_mut_ptr(), len_i32, new_len_i32, nb_streams)
266 };
267 if r != 0 {
268 return Err(Error::from_code(r));
269 }
270 Ok(())
271}
272
273pub fn multistream_packet_unpad(packet: &mut [u8], len: usize, nb_streams: i32) -> Result<usize> {
278 if len > packet.len() {
279 return Err(Error::BadArg);
280 }
281 let len_i32 = i32::try_from(len).map_err(|_| Error::BadArg)?;
282 let n = unsafe { opus_multistream_packet_unpad(packet.as_mut_ptr(), len_i32, nb_streams) };
283 if n < 0 {
284 return Err(Error::from_code(n));
285 }
286 usize::try_from(n).map_err(|_| Error::InternalError)
287}