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_frame_count(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_sample_count(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 let ptr = frames_ptrs[i];
190 if ptr.is_null() {
191 return Err(Error::InvalidPacket);
192 }
193 let ptr_addr = ptr as usize;
194 let base_addr = packet.as_ptr() as usize;
195 if ptr_addr < base_addr {
196 return Err(Error::InvalidPacket);
197 }
198 let start = ptr_addr - base_addr;
200 let end = start + size;
201 if end > packet.len() {
202 return Err(Error::InvalidPacket);
203 }
204 frames.push(&packet[start..end]);
205 }
206 Ok((
207 out_toc,
208 usize::try_from(payload_offset).map_err(|_| Error::InternalError)?,
209 frames,
210 ))
211}
212
213pub fn packet_pad(packet: &mut [u8], len: usize, new_len: usize) -> Result<()> {
218 if new_len < len || new_len > packet.len() {
219 return Err(Error::BadArg);
220 }
221 let len_i32 = i32::try_from(len).map_err(|_| Error::BadArg)?;
222 let new_len_i32 = i32::try_from(new_len).map_err(|_| Error::BadArg)?;
223 let r = unsafe { opus_packet_pad(packet.as_mut_ptr(), len_i32, new_len_i32) };
224 if r != 0 {
225 return Err(Error::from_code(r));
226 }
227 Ok(())
228}
229
230pub fn packet_unpad(packet: &mut [u8], len: usize) -> Result<usize> {
235 if len > packet.len() {
236 return Err(Error::BadArg);
237 }
238 let len_i32 = i32::try_from(len).map_err(|_| Error::BadArg)?;
239 let n = unsafe { opus_packet_unpad(packet.as_mut_ptr(), len_i32) };
240 if n < 0 {
241 return Err(Error::from_code(n));
242 }
243 usize::try_from(n).map_err(|_| Error::InternalError)
244}
245
246pub fn multistream_packet_pad(
251 packet: &mut [u8],
252 len: usize,
253 new_len: usize,
254 nb_streams: i32,
255) -> Result<()> {
256 if new_len < len || new_len > packet.len() {
257 return Err(Error::BadArg);
258 }
259 let len_i32 = i32::try_from(len).map_err(|_| Error::BadArg)?;
260 let new_len_i32 = i32::try_from(new_len).map_err(|_| Error::BadArg)?;
261 let r = unsafe {
262 opus_multistream_packet_pad(packet.as_mut_ptr(), len_i32, new_len_i32, nb_streams)
263 };
264 if r != 0 {
265 return Err(Error::from_code(r));
266 }
267 Ok(())
268}
269
270pub fn multistream_packet_unpad(packet: &mut [u8], len: usize, nb_streams: i32) -> Result<usize> {
275 if len > packet.len() {
276 return Err(Error::BadArg);
277 }
278 let len_i32 = i32::try_from(len).map_err(|_| Error::BadArg)?;
279 let n = unsafe { opus_multistream_packet_unpad(packet.as_mut_ptr(), len_i32, nb_streams) };
280 if n < 0 {
281 return Err(Error::from_code(n));
282 }
283 usize::try_from(n).map_err(|_| Error::InternalError)
284}