1use crate::bindings::{
4 OPUS_BITRATE_MAX, OPUS_GET_BITRATE_REQUEST, OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST,
5 OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST,
6 OPUS_SET_BITRATE_REQUEST, OpusProjectionDecoder, OpusProjectionEncoder,
7 opus_projection_ambisonics_encoder_create, opus_projection_ambisonics_encoder_get_size,
8 opus_projection_ambisonics_encoder_init, opus_projection_decode, opus_projection_decode_float,
9 opus_projection_decoder_create, opus_projection_decoder_destroy,
10 opus_projection_decoder_get_size, opus_projection_decoder_init, opus_projection_encode,
11 opus_projection_encode_float, opus_projection_encoder_ctl, opus_projection_encoder_destroy,
12};
13use crate::constants::max_frame_samples_for;
14use crate::error::{Error, Result};
15use crate::types::{Application, Bitrate, SampleRate};
16use crate::{AlignedBuffer, Ownership, RawHandle};
17use std::marker::PhantomData;
18use std::num::NonZeroUsize;
19use std::ops::{Deref, DerefMut};
20use std::ptr::NonNull;
21
22pub struct ProjectionEncoder {
24 raw: RawHandle<OpusProjectionEncoder>,
25 sample_rate: SampleRate,
26 channels: u8,
27 streams: u8,
28 coupled_streams: u8,
29}
30
31unsafe impl Send for ProjectionEncoder {}
32unsafe impl Sync for ProjectionEncoder {}
33
34pub struct ProjectionEncoderRef<'a> {
36 inner: ProjectionEncoder,
37 _marker: PhantomData<&'a mut OpusProjectionEncoder>,
38}
39
40unsafe impl Send for ProjectionEncoderRef<'_> {}
41unsafe impl Sync for ProjectionEncoderRef<'_> {}
42
43impl ProjectionEncoder {
44 fn from_raw(
45 ptr: NonNull<OpusProjectionEncoder>,
46 sample_rate: SampleRate,
47 channels: u8,
48 streams: u8,
49 coupled_streams: u8,
50 ownership: Ownership,
51 ) -> Self {
52 Self {
53 raw: RawHandle::new(ptr, ownership, opus_projection_encoder_destroy),
54 sample_rate,
55 channels,
56 streams,
57 coupled_streams,
58 }
59 }
60
61 pub fn size(channels: u8, mapping_family: i32) -> Result<usize> {
66 let raw = unsafe {
67 opus_projection_ambisonics_encoder_get_size(i32::from(channels), mapping_family)
68 };
69 if raw <= 0 {
70 return Err(Error::BadArg);
71 }
72 usize::try_from(raw).map_err(|_| Error::InternalError)
73 }
74
75 pub unsafe fn init_in_place(
84 ptr: *mut OpusProjectionEncoder,
85 sample_rate: SampleRate,
86 channels: u8,
87 mapping_family: i32,
88 application: Application,
89 ) -> Result<(u8, u8)> {
90 if ptr.is_null() || channels == 0 {
91 return Err(Error::BadArg);
92 }
93 if !crate::opus_ptr_is_aligned(ptr.cast()) {
94 return Err(Error::BadArg);
95 }
96 let mut streams = 0i32;
97 let mut coupled = 0i32;
98 let r = unsafe {
99 opus_projection_ambisonics_encoder_init(
100 ptr,
101 sample_rate as i32,
102 i32::from(channels),
103 mapping_family,
104 std::ptr::addr_of_mut!(streams),
105 std::ptr::addr_of_mut!(coupled),
106 application as i32,
107 )
108 };
109 if r != 0 {
110 return Err(Error::from_code(r));
111 }
112 Ok((
113 u8::try_from(streams).map_err(|_| Error::BadArg)?,
114 u8::try_from(coupled).map_err(|_| Error::BadArg)?,
115 ))
116 }
117
118 pub fn new(
127 sample_rate: SampleRate,
128 channels: u8,
129 mapping_family: i32,
130 application: Application,
131 ) -> Result<Self> {
132 let mut err = 0i32;
133 let mut streams = 0i32;
134 let mut coupled = 0i32;
135 let enc = unsafe {
136 opus_projection_ambisonics_encoder_create(
137 sample_rate as i32,
138 i32::from(channels),
139 mapping_family,
140 &raw mut streams,
141 &raw mut coupled,
142 application as i32,
143 &raw mut err,
144 )
145 };
146 if err != 0 {
147 return Err(Error::from_code(err));
148 }
149 let enc = NonNull::new(enc).ok_or(Error::AllocFail)?;
150 let streams_u8 = u8::try_from(streams).map_err(|_| Error::BadArg)?;
151 let coupled_u8 = u8::try_from(coupled).map_err(|_| Error::BadArg)?;
152 Ok(Self::from_raw(
153 enc,
154 sample_rate,
155 channels,
156 streams_u8,
157 coupled_u8,
158 Ownership::Owned,
159 ))
160 }
161
162 fn validate_frame_size(&self, frame_size_per_ch: usize) -> Result<i32> {
163 let frame_size = NonZeroUsize::new(frame_size_per_ch).ok_or(Error::BadArg)?;
164 if frame_size.get() > max_frame_samples_for(self.sample_rate) {
165 return Err(Error::BadArg);
166 }
167 i32::try_from(frame_size.get()).map_err(|_| Error::BadArg)
168 }
169
170 fn ensure_pcm_layout(&self, len: usize, frame_size_per_ch: usize) -> Result<()> {
171 if len != frame_size_per_ch * self.channels as usize {
172 return Err(Error::BadArg);
173 }
174 Ok(())
175 }
176
177 pub fn encode(
184 &mut self,
185 pcm: &[i16],
186 frame_size_per_ch: usize,
187 out: &mut [u8],
188 ) -> Result<usize> {
189 if out.is_empty() || out.len() > i32::MAX as usize {
190 return Err(Error::BadArg);
191 }
192 self.ensure_pcm_layout(pcm.len(), frame_size_per_ch)?;
193 let frame_size = self.validate_frame_size(frame_size_per_ch)?;
194 let out_len = i32::try_from(out.len()).map_err(|_| Error::BadArg)?;
195 let n = unsafe {
196 opus_projection_encode(
197 self.raw.as_ptr(),
198 pcm.as_ptr(),
199 frame_size,
200 out.as_mut_ptr(),
201 out_len,
202 )
203 };
204 if n < 0 {
205 return Err(Error::from_code(n));
206 }
207 usize::try_from(n).map_err(|_| Error::InternalError)
208 }
209
210 pub fn encode_float(
217 &mut self,
218 pcm: &[f32],
219 frame_size_per_ch: usize,
220 out: &mut [u8],
221 ) -> Result<usize> {
222 if out.is_empty() || out.len() > i32::MAX as usize {
223 return Err(Error::BadArg);
224 }
225 self.ensure_pcm_layout(pcm.len(), frame_size_per_ch)?;
226 let frame_size = self.validate_frame_size(frame_size_per_ch)?;
227 let out_len = i32::try_from(out.len()).map_err(|_| Error::BadArg)?;
228 let n = unsafe {
229 opus_projection_encode_float(
230 self.raw.as_ptr(),
231 pcm.as_ptr(),
232 frame_size,
233 out.as_mut_ptr(),
234 out_len,
235 )
236 };
237 if n < 0 {
238 return Err(Error::from_code(n));
239 }
240 usize::try_from(n).map_err(|_| Error::InternalError)
241 }
242
243 pub fn set_bitrate(&mut self, bitrate: Bitrate) -> Result<()> {
248 self.simple_ctl(OPUS_SET_BITRATE_REQUEST as i32, bitrate.value())
249 }
250
251 pub fn bitrate(&mut self) -> Result<Bitrate> {
256 let v = self.get_int_ctl(OPUS_GET_BITRATE_REQUEST as i32)?;
257 Ok(match v {
258 x if x == crate::bindings::OPUS_AUTO => Bitrate::Auto,
259 x if x == OPUS_BITRATE_MAX => Bitrate::Max,
260 other => Bitrate::Custom(other),
261 })
262 }
263
264 pub fn demixing_matrix_size(&mut self) -> Result<i32> {
269 self.get_int_ctl(OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST as i32)
270 }
271
272 pub fn demixing_matrix_gain(&mut self) -> Result<i32> {
277 self.get_int_ctl(OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST as i32)
278 }
279
280 pub fn write_demixing_matrix(&mut self, out: &mut [u8]) -> Result<usize> {
287 let size = self.demixing_matrix_size()?;
288 if size <= 0 {
289 return Err(Error::InternalError);
290 }
291 let needed = usize::try_from(size).map_err(|_| Error::InternalError)?;
292 if out.len() < needed {
293 return Err(Error::BufferTooSmall);
294 }
295 let r = unsafe {
296 opus_projection_encoder_ctl(
297 self.raw.as_ptr(),
298 OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST as i32,
299 out.as_mut_ptr(),
300 size,
301 )
302 };
303 if r != 0 {
304 return Err(Error::from_code(r));
305 }
306 Ok(needed)
307 }
308
309 pub fn demixing_matrix_bytes(&mut self) -> Result<Vec<u8>> {
315 let size = self.demixing_matrix_size()?;
316 let len = usize::try_from(size).map_err(|_| Error::InternalError)?;
317 let mut buf = vec![0u8; len];
318 self.write_demixing_matrix(&mut buf)?;
319 Ok(buf)
320 }
321
322 #[must_use]
324 pub const fn streams(&self) -> u8 {
325 self.streams
326 }
327
328 #[must_use]
330 pub const fn coupled_streams(&self) -> u8 {
331 self.coupled_streams
332 }
333
334 #[must_use]
336 pub const fn channels(&self) -> u8 {
337 self.channels
338 }
339
340 #[must_use]
342 pub const fn sample_rate(&self) -> SampleRate {
343 self.sample_rate
344 }
345
346 fn simple_ctl(&mut self, req: i32, val: i32) -> Result<()> {
347 let r = unsafe { opus_projection_encoder_ctl(self.raw.as_ptr(), req, val) };
348 if r != 0 {
349 return Err(Error::from_code(r));
350 }
351 Ok(())
352 }
353
354 fn get_int_ctl(&mut self, req: i32) -> Result<i32> {
355 let mut v = 0i32;
356 let r = unsafe { opus_projection_encoder_ctl(self.raw.as_ptr(), req, &mut v) };
357 if r != 0 {
358 return Err(Error::from_code(r));
359 }
360 Ok(v)
361 }
362}
363
364impl<'a> ProjectionEncoderRef<'a> {
365 #[must_use]
375 pub unsafe fn from_raw(
376 ptr: *mut OpusProjectionEncoder,
377 sample_rate: SampleRate,
378 channels: u8,
379 streams: u8,
380 coupled_streams: u8,
381 ) -> Self {
382 debug_assert!(!ptr.is_null(), "from_raw called with null ptr");
383 debug_assert!(crate::opus_ptr_is_aligned(ptr.cast()));
384 let encoder = ProjectionEncoder::from_raw(
385 unsafe { NonNull::new_unchecked(ptr) },
386 sample_rate,
387 channels,
388 streams,
389 coupled_streams,
390 Ownership::Borrowed,
391 );
392 Self {
393 inner: encoder,
394 _marker: PhantomData,
395 }
396 }
397
398 pub fn init_in(
403 buf: &'a mut AlignedBuffer,
404 sample_rate: SampleRate,
405 channels: u8,
406 mapping_family: i32,
407 application: Application,
408 ) -> Result<Self> {
409 let required = ProjectionEncoder::size(channels, mapping_family)?;
410 if buf.capacity_bytes() < required {
411 return Err(Error::BadArg);
412 }
413 let ptr = buf.as_mut_ptr::<OpusProjectionEncoder>();
414 let (streams, coupled) = unsafe {
415 ProjectionEncoder::init_in_place(
416 ptr,
417 sample_rate,
418 channels,
419 mapping_family,
420 application,
421 )?
422 };
423 Ok(unsafe { Self::from_raw(ptr, sample_rate, channels, streams, coupled) })
424 }
425}
426
427impl Deref for ProjectionEncoderRef<'_> {
428 type Target = ProjectionEncoder;
429
430 fn deref(&self) -> &Self::Target {
431 &self.inner
432 }
433}
434
435impl DerefMut for ProjectionEncoderRef<'_> {
436 fn deref_mut(&mut self) -> &mut Self::Target {
437 &mut self.inner
438 }
439}
440
441pub struct ProjectionDecoder {
443 raw: RawHandle<OpusProjectionDecoder>,
444 sample_rate: SampleRate,
445 channels: u8,
446 streams: u8,
447 coupled_streams: u8,
448}
449
450unsafe impl Send for ProjectionDecoder {}
451unsafe impl Sync for ProjectionDecoder {}
452
453pub struct ProjectionDecoderRef<'a> {
455 inner: ProjectionDecoder,
456 _marker: PhantomData<&'a mut OpusProjectionDecoder>,
457}
458
459unsafe impl Send for ProjectionDecoderRef<'_> {}
460unsafe impl Sync for ProjectionDecoderRef<'_> {}
461
462impl ProjectionDecoder {
463 fn from_raw(
464 ptr: NonNull<OpusProjectionDecoder>,
465 sample_rate: SampleRate,
466 channels: u8,
467 streams: u8,
468 coupled_streams: u8,
469 ownership: Ownership,
470 ) -> Self {
471 Self {
472 raw: RawHandle::new(ptr, ownership, opus_projection_decoder_destroy),
473 sample_rate,
474 channels,
475 streams,
476 coupled_streams,
477 }
478 }
479
480 pub fn size(channels: u8, streams: u8, coupled_streams: u8) -> Result<usize> {
485 let raw = unsafe {
486 opus_projection_decoder_get_size(
487 i32::from(channels),
488 i32::from(streams),
489 i32::from(coupled_streams),
490 )
491 };
492 if raw <= 0 {
493 return Err(Error::BadArg);
494 }
495 usize::try_from(raw).map_err(|_| Error::InternalError)
496 }
497
498 pub unsafe fn init_in_place(
507 ptr: *mut OpusProjectionDecoder,
508 sample_rate: SampleRate,
509 channels: u8,
510 streams: u8,
511 coupled_streams: u8,
512 demixing_matrix: &[u8],
513 ) -> Result<()> {
514 if ptr.is_null() || demixing_matrix.is_empty() {
515 return Err(Error::BadArg);
516 }
517 if !crate::opus_ptr_is_aligned(ptr.cast()) {
518 return Err(Error::BadArg);
519 }
520 let matrix_len = i32::try_from(demixing_matrix.len()).map_err(|_| Error::BadArg)?;
521 let r = unsafe {
522 opus_projection_decoder_init(
523 ptr,
524 sample_rate as i32,
525 i32::from(channels),
526 i32::from(streams),
527 i32::from(coupled_streams),
528 demixing_matrix.as_ptr().cast_mut(),
529 matrix_len,
530 )
531 };
532 if r != 0 {
533 return Err(Error::from_code(r));
534 }
535 Ok(())
536 }
537
538 pub fn new(
544 sample_rate: SampleRate,
545 channels: u8,
546 streams: u8,
547 coupled_streams: u8,
548 demixing_matrix: &[u8],
549 ) -> Result<Self> {
550 if demixing_matrix.is_empty() {
551 return Err(Error::BadArg);
552 }
553 let matrix_len = i32::try_from(demixing_matrix.len()).map_err(|_| Error::BadArg)?;
554 let mut err = 0i32;
555 let dec = unsafe {
556 opus_projection_decoder_create(
557 sample_rate as i32,
558 i32::from(channels),
559 i32::from(streams),
560 i32::from(coupled_streams),
561 demixing_matrix.as_ptr().cast_mut(),
562 matrix_len,
563 &raw mut err,
564 )
565 };
566 if err != 0 {
567 return Err(Error::from_code(err));
568 }
569 let dec = NonNull::new(dec).ok_or(Error::AllocFail)?;
570 Ok(Self::from_raw(
571 dec,
572 sample_rate,
573 channels,
574 streams,
575 coupled_streams,
576 Ownership::Owned,
577 ))
578 }
579
580 fn validate_frame_size(&self, frame_size_per_ch: usize) -> Result<i32> {
581 let frame_size = NonZeroUsize::new(frame_size_per_ch).ok_or(Error::BadArg)?;
582 if frame_size.get() > max_frame_samples_for(self.sample_rate) {
583 return Err(Error::BadArg);
584 }
585 i32::try_from(frame_size.get()).map_err(|_| Error::BadArg)
586 }
587
588 fn ensure_output_layout(&self, len: usize, frame_size_per_ch: usize) -> Result<()> {
589 if len != frame_size_per_ch * self.channels as usize {
590 return Err(Error::BadArg);
591 }
592 Ok(())
593 }
594
595 pub fn decode(
602 &mut self,
603 packet: &[u8],
604 out: &mut [i16],
605 frame_size_per_ch: usize,
606 fec: bool,
607 ) -> Result<usize> {
608 self.ensure_output_layout(out.len(), frame_size_per_ch)?;
609 let frame_size = self.validate_frame_size(frame_size_per_ch)?;
610 let packet_len = if packet.is_empty() {
611 0
612 } else {
613 i32::try_from(packet.len()).map_err(|_| Error::BadArg)?
614 };
615 let n = unsafe {
616 opus_projection_decode(
617 self.raw.as_ptr(),
618 if packet.is_empty() {
619 std::ptr::null()
620 } else {
621 packet.as_ptr()
622 },
623 packet_len,
624 out.as_mut_ptr(),
625 frame_size,
626 i32::from(fec),
627 )
628 };
629 if n < 0 {
630 return Err(Error::from_code(n));
631 }
632 usize::try_from(n).map_err(|_| Error::InternalError)
633 }
634
635 pub fn decode_float(
642 &mut self,
643 packet: &[u8],
644 out: &mut [f32],
645 frame_size_per_ch: usize,
646 fec: bool,
647 ) -> Result<usize> {
648 self.ensure_output_layout(out.len(), frame_size_per_ch)?;
649 let frame_size = self.validate_frame_size(frame_size_per_ch)?;
650 let packet_len = if packet.is_empty() {
651 0
652 } else {
653 i32::try_from(packet.len()).map_err(|_| Error::BadArg)?
654 };
655 let n = unsafe {
656 opus_projection_decode_float(
657 self.raw.as_ptr(),
658 if packet.is_empty() {
659 std::ptr::null()
660 } else {
661 packet.as_ptr()
662 },
663 packet_len,
664 out.as_mut_ptr(),
665 frame_size,
666 i32::from(fec),
667 )
668 };
669 if n < 0 {
670 return Err(Error::from_code(n));
671 }
672 usize::try_from(n).map_err(|_| Error::InternalError)
673 }
674
675 #[must_use]
677 pub const fn channels(&self) -> u8 {
678 self.channels
679 }
680
681 #[must_use]
683 pub const fn streams(&self) -> u8 {
684 self.streams
685 }
686
687 #[must_use]
689 pub const fn coupled_streams(&self) -> u8 {
690 self.coupled_streams
691 }
692
693 #[must_use]
695 pub const fn sample_rate(&self) -> SampleRate {
696 self.sample_rate
697 }
698}
699
700impl<'a> ProjectionDecoderRef<'a> {
701 #[must_use]
711 pub unsafe fn from_raw(
712 ptr: *mut OpusProjectionDecoder,
713 sample_rate: SampleRate,
714 channels: u8,
715 streams: u8,
716 coupled_streams: u8,
717 ) -> Self {
718 debug_assert!(!ptr.is_null(), "from_raw called with null ptr");
719 debug_assert!(crate::opus_ptr_is_aligned(ptr.cast()));
720 let decoder = ProjectionDecoder::from_raw(
721 unsafe { NonNull::new_unchecked(ptr) },
722 sample_rate,
723 channels,
724 streams,
725 coupled_streams,
726 Ownership::Borrowed,
727 );
728 Self {
729 inner: decoder,
730 _marker: PhantomData,
731 }
732 }
733
734 pub fn init_in(
739 buf: &'a mut AlignedBuffer,
740 sample_rate: SampleRate,
741 channels: u8,
742 streams: u8,
743 coupled_streams: u8,
744 demixing_matrix: &[u8],
745 ) -> Result<Self> {
746 let required = ProjectionDecoder::size(channels, streams, coupled_streams)?;
747 if buf.capacity_bytes() < required {
748 return Err(Error::BadArg);
749 }
750 let ptr = buf.as_mut_ptr::<OpusProjectionDecoder>();
751 unsafe {
752 ProjectionDecoder::init_in_place(
753 ptr,
754 sample_rate,
755 channels,
756 streams,
757 coupled_streams,
758 demixing_matrix,
759 )?;
760 }
761 Ok(unsafe { Self::from_raw(ptr, sample_rate, channels, streams, coupled_streams) })
762 }
763}
764
765impl Deref for ProjectionDecoderRef<'_> {
766 type Target = ProjectionDecoder;
767
768 fn deref(&self) -> &Self::Target {
769 &self.inner
770 }
771}
772
773impl DerefMut for ProjectionDecoderRef<'_> {
774 fn deref_mut(&mut self) -> &mut Self::Target {
775 &mut self.inner
776 }
777}