Skip to main content

oporus/
opus_multistream.rs

1//! Channel layout helpers mirrored from `opus_multistream.c`.
2#![cfg_attr(not(test), allow(dead_code))]
3
4use alloc::vec;
5use alloc::vec::Vec;
6
7use crate::celt::{CELT_SIG_SCALE, OpusRes, float2int, float2int16, isqrt32};
8use crate::opus_decoder::{
9    OpusDecodeError, OpusDecoder, OpusDecoderCtlError, OpusDecoderCtlRequest, OpusDecoderInitError,
10    opus_decode_native, opus_decoder_create, opus_decoder_ctl, opus_decoder_get_size,
11};
12use crate::opus_encoder::{
13    OPUS_FRAMESIZE_ARG, OpusEncodeError, OpusEncodeOptions, OpusEncoder, OpusEncoderCtlError,
14    OpusEncoderCtlRequest, OpusEncoderInitError, opus_encode_with_options, opus_encoder_create,
15    opus_encoder_ctl, opus_encoder_get_size,
16};
17use crate::packet::{PacketError, opus_packet_get_nb_samples, opus_packet_parse_impl};
18
19/// Sentinel used by the reference encoder when auto-selecting the bitrate.
20pub(crate) const OPUS_AUTO: i32 = -1000;
21/// Maximum bitrate marker mirrored from the public Opus defines.
22pub(crate) const OPUS_BITRATE_MAX: i32 = -1;
23
24/// Mirrors the mapping type enum embedded in the multistream encoder state.
25#[allow(dead_code)]
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub(crate) enum MappingType {
28    None,
29    Surround,
30    Ambisonics,
31}
32
33/// Internal multistream channel layout description.
34///
35/// Mirrors the layout prefix embedded in the multistream encoder/decoder
36/// states. The `mapping` table uses `255` as a sentinel for channels that are
37/// omitted from the encoded streams.
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub struct ChannelLayout {
40    pub nb_channels: usize,
41    pub nb_streams: usize,
42    pub nb_coupled_streams: usize,
43    pub mapping: [u8; 256],
44}
45
46/// Errors surfaced by the multistream decoder front-end.
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub enum OpusMultistreamDecoderError {
49    BadArgument,
50    BufferTooSmall,
51    InternalError,
52    InvalidPacket,
53    Unimplemented,
54    DecoderInit(OpusDecoderInitError),
55    DecoderCtl(OpusDecoderCtlError),
56    DecoderDecode(OpusDecodeError),
57}
58
59impl OpusMultistreamDecoderError {
60    #[inline]
61    pub const fn code(&self) -> i32 {
62        match self {
63            Self::BadArgument => -1,
64            Self::BufferTooSmall => -2,
65            Self::InternalError => -3,
66            Self::InvalidPacket => -4,
67            Self::Unimplemented => -5,
68            Self::DecoderInit(OpusDecoderInitError::BadArgument) => -1,
69            Self::DecoderInit(_) => -3,
70            Self::DecoderCtl(OpusDecoderCtlError::BadArgument) => -1,
71            Self::DecoderCtl(OpusDecoderCtlError::Unimplemented) => -5,
72            Self::DecoderCtl(OpusDecoderCtlError::Silk(_)) => -3,
73            Self::DecoderDecode(err) => err.code(),
74        }
75    }
76}
77
78impl From<PacketError> for OpusMultistreamDecoderError {
79    #[inline]
80    fn from(value: PacketError) -> Self {
81        match value {
82            PacketError::BadArgument => Self::BadArgument,
83            PacketError::InvalidPacket => Self::InvalidPacket,
84        }
85    }
86}
87
88impl From<OpusDecoderInitError> for OpusMultistreamDecoderError {
89    #[inline]
90    fn from(value: OpusDecoderInitError) -> Self {
91        Self::DecoderInit(value)
92    }
93}
94
95impl From<OpusDecoderCtlError> for OpusMultistreamDecoderError {
96    #[inline]
97    fn from(value: OpusDecoderCtlError) -> Self {
98        Self::DecoderCtl(value)
99    }
100}
101
102impl From<OpusDecodeError> for OpusMultistreamDecoderError {
103    #[inline]
104    fn from(value: OpusDecodeError) -> Self {
105        Self::DecoderDecode(value)
106    }
107}
108
109#[repr(C)]
110struct ChannelLayoutLayout {
111    nb_channels: i32,
112    nb_streams: i32,
113    nb_coupled_streams: i32,
114    mapping: [u8; 256],
115}
116
117#[repr(C)]
118struct OpusMsDecoderLayout {
119    layout: ChannelLayoutLayout,
120}
121
122#[repr(C)]
123struct OpusMsEncoderLayout {
124    layout: ChannelLayoutLayout,
125}
126
127/// Mirrors the alignment helper from `opus_private.h`.
128#[inline]
129fn align(value: usize) -> usize {
130    #[repr(C)]
131    struct AlignProbe {
132        _tag: u8,
133        _union: AlignUnion,
134    }
135
136    #[repr(C)]
137    union AlignUnion {
138        _ptr: *const (),
139        _i32: i32,
140        _f32: f32,
141    }
142
143    let alignment = core::mem::align_of::<AlignProbe>();
144    value.div_ceil(alignment) * alignment
145}
146
147/// Returns the number of bytes required to allocate a multistream decoder.
148#[must_use]
149pub fn opus_multistream_decoder_get_size(
150    nb_streams: usize,
151    nb_coupled_streams: usize,
152) -> Option<usize> {
153    if nb_streams == 0 || nb_coupled_streams > nb_streams {
154        return None;
155    }
156
157    let coupled_size = opus_decoder_get_size(2)?;
158    let mono_size = opus_decoder_get_size(1)?;
159    let header_size = align(core::mem::size_of::<OpusMsDecoderLayout>());
160
161    let coupled_total = nb_coupled_streams.checked_mul(align(coupled_size))?;
162    let mono_total = nb_streams
163        .checked_sub(nb_coupled_streams)?
164        .checked_mul(align(mono_size))?;
165
166    header_size
167        .checked_add(coupled_total)?
168        .checked_add(mono_total)
169}
170
171/// Multistream decoder state mirroring `OpusMSDecoder` from the reference code.
172#[derive(Debug)]
173pub struct OpusMultistreamDecoder<'mode> {
174    layout: ChannelLayout,
175    decoders: Vec<OpusDecoder<'mode>>,
176}
177
178impl<'mode> OpusMultistreamDecoder<'mode> {
179    #[inline]
180    pub fn layout(&self) -> &ChannelLayout {
181        &self.layout
182    }
183
184    #[inline]
185    fn sample_rate(&self) -> Option<i32> {
186        self.decoders.first().map(|decoder| decoder.fs)
187    }
188
189    /// Resets the decoder to a new layout and sample rate.
190    pub fn init(
191        &mut self,
192        sample_rate: i32,
193        channels: usize,
194        streams: usize,
195        coupled_streams: usize,
196        mapping: &[u8],
197    ) -> Result<(), OpusMultistreamDecoderError> {
198        let layout = build_layout(channels, streams, coupled_streams, mapping)?;
199        let decoders = build_stream_decoders(sample_rate, streams, coupled_streams)?;
200
201        self.layout = layout;
202        self.decoders = decoders;
203        Ok(())
204    }
205
206    /// Returns a mutable reference to the decoder for `stream_id`, mirroring
207    /// `OPUS_MULTISTREAM_GET_DECODER_STATE`.
208    pub fn decoder_state(&mut self, stream_id: usize) -> Option<&mut OpusDecoder<'mode>> {
209        self.decoders.get_mut(stream_id)
210    }
211}
212
213/// Mirrors `opus_multistream_decoder_create` by allocating and initialising all
214/// component decoders.
215pub fn opus_multistream_decoder_create(
216    sample_rate: i32,
217    channels: usize,
218    streams: usize,
219    coupled_streams: usize,
220    mapping: &[u8],
221) -> Result<OpusMultistreamDecoder<'static>, OpusMultistreamDecoderError> {
222    let layout = build_layout(channels, streams, coupled_streams, mapping)?;
223    let decoders = build_stream_decoders(sample_rate, streams, coupled_streams)?;
224
225    Ok(OpusMultistreamDecoder { layout, decoders })
226}
227
228/// Mirrors `opus_multistream_decoder_init` by resetting an existing decoder instance.
229pub fn opus_multistream_decoder_init(
230    decoder: &mut OpusMultistreamDecoder<'_>,
231    sample_rate: i32,
232    channels: usize,
233    streams: usize,
234    coupled_streams: usize,
235    mapping: &[u8],
236) -> Result<(), OpusMultistreamDecoderError> {
237    decoder.init(sample_rate, channels, streams, coupled_streams, mapping)
238}
239
240fn build_layout(
241    channels: usize,
242    streams: usize,
243    coupled_streams: usize,
244    mapping: &[u8],
245) -> Result<ChannelLayout, OpusMultistreamDecoderError> {
246    if channels == 0
247        || channels > 255
248        || coupled_streams > streams
249        || streams == 0
250        || streams > 255 - coupled_streams
251    {
252        return Err(OpusMultistreamDecoderError::BadArgument);
253    }
254
255    if mapping.len() < channels {
256        return Err(OpusMultistreamDecoderError::BadArgument);
257    }
258
259    let mut layout = ChannelLayout {
260        nb_channels: channels,
261        nb_streams: streams,
262        nb_coupled_streams: coupled_streams,
263        mapping: [u8::MAX; 256],
264    };
265    layout.mapping[..channels].copy_from_slice(&mapping[..channels]);
266    if !validate_layout(&layout) {
267        return Err(OpusMultistreamDecoderError::BadArgument);
268    }
269
270    Ok(layout)
271}
272
273fn build_stream_decoders(
274    sample_rate: i32,
275    streams: usize,
276    coupled_streams: usize,
277) -> Result<Vec<OpusDecoder<'static>>, OpusMultistreamDecoderError> {
278    if sample_rate <= 0 {
279        return Err(OpusMultistreamDecoderError::BadArgument);
280    }
281
282    let mut decoders = Vec::with_capacity(streams);
283    for stream in 0..streams {
284        let channels: i32 = if stream < coupled_streams { 2 } else { 1 };
285        decoders.push(opus_decoder_create(sample_rate, channels)?);
286    }
287
288    Ok(decoders)
289}
290
291#[allow(dead_code)]
292#[derive(Debug, Clone, Copy, PartialEq, Eq)]
293struct VorbisLayout {
294    nb_streams: usize,
295    nb_coupled_streams: usize,
296    mapping: [u8; 8],
297}
298
299/* Index is nb_channel-1 */
300#[allow(dead_code)]
301const VORBIS_MAPPINGS: [VorbisLayout; 8] = [
302    VorbisLayout {
303        nb_streams: 1,
304        nb_coupled_streams: 0,
305        mapping: [0, 255, 255, 255, 255, 255, 255, 255],
306    }, /* 1: mono */
307    VorbisLayout {
308        nb_streams: 1,
309        nb_coupled_streams: 1,
310        mapping: [0, 1, 255, 255, 255, 255, 255, 255],
311    }, /* 2: stereo */
312    VorbisLayout {
313        nb_streams: 2,
314        nb_coupled_streams: 1,
315        mapping: [0, 2, 1, 255, 255, 255, 255, 255],
316    }, /* 3: 1-d surround */
317    VorbisLayout {
318        nb_streams: 2,
319        nb_coupled_streams: 2,
320        mapping: [0, 1, 2, 3, 255, 255, 255, 255],
321    }, /* 4: quadraphonic surround */
322    VorbisLayout {
323        nb_streams: 3,
324        nb_coupled_streams: 2,
325        mapping: [0, 4, 1, 2, 3, 255, 255, 255],
326    }, /* 5: 5-channel surround */
327    VorbisLayout {
328        nb_streams: 4,
329        nb_coupled_streams: 2,
330        mapping: [0, 4, 1, 2, 3, 5, 255, 255],
331    }, /* 6: 5.1 surround */
332    VorbisLayout {
333        nb_streams: 4,
334        nb_coupled_streams: 3,
335        mapping: [0, 4, 1, 2, 3, 5, 6, 255],
336    }, /* 7: 6.1 surround */
337    VorbisLayout {
338        nb_streams: 5,
339        nb_coupled_streams: 3,
340        mapping: [0, 6, 1, 2, 3, 4, 5, 7],
341    }, /* 8: 7.1 surround */
342];
343
344/// Verifies that the layout only references stream indices that exist.
345#[must_use]
346pub(crate) fn validate_layout(layout: &ChannelLayout) -> bool {
347    let Some(max_channel) = layout.nb_streams.checked_add(layout.nb_coupled_streams) else {
348        return false;
349    };
350
351    if max_channel > u8::MAX as usize {
352        return false;
353    }
354
355    if layout.nb_channels > layout.mapping.len() {
356        return false;
357    }
358
359    layout
360        .mapping
361        .iter()
362        .take(layout.nb_channels)
363        .all(|&value| value == u8::MAX || usize::from(value) < max_channel)
364}
365
366/// Ensures each stream in the layout has a channel mapping.
367#[must_use]
368pub(crate) fn validate_encoder_layout(layout: &ChannelLayout) -> bool {
369    for stream in 0..layout.nb_streams {
370        if stream < layout.nb_coupled_streams {
371            if get_left_channel(layout, stream, None).is_none() {
372                return false;
373            }
374            if get_right_channel(layout, stream, None).is_none() {
375                return false;
376            }
377        } else if get_mono_channel(layout, stream, None).is_none() {
378            return false;
379        }
380    }
381
382    true
383}
384
385/// Validates the ambisonics channel count and returns the derived stream layout.
386#[must_use]
387pub(crate) fn validate_ambisonics(channels: usize) -> Option<(usize, usize)> {
388    if !(1..=227).contains(&channels) {
389        return None;
390    }
391
392    let order_plus_one = isqrt32(channels as u32) as usize;
393    let acn_channels = order_plus_one.checked_mul(order_plus_one)?;
394    let nondiegetic_channels = channels.checked_sub(acn_channels)?;
395
396    if nondiegetic_channels != 0 && nondiegetic_channels != 2 {
397        return None;
398    }
399
400    let streams = acn_channels + usize::from(nondiegetic_channels != 0);
401    let coupled_streams = usize::from(nondiegetic_channels != 0);
402    Some((streams, coupled_streams))
403}
404
405fn surround_rate_allocation(
406    layout: &ChannelLayout,
407    bitrate_bps: i32,
408    lfe_stream: Option<usize>,
409    frame_size: usize,
410    sample_rate: i32,
411    rates: &mut [i32],
412) -> Option<()> {
413    let nb_streams = layout.nb_streams;
414    let nb_coupled = layout.nb_coupled_streams;
415    let nb_lfe = usize::from(lfe_stream.is_some());
416    if nb_streams == 0 || nb_coupled > nb_streams || nb_streams < nb_coupled + nb_lfe {
417        return None;
418    }
419    if frame_size == 0 || sample_rate <= 0 {
420        return None;
421    }
422    if rates.len() < nb_streams {
423        return None;
424    }
425
426    let nb_uncoupled = nb_streams - nb_coupled - nb_lfe;
427    let nb_normal = 2 * nb_coupled + nb_uncoupled;
428    if nb_normal == 0 {
429        return None;
430    }
431
432    let frame_rate = sample_rate / frame_size as i32;
433    let channel_offset = 40 * frame_rate.max(50);
434    let bitrate = if bitrate_bps == OPUS_AUTO {
435        nb_normal as i32 * (channel_offset + sample_rate + 10_000) + 8000 * nb_lfe as i32
436    } else if bitrate_bps == OPUS_BITRATE_MAX {
437        nb_normal as i32 * 300_000 + nb_lfe as i32 * 128_000
438    } else {
439        bitrate_bps
440    };
441
442    let lfe_offset = bitrate
443        .checked_div(20)
444        .map(|value| value.min(3000))
445        .and_then(|value| value.checked_add(15 * frame_rate.max(50)))?;
446    let stream_offset =
447        (((bitrate - channel_offset * nb_normal as i32 - lfe_offset * nb_lfe as i32)
448            / nb_normal as i32)
449            / 2)
450        .clamp(0, 20_000);
451    let coupled_ratio = 512;
452    let lfe_ratio = 32;
453
454    let total = ((nb_uncoupled as i32) << 8)
455        + coupled_ratio * nb_coupled as i32
456        + lfe_ratio * nb_lfe as i32;
457    if total == 0 {
458        return None;
459    }
460    let channel_rate = 256
461        * (bitrate
462            - lfe_offset * nb_lfe as i32
463            - stream_offset * (nb_coupled as i32 + nb_uncoupled as i32)
464            - channel_offset * nb_normal as i32)
465        / total;
466
467    for (stream, slot) in rates.iter_mut().take(nb_streams).enumerate() {
468        let value = if stream < nb_coupled {
469            2 * channel_offset + (stream_offset + ((channel_rate * coupled_ratio) >> 8)).max(0)
470        } else if lfe_stream == Some(stream) {
471            (lfe_offset + ((channel_rate * lfe_ratio) >> 8)).max(0)
472        } else {
473            channel_offset + (stream_offset + channel_rate).max(0)
474        };
475        *slot = value;
476    }
477
478    Some(())
479}
480
481fn ambisonics_rate_allocation(
482    layout: &ChannelLayout,
483    bitrate_bps: i32,
484    frame_size: usize,
485    sample_rate: i32,
486    rates: &mut [i32],
487) -> Option<()> {
488    if frame_size == 0 || sample_rate <= 0 || layout.nb_streams == 0 {
489        return None;
490    }
491    if rates.len() < layout.nb_streams {
492        return None;
493    }
494
495    let nb_channels = layout.nb_streams + layout.nb_coupled_streams;
496    let total_rate = if bitrate_bps == OPUS_AUTO {
497        let term = sample_rate + 60 * sample_rate / frame_size as i32;
498        (layout.nb_coupled_streams + layout.nb_streams) as i32 * term
499            + layout.nb_streams as i32 * 15_000
500    } else if bitrate_bps == OPUS_BITRATE_MAX {
501        nb_channels as i32 * 320_000
502    } else {
503        bitrate_bps
504    };
505
506    let per_stream_rate = total_rate / layout.nb_streams as i32;
507    for slot in rates.iter_mut().take(layout.nb_streams) {
508        *slot = per_stream_rate;
509    }
510
511    Some(())
512}
513
514/// Computes the bitrate distribution across all streams.
515#[must_use]
516pub(crate) fn rate_allocation(
517    layout: &ChannelLayout,
518    mapping_type: MappingType,
519    bitrate_bps: i32,
520    lfe_stream: Option<usize>,
521    frame_size: usize,
522    sample_rate: i32,
523    rates: &mut [i32],
524) -> Option<i32> {
525    match mapping_type {
526        MappingType::Ambisonics => {
527            ambisonics_rate_allocation(layout, bitrate_bps, frame_size, sample_rate, rates)?
528        }
529        _ => surround_rate_allocation(
530            layout,
531            bitrate_bps,
532            lfe_stream,
533            frame_size,
534            sample_rate,
535            rates,
536        )?,
537    }
538
539    let mut sum = 0i64;
540    for rate in rates.iter_mut().take(layout.nb_streams) {
541        *rate = (*rate).max(500);
542        sum += i64::from(*rate);
543    }
544
545    i32::try_from(sum).ok()
546}
547
548fn next_index(prev: Option<usize>) -> Option<usize> {
549    match prev {
550        Some(idx) => idx.checked_add(1),
551        None => Some(0),
552    }
553}
554
555fn find_channel(layout: &ChannelLayout, start: usize, target: usize) -> Option<usize> {
556    let limit = layout.nb_channels.min(layout.mapping.len());
557    (start..limit).find(|&i| usize::from(layout.mapping[i]) == target)
558}
559
560/// Returns the next channel mapped to the left slot of `stream_id`.
561#[must_use]
562pub(crate) fn get_left_channel(
563    layout: &ChannelLayout,
564    stream_id: usize,
565    prev: Option<usize>,
566) -> Option<usize> {
567    let target = stream_id.checked_mul(2)?;
568    let start = next_index(prev)?;
569    find_channel(layout, start, target)
570}
571
572/// Returns the next channel mapped to the right slot of `stream_id`.
573#[must_use]
574pub(crate) fn get_right_channel(
575    layout: &ChannelLayout,
576    stream_id: usize,
577    prev: Option<usize>,
578) -> Option<usize> {
579    let target = stream_id.checked_mul(2)?.checked_add(1)?;
580    let start = next_index(prev)?;
581    find_channel(layout, start, target)
582}
583
584/// Returns the next channel mapped to the mono stream `stream_id`.
585#[must_use]
586pub(crate) fn get_mono_channel(
587    layout: &ChannelLayout,
588    stream_id: usize,
589    prev: Option<usize>,
590) -> Option<usize> {
591    let target = stream_id.checked_add(layout.nb_coupled_streams)?;
592    let start = next_index(prev)?;
593    find_channel(layout, start, target)
594}
595
596/// Strongly-typed replacement for the multistream decoder CTL dispatcher.
597pub enum OpusMultistreamDecoderCtlRequest<'req> {
598    SetGain(i32),
599    GetGain(&'req mut i32),
600    SetComplexity(i32),
601    GetComplexity(&'req mut i32),
602    GetBandwidth(&'req mut i32),
603    GetSampleRate(&'req mut i32),
604    GetFinalRange(&'req mut u32),
605    ResetState,
606    GetLastPacketDuration(&'req mut i32),
607    SetPhaseInversionDisabled(bool),
608    GetPhaseInversionDisabled(&'req mut bool),
609    SetDnnBlob(&'req [u8]),
610}
611
612/// Applies a control request across the embedded decoders.
613pub fn opus_multistream_decoder_ctl<'req>(
614    decoder: &mut OpusMultistreamDecoder<'_>,
615    request: OpusMultistreamDecoderCtlRequest<'req>,
616) -> Result<(), OpusMultistreamDecoderError> {
617    if decoder.decoders.is_empty() {
618        return Err(OpusMultistreamDecoderError::InternalError);
619    }
620
621    match request {
622        OpusMultistreamDecoderCtlRequest::SetGain(value) => {
623            for dec in &mut decoder.decoders {
624                opus_decoder_ctl(dec, OpusDecoderCtlRequest::SetGain(value))?;
625            }
626        }
627        OpusMultistreamDecoderCtlRequest::GetGain(slot) => {
628            opus_decoder_ctl(
629                decoder
630                    .decoders
631                    .first_mut()
632                    .ok_or(OpusMultistreamDecoderError::InternalError)?,
633                OpusDecoderCtlRequest::GetGain(slot),
634            )?;
635        }
636        OpusMultistreamDecoderCtlRequest::SetComplexity(value) => {
637            for dec in &mut decoder.decoders {
638                opus_decoder_ctl(dec, OpusDecoderCtlRequest::SetComplexity(value))?;
639            }
640        }
641        OpusMultistreamDecoderCtlRequest::GetComplexity(slot) => {
642            opus_decoder_ctl(
643                decoder
644                    .decoders
645                    .first_mut()
646                    .ok_or(OpusMultistreamDecoderError::InternalError)?,
647                OpusDecoderCtlRequest::GetComplexity(slot),
648            )?;
649        }
650        OpusMultistreamDecoderCtlRequest::GetBandwidth(slot) => {
651            opus_decoder_ctl(
652                decoder
653                    .decoders
654                    .first_mut()
655                    .ok_or(OpusMultistreamDecoderError::InternalError)?,
656                OpusDecoderCtlRequest::GetBandwidth(slot),
657            )?;
658        }
659        OpusMultistreamDecoderCtlRequest::GetSampleRate(slot) => {
660            opus_decoder_ctl(
661                decoder
662                    .decoders
663                    .first_mut()
664                    .ok_or(OpusMultistreamDecoderError::InternalError)?,
665                OpusDecoderCtlRequest::GetSampleRate(slot),
666            )?;
667        }
668        OpusMultistreamDecoderCtlRequest::GetFinalRange(slot) => {
669            let mut acc = 0u32;
670            for dec in &mut decoder.decoders {
671                let mut value = 0u32;
672                opus_decoder_ctl(dec, OpusDecoderCtlRequest::GetFinalRange(&mut value))?;
673                acc ^= value;
674            }
675            *slot = acc;
676        }
677        OpusMultistreamDecoderCtlRequest::ResetState => {
678            for dec in &mut decoder.decoders {
679                opus_decoder_ctl(dec, OpusDecoderCtlRequest::ResetState)?;
680            }
681        }
682        OpusMultistreamDecoderCtlRequest::GetLastPacketDuration(slot) => {
683            opus_decoder_ctl(
684                decoder
685                    .decoders
686                    .first_mut()
687                    .ok_or(OpusMultistreamDecoderError::InternalError)?,
688                OpusDecoderCtlRequest::GetLastPacketDuration(slot),
689            )?;
690        }
691        OpusMultistreamDecoderCtlRequest::SetPhaseInversionDisabled(value) => {
692            for dec in &mut decoder.decoders {
693                opus_decoder_ctl(dec, OpusDecoderCtlRequest::SetPhaseInversionDisabled(value))?;
694            }
695        }
696        OpusMultistreamDecoderCtlRequest::GetPhaseInversionDisabled(slot) => {
697            opus_decoder_ctl(
698                decoder
699                    .decoders
700                    .first_mut()
701                    .ok_or(OpusMultistreamDecoderError::InternalError)?,
702                OpusDecoderCtlRequest::GetPhaseInversionDisabled(slot),
703            )?;
704        }
705        OpusMultistreamDecoderCtlRequest::SetDnnBlob(data) => {
706            for dec in &mut decoder.decoders {
707                opus_decoder_ctl(dec, OpusDecoderCtlRequest::SetDnnBlob(data))?;
708            }
709        }
710    }
711
712    Ok(())
713}
714
715fn opus_multistream_packet_validate(
716    data: &[u8],
717    len: usize,
718    nb_streams: usize,
719    sample_rate: i32,
720) -> Result<usize, OpusMultistreamDecoderError> {
721    if len > data.len() || nb_streams == 0 || sample_rate <= 0 {
722        return Err(OpusMultistreamDecoderError::BadArgument);
723    }
724
725    let mut remaining = len;
726    let mut cursor = data;
727    let mut samples: Option<usize> = None;
728
729    for stream in 0..nb_streams {
730        if remaining == 0 {
731            return Err(OpusMultistreamDecoderError::InvalidPacket);
732        }
733
734        let parsed = opus_packet_parse_impl(cursor, remaining, stream + 1 != nb_streams)?;
735        let tmp_samples =
736            opus_packet_get_nb_samples(cursor, parsed.packet_offset, sample_rate as u32)?;
737        if let Some(prev) = samples {
738            if prev != tmp_samples {
739                return Err(OpusMultistreamDecoderError::InvalidPacket);
740            }
741        } else {
742            samples = Some(tmp_samples);
743        }
744
745        cursor = &cursor[parsed.packet_offset..];
746        remaining = remaining
747            .checked_sub(parsed.packet_offset)
748            .ok_or(OpusMultistreamDecoderError::InvalidPacket)?;
749    }
750
751    samples.ok_or(OpusMultistreamDecoderError::InvalidPacket)
752}
753
754#[cfg(feature = "fixed_point")]
755const OPTIONAL_CLIP: bool = false;
756#[cfg(not(feature = "fixed_point"))]
757const OPTIONAL_CLIP: bool = true;
758
759fn opus_multistream_decode_native<T: PcmSample>(
760    decoder: &mut OpusMultistreamDecoder<'_>,
761    data: &[u8],
762    len: usize,
763    pcm: &mut [T],
764    frame_size: usize,
765    decode_fec: bool,
766    soft_clip: bool,
767) -> Result<usize, OpusMultistreamDecoderError> {
768    opus_multistream_decode_native_with_handler(
769        decoder,
770        data,
771        len,
772        pcm,
773        frame_size,
774        decode_fec,
775        soft_clip,
776        |dst, dst_stride, dst_channel, src, frame_size, src_offset| {
777            copy_channel_out(dst, dst_stride, dst_channel, src, frame_size, src_offset);
778        },
779    )
780}
781
782#[allow(clippy::too_many_arguments)]
783pub(crate) fn opus_multistream_decode_native_with_handler<T>(
784    decoder: &mut OpusMultistreamDecoder<'_>,
785    data: &[u8],
786    len: usize,
787    pcm: &mut [T],
788    mut frame_size: usize,
789    decode_fec: bool,
790    soft_clip: bool,
791    mut handler: impl FnMut(&mut [T], usize, usize, Option<(&[OpusRes], usize)>, usize, usize),
792) -> Result<usize, OpusMultistreamDecoderError> {
793    if frame_size == 0 {
794        return Err(OpusMultistreamDecoderError::BadArgument);
795    }
796
797    if len > data.len() {
798        return Err(OpusMultistreamDecoderError::BadArgument);
799    }
800
801    let nb_streams = decoder.layout.nb_streams;
802    if nb_streams == 0 {
803        return Err(OpusMultistreamDecoderError::BadArgument);
804    }
805
806    let sample_rate = decoder
807        .sample_rate()
808        .ok_or(OpusMultistreamDecoderError::InternalError)?;
809
810    let max_frame = sample_rate as usize / 25 * 3;
811    frame_size = frame_size.min(max_frame);
812
813    let required = frame_size
814        .checked_mul(decoder.layout.nb_channels)
815        .ok_or(OpusMultistreamDecoderError::BadArgument)?;
816    if pcm.len() < required {
817        return Err(OpusMultistreamDecoderError::BufferTooSmall);
818    }
819
820    let do_plc = len == 0;
821    if !do_plc {
822        let minimum = nb_streams
823            .checked_mul(2)
824            .and_then(|value| value.checked_sub(1))
825            .ok_or(OpusMultistreamDecoderError::BadArgument)?;
826        if len < minimum {
827            return Err(OpusMultistreamDecoderError::InvalidPacket);
828        }
829
830        let samples = opus_multistream_packet_validate(data, len, nb_streams, sample_rate)?;
831        if samples > frame_size {
832            return Err(OpusMultistreamDecoderError::BufferTooSmall);
833        }
834    }
835
836    let mut scratch = vec![OpusRes::default(); 2 * frame_size];
837    let mut cursor = data;
838    let mut remaining = len;
839    let mut decoded_frame_size = frame_size;
840
841    for stream in 0..nb_streams {
842        let self_delimited = stream + 1 != nb_streams;
843
844        let decoder_state = decoder
845            .decoders
846            .get_mut(stream)
847            .ok_or(OpusMultistreamDecoderError::InternalError)?;
848
849        let mut packet_offset = 0usize;
850        let decoded = if do_plc {
851            opus_decode_native(
852                decoder_state,
853                None,
854                0,
855                &mut scratch,
856                decoded_frame_size,
857                decode_fec,
858                self_delimited,
859                None,
860                soft_clip,
861            )?
862        } else {
863            if remaining == 0 {
864                return Err(OpusMultistreamDecoderError::InternalError);
865            }
866            opus_decode_native(
867                decoder_state,
868                Some(cursor),
869                remaining,
870                &mut scratch,
871                decoded_frame_size,
872                decode_fec,
873                self_delimited,
874                Some(&mut packet_offset),
875                soft_clip,
876            )?
877        };
878
879        if !do_plc {
880            if packet_offset > remaining {
881                return Err(OpusMultistreamDecoderError::InvalidPacket);
882            }
883            cursor = &cursor[packet_offset..];
884            remaining -= packet_offset;
885        }
886
887        if decoded == 0 {
888            return Err(OpusMultistreamDecoderError::InternalError);
889        }
890        decoded_frame_size = decoded;
891
892        if stream < decoder.layout.nb_coupled_streams {
893            let mut prev = None;
894            while let Some(chan) = get_left_channel(&decoder.layout, stream, prev) {
895                handler(
896                    pcm,
897                    decoder.layout.nb_channels,
898                    chan,
899                    Some((&scratch[..], 2)),
900                    decoded_frame_size,
901                    0,
902                );
903                prev = Some(chan);
904            }
905
906            let mut prev = None;
907            while let Some(chan) = get_right_channel(&decoder.layout, stream, prev) {
908                handler(
909                    pcm,
910                    decoder.layout.nb_channels,
911                    chan,
912                    Some((&scratch[1..], 2)),
913                    decoded_frame_size,
914                    0,
915                );
916                prev = Some(chan);
917            }
918        } else {
919            let mut prev = None;
920            while let Some(chan) = get_mono_channel(&decoder.layout, stream, prev) {
921                handler(
922                    pcm,
923                    decoder.layout.nb_channels,
924                    chan,
925                    Some((&scratch[..], 1)),
926                    decoded_frame_size,
927                    0,
928                );
929                prev = Some(chan);
930            }
931        }
932    }
933
934    // Handle muted channels.
935    for channel in 0..decoder.layout.nb_channels {
936        if decoder.layout.mapping[channel] == u8::MAX {
937            handler(
938                pcm,
939                decoder.layout.nb_channels,
940                channel,
941                None,
942                decoded_frame_size,
943                0,
944            );
945        }
946    }
947
948    Ok(decoded_frame_size)
949}
950
951pub fn opus_multistream_decode(
952    decoder: &mut OpusMultistreamDecoder<'_>,
953    data: &[u8],
954    len: usize,
955    pcm: &mut [i16],
956    frame_size: usize,
957    decode_fec: bool,
958) -> Result<usize, OpusMultistreamDecoderError> {
959    opus_multistream_decode_native(
960        decoder,
961        data,
962        len,
963        pcm,
964        frame_size,
965        decode_fec,
966        OPTIONAL_CLIP,
967    )
968}
969
970pub fn opus_multistream_decode24(
971    decoder: &mut OpusMultistreamDecoder<'_>,
972    data: &[u8],
973    len: usize,
974    pcm: &mut [i32],
975    frame_size: usize,
976    decode_fec: bool,
977) -> Result<usize, OpusMultistreamDecoderError> {
978    opus_multistream_decode_native(decoder, data, len, pcm, frame_size, decode_fec, false)
979}
980
981pub fn opus_multistream_decode_float(
982    decoder: &mut OpusMultistreamDecoder<'_>,
983    data: &[u8],
984    len: usize,
985    pcm: &mut [f32],
986    frame_size: usize,
987    decode_fec: bool,
988) -> Result<usize, OpusMultistreamDecoderError> {
989    opus_multistream_decode_native(decoder, data, len, pcm, frame_size, decode_fec, false)
990}
991
992trait PcmSample: Copy + Default {
993    fn from_opus_res(value: OpusRes) -> Self;
994}
995
996#[inline]
997fn res_to_int24(sample: OpusRes) -> i32 {
998    let scale = CELT_SIG_SCALE * 256.0;
999    let scaled = (sample * scale).clamp(-8_388_608.0, 8_388_607.0);
1000    float2int(scaled)
1001}
1002
1003impl PcmSample for i16 {
1004    #[inline]
1005    fn from_opus_res(value: OpusRes) -> Self {
1006        float2int16(value)
1007    }
1008}
1009
1010impl PcmSample for i32 {
1011    #[inline]
1012    fn from_opus_res(value: OpusRes) -> Self {
1013        res_to_int24(value)
1014    }
1015}
1016
1017impl PcmSample for f32 {
1018    #[inline]
1019    fn from_opus_res(value: OpusRes) -> Self {
1020        value
1021    }
1022}
1023
1024fn copy_channel_out<T: PcmSample>(
1025    dst: &mut [T],
1026    dst_stride: usize,
1027    dst_channel: usize,
1028    src: Option<(&[OpusRes], usize)>,
1029    frame_size: usize,
1030    src_offset: usize,
1031) {
1032    if dst_stride == 0 || frame_size == 0 {
1033        return;
1034    }
1035    for i in 0..frame_size {
1036        let dst_index = i * dst_stride + dst_channel;
1037        if dst_index >= dst.len() {
1038            break;
1039        }
1040        dst[dst_index] = match src {
1041            Some((src_data, src_stride)) => {
1042                let src_index = src_offset + i * src_stride;
1043                let value = src_data.get(src_index).copied().unwrap_or_default();
1044                T::from_opus_res(value)
1045            }
1046            None => T::default(),
1047        };
1048    }
1049}
1050
1051/// Errors surfaced by the multistream encoder front-end.
1052#[derive(Debug, Clone, PartialEq, Eq)]
1053pub enum OpusMultistreamEncoderError {
1054    BadArgument,
1055    BufferTooSmall,
1056    InternalError,
1057    Unimplemented,
1058    EncoderInit(OpusEncoderInitError),
1059    EncoderCtl(OpusEncoderCtlError),
1060    Encode(OpusEncodeError),
1061}
1062
1063impl OpusMultistreamEncoderError {
1064    #[inline]
1065    pub const fn code(&self) -> i32 {
1066        match self {
1067            Self::BadArgument => -1,
1068            Self::BufferTooSmall => -2,
1069            Self::InternalError => -3,
1070            Self::Unimplemented => -5,
1071            Self::EncoderInit(err) => err.code(),
1072            Self::EncoderCtl(err) => err.code(),
1073            Self::Encode(err) => err.code(),
1074        }
1075    }
1076}
1077
1078impl From<OpusEncoderInitError> for OpusMultistreamEncoderError {
1079    #[inline]
1080    fn from(value: OpusEncoderInitError) -> Self {
1081        Self::EncoderInit(value)
1082    }
1083}
1084
1085impl From<OpusEncoderCtlError> for OpusMultistreamEncoderError {
1086    #[inline]
1087    fn from(value: OpusEncoderCtlError) -> Self {
1088        Self::EncoderCtl(value)
1089    }
1090}
1091
1092impl From<OpusEncodeError> for OpusMultistreamEncoderError {
1093    #[inline]
1094    fn from(value: OpusEncodeError) -> Self {
1095        match value {
1096            OpusEncodeError::BadArgument => Self::BadArgument,
1097            OpusEncodeError::BufferTooSmall => Self::BufferTooSmall,
1098            OpusEncodeError::InternalError => Self::InternalError,
1099            OpusEncodeError::Unimplemented => Self::Unimplemented,
1100            OpusEncodeError::Silk(_) => Self::Encode(value),
1101        }
1102    }
1103}
1104
1105/// Multistream encoder state mirroring `OpusMSEncoder` from the reference code.
1106#[derive(Debug)]
1107pub struct OpusMultistreamEncoder<'mode> {
1108    layout: ChannelLayout,
1109    encoders: Vec<OpusEncoder<'mode>>,
1110    mapping_type: MappingType,
1111    lfe_stream: Option<usize>,
1112    sample_rate: i32,
1113    application: i32,
1114    bitrate_bps: i32,
1115    variable_duration: i32,
1116}
1117
1118#[derive(Debug, Clone, Copy, Default)]
1119pub struct OpusMultistreamEncodeOptions<'a> {
1120    pub stream_energy_masks: Option<&'a [Option<&'a [f32]>]>,
1121}
1122
1123impl<'mode> OpusMultistreamEncoder<'mode> {
1124    #[inline]
1125    pub fn layout(&self) -> &ChannelLayout {
1126        &self.layout
1127    }
1128
1129    /// Resets the encoder to a new layout and sample rate.
1130    pub fn init(
1131        &mut self,
1132        sample_rate: i32,
1133        channels: usize,
1134        streams: usize,
1135        coupled_streams: usize,
1136        mapping: &[u8],
1137        application: i32,
1138    ) -> Result<(), OpusMultistreamEncoderError> {
1139        let layout = build_encoder_layout(channels, streams, coupled_streams, mapping)?;
1140        let encoders = build_stream_encoders(sample_rate, streams, coupled_streams, application)?;
1141
1142        self.layout = layout;
1143        self.encoders = encoders;
1144        self.mapping_type = MappingType::None;
1145        self.lfe_stream = None;
1146        self.sample_rate = sample_rate;
1147        self.application = application;
1148        self.bitrate_bps = OPUS_AUTO;
1149        self.variable_duration = OPUS_FRAMESIZE_ARG;
1150        Ok(())
1151    }
1152
1153    /// Returns a mutable reference to the encoder for `stream_id`, mirroring
1154    /// `OPUS_MULTISTREAM_GET_ENCODER_STATE`.
1155    pub fn encoder_state(&mut self, stream_id: usize) -> Option<&mut OpusEncoder<'mode>> {
1156        self.encoders.get_mut(stream_id)
1157    }
1158}
1159
1160/// Returns the encoder state for a specific stream, mirroring
1161/// `OPUS_MULTISTREAM_GET_ENCODER_STATE`.
1162pub fn opus_multistream_encoder_get_encoder_state<'a, 'mode>(
1163    encoder: &'a mut OpusMultistreamEncoder<'mode>,
1164    stream_id: usize,
1165) -> Result<&'a mut OpusEncoder<'mode>, OpusMultistreamEncoderError> {
1166    encoder
1167        .encoders
1168        .get_mut(stream_id)
1169        .ok_or(OpusMultistreamEncoderError::BadArgument)
1170}
1171
1172/// Returns the number of bytes required to allocate a multistream encoder.
1173#[must_use]
1174pub fn opus_multistream_encoder_get_size(
1175    nb_streams: usize,
1176    nb_coupled_streams: usize,
1177) -> Option<usize> {
1178    if nb_streams == 0 || nb_coupled_streams > nb_streams {
1179        return None;
1180    }
1181
1182    let coupled_size = opus_encoder_get_size(2)?;
1183    let mono_size = opus_encoder_get_size(1)?;
1184    let header_size = align(core::mem::size_of::<OpusMsEncoderLayout>());
1185
1186    let coupled_total = nb_coupled_streams.checked_mul(align(coupled_size))?;
1187    let mono_total = nb_streams
1188        .checked_sub(nb_coupled_streams)?
1189        .checked_mul(align(mono_size))?;
1190
1191    header_size
1192        .checked_add(coupled_total)?
1193        .checked_add(mono_total)
1194}
1195
1196/// Mirrors `opus_multistream_encoder_create` by allocating and initialising all
1197/// component encoders.
1198pub fn opus_multistream_encoder_create(
1199    sample_rate: i32,
1200    channels: usize,
1201    streams: usize,
1202    coupled_streams: usize,
1203    mapping: &[u8],
1204    application: i32,
1205) -> Result<OpusMultistreamEncoder<'static>, OpusMultistreamEncoderError> {
1206    let layout = build_encoder_layout(channels, streams, coupled_streams, mapping)?;
1207    let encoders = build_stream_encoders(sample_rate, streams, coupled_streams, application)?;
1208
1209    Ok(OpusMultistreamEncoder {
1210        layout,
1211        encoders,
1212        mapping_type: MappingType::None,
1213        lfe_stream: None,
1214        sample_rate,
1215        application,
1216        bitrate_bps: OPUS_AUTO,
1217        variable_duration: OPUS_FRAMESIZE_ARG,
1218    })
1219}
1220
1221fn build_encoder_layout(
1222    channels: usize,
1223    streams: usize,
1224    coupled_streams: usize,
1225    mapping: &[u8],
1226) -> Result<ChannelLayout, OpusMultistreamEncoderError> {
1227    let layout =
1228        build_layout(channels, streams, coupled_streams, mapping).map_err(|err| match err {
1229            OpusMultistreamDecoderError::BadArgument => OpusMultistreamEncoderError::BadArgument,
1230            _ => OpusMultistreamEncoderError::InternalError,
1231        })?;
1232    if streams
1233        .checked_add(coupled_streams)
1234        .is_none_or(|total| total > channels)
1235    {
1236        return Err(OpusMultistreamEncoderError::BadArgument);
1237    }
1238    if !validate_encoder_layout(&layout) {
1239        return Err(OpusMultistreamEncoderError::BadArgument);
1240    }
1241    Ok(layout)
1242}
1243
1244fn build_stream_encoders(
1245    sample_rate: i32,
1246    streams: usize,
1247    coupled_streams: usize,
1248    application: i32,
1249) -> Result<Vec<OpusEncoder<'static>>, OpusMultistreamEncoderError> {
1250    if sample_rate <= 0 {
1251        return Err(OpusMultistreamEncoderError::BadArgument);
1252    }
1253    let mut encoders = Vec::with_capacity(streams);
1254    for stream in 0..streams {
1255        let channels: i32 = if stream < coupled_streams { 2 } else { 1 };
1256        encoders.push(opus_encoder_create(sample_rate, channels, application)?);
1257    }
1258    Ok(encoders)
1259}
1260
1261/// Strongly-typed replacement for the multistream encoder CTL dispatcher.
1262pub enum OpusMultistreamEncoderCtlRequest<'req> {
1263    SetApplication(i32),
1264    GetApplication(&'req mut i32),
1265    SetBitrate(i32),
1266    GetBitrate(&'req mut i32),
1267    SetForceChannels(i32),
1268    GetForceChannels(&'req mut i32),
1269    SetMaxBandwidth(i32),
1270    GetMaxBandwidth(&'req mut i32),
1271    SetBandwidth(i32),
1272    GetBandwidth(&'req mut i32),
1273    SetVbr(bool),
1274    GetVbr(&'req mut bool),
1275    SetVbrConstraint(bool),
1276    GetVbrConstraint(&'req mut bool),
1277    SetComplexity(i32),
1278    GetComplexity(&'req mut i32),
1279    SetSignal(i32),
1280    GetSignal(&'req mut i32),
1281    GetVoiceRatio(&'req mut i32),
1282    SetPacketLossPerc(i32),
1283    GetPacketLossPerc(&'req mut i32),
1284    SetInbandFec(bool),
1285    GetInbandFec(&'req mut bool),
1286    SetDtx(bool),
1287    GetDtx(&'req mut bool),
1288    GetInDtx(&'req mut bool),
1289    SetLsbDepth(i32),
1290    GetLsbDepth(&'req mut i32),
1291    SetExpertFrameDuration(i32),
1292    GetExpertFrameDuration(&'req mut i32),
1293    SetPredictionDisabled(bool),
1294    GetPredictionDisabled(&'req mut bool),
1295    SetPhaseInversionDisabled(bool),
1296    GetPhaseInversionDisabled(&'req mut bool),
1297    SetDredDuration(i32),
1298    GetDredDuration(&'req mut i32),
1299    SetDnnBlob(&'req [u8]),
1300    SetForceMode(i32),
1301    GetSampleRate(&'req mut i32),
1302    GetLookahead(&'req mut i32),
1303    GetFinalRange(&'req mut u32),
1304    ResetState,
1305}
1306
1307/// Applies a control request across the embedded encoders.
1308pub fn opus_multistream_encoder_ctl<'req>(
1309    encoder: &mut OpusMultistreamEncoder<'_>,
1310    request: OpusMultistreamEncoderCtlRequest<'req>,
1311) -> Result<(), OpusMultistreamEncoderError> {
1312    if encoder.encoders.is_empty() {
1313        return Err(OpusMultistreamEncoderError::InternalError);
1314    }
1315
1316    match request {
1317        OpusMultistreamEncoderCtlRequest::SetApplication(value) => {
1318            for enc in &mut encoder.encoders {
1319                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetApplication(value)).map_err(
1320                    |err| match err {
1321                        OpusEncoderCtlError::BadArgument => {
1322                            OpusMultistreamEncoderError::BadArgument
1323                        }
1324                        _ => OpusMultistreamEncoderError::EncoderCtl(err),
1325                    },
1326                )?;
1327            }
1328            encoder.application = value;
1329        }
1330        OpusMultistreamEncoderCtlRequest::GetApplication(out) => {
1331            opus_encoder_ctl(
1332                encoder
1333                    .encoders
1334                    .first_mut()
1335                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1336                OpusEncoderCtlRequest::GetApplication(out),
1337            )?;
1338        }
1339        OpusMultistreamEncoderCtlRequest::SetBitrate(value) => {
1340            if value != OPUS_AUTO && value != OPUS_BITRATE_MAX && value <= 0 {
1341                return Err(OpusMultistreamEncoderError::BadArgument);
1342            }
1343            let clamped = if value == OPUS_AUTO || value == OPUS_BITRATE_MAX {
1344                value
1345            } else {
1346                let channels = i32::try_from(encoder.layout.nb_channels)
1347                    .map_err(|_| OpusMultistreamEncoderError::BadArgument)?;
1348                let min_rate = 500i32.saturating_mul(channels);
1349                let max_rate = 300_000i32.saturating_mul(channels);
1350                value.clamp(min_rate, max_rate)
1351            };
1352            encoder.bitrate_bps = clamped;
1353        }
1354        OpusMultistreamEncoderCtlRequest::GetBitrate(out) => {
1355            let mut total = 0i64;
1356            for enc in &mut encoder.encoders {
1357                let mut rate = 0i32;
1358                opus_encoder_ctl(enc, OpusEncoderCtlRequest::GetBitrate(&mut rate))?;
1359                total += i64::from(rate);
1360            }
1361            *out = i32::try_from(total).map_err(|_| OpusMultistreamEncoderError::InternalError)?;
1362        }
1363        OpusMultistreamEncoderCtlRequest::SetForceChannels(value) => {
1364            for enc in &mut encoder.encoders {
1365                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetForceChannels(value))?;
1366            }
1367        }
1368        OpusMultistreamEncoderCtlRequest::GetForceChannels(out) => {
1369            opus_encoder_ctl(
1370                encoder
1371                    .encoders
1372                    .first_mut()
1373                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1374                OpusEncoderCtlRequest::GetForceChannels(out),
1375            )?;
1376        }
1377        OpusMultistreamEncoderCtlRequest::SetMaxBandwidth(value) => {
1378            for enc in &mut encoder.encoders {
1379                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetMaxBandwidth(value))?;
1380            }
1381        }
1382        OpusMultistreamEncoderCtlRequest::GetMaxBandwidth(out) => {
1383            opus_encoder_ctl(
1384                encoder
1385                    .encoders
1386                    .first_mut()
1387                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1388                OpusEncoderCtlRequest::GetMaxBandwidth(out),
1389            )?;
1390        }
1391        OpusMultistreamEncoderCtlRequest::SetBandwidth(value) => {
1392            for enc in &mut encoder.encoders {
1393                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetBandwidth(value))?;
1394            }
1395        }
1396        OpusMultistreamEncoderCtlRequest::GetBandwidth(out) => {
1397            opus_encoder_ctl(
1398                encoder
1399                    .encoders
1400                    .first_mut()
1401                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1402                OpusEncoderCtlRequest::GetBandwidth(out),
1403            )?;
1404        }
1405        OpusMultistreamEncoderCtlRequest::SetVbr(value) => {
1406            for enc in &mut encoder.encoders {
1407                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetVbr(value))?;
1408            }
1409        }
1410        OpusMultistreamEncoderCtlRequest::GetVbr(out) => {
1411            opus_encoder_ctl(
1412                encoder
1413                    .encoders
1414                    .first_mut()
1415                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1416                OpusEncoderCtlRequest::GetVbr(out),
1417            )?;
1418        }
1419        OpusMultistreamEncoderCtlRequest::SetVbrConstraint(value) => {
1420            for enc in &mut encoder.encoders {
1421                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetVbrConstraint(value))?;
1422            }
1423        }
1424        OpusMultistreamEncoderCtlRequest::GetVbrConstraint(out) => {
1425            opus_encoder_ctl(
1426                encoder
1427                    .encoders
1428                    .first_mut()
1429                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1430                OpusEncoderCtlRequest::GetVbrConstraint(out),
1431            )?;
1432        }
1433        OpusMultistreamEncoderCtlRequest::SetComplexity(value) => {
1434            for enc in &mut encoder.encoders {
1435                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetComplexity(value))?;
1436            }
1437        }
1438        OpusMultistreamEncoderCtlRequest::GetComplexity(out) => {
1439            opus_encoder_ctl(
1440                encoder
1441                    .encoders
1442                    .first_mut()
1443                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1444                OpusEncoderCtlRequest::GetComplexity(out),
1445            )?;
1446        }
1447        OpusMultistreamEncoderCtlRequest::SetSignal(value) => {
1448            for enc in &mut encoder.encoders {
1449                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetSignal(value))?;
1450            }
1451        }
1452        OpusMultistreamEncoderCtlRequest::GetSignal(out) => {
1453            opus_encoder_ctl(
1454                encoder
1455                    .encoders
1456                    .first_mut()
1457                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1458                OpusEncoderCtlRequest::GetSignal(out),
1459            )?;
1460        }
1461        OpusMultistreamEncoderCtlRequest::GetVoiceRatio(out) => {
1462            opus_encoder_ctl(
1463                encoder
1464                    .encoders
1465                    .first_mut()
1466                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1467                OpusEncoderCtlRequest::GetVoiceRatio(out),
1468            )?;
1469        }
1470        OpusMultistreamEncoderCtlRequest::SetPacketLossPerc(value) => {
1471            for enc in &mut encoder.encoders {
1472                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetPacketLossPerc(value))?;
1473            }
1474        }
1475        OpusMultistreamEncoderCtlRequest::GetPacketLossPerc(out) => {
1476            opus_encoder_ctl(
1477                encoder
1478                    .encoders
1479                    .first_mut()
1480                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1481                OpusEncoderCtlRequest::GetPacketLossPerc(out),
1482            )?;
1483        }
1484        OpusMultistreamEncoderCtlRequest::SetInbandFec(value) => {
1485            for enc in &mut encoder.encoders {
1486                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetInbandFec(value))?;
1487            }
1488        }
1489        OpusMultistreamEncoderCtlRequest::GetInbandFec(out) => {
1490            opus_encoder_ctl(
1491                encoder
1492                    .encoders
1493                    .first_mut()
1494                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1495                OpusEncoderCtlRequest::GetInbandFec(out),
1496            )?;
1497        }
1498        OpusMultistreamEncoderCtlRequest::SetDtx(value) => {
1499            for enc in &mut encoder.encoders {
1500                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetDtx(value))?;
1501            }
1502        }
1503        OpusMultistreamEncoderCtlRequest::GetDtx(out) => {
1504            opus_encoder_ctl(
1505                encoder
1506                    .encoders
1507                    .first_mut()
1508                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1509                OpusEncoderCtlRequest::GetDtx(out),
1510            )?;
1511        }
1512        OpusMultistreamEncoderCtlRequest::GetInDtx(out) => {
1513            opus_encoder_ctl(
1514                encoder
1515                    .encoders
1516                    .first_mut()
1517                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1518                OpusEncoderCtlRequest::GetInDtx(out),
1519            )?;
1520        }
1521        OpusMultistreamEncoderCtlRequest::SetLsbDepth(value) => {
1522            for enc in &mut encoder.encoders {
1523                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetLsbDepth(value))?;
1524            }
1525        }
1526        OpusMultistreamEncoderCtlRequest::GetLsbDepth(out) => {
1527            opus_encoder_ctl(
1528                encoder
1529                    .encoders
1530                    .first_mut()
1531                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1532                OpusEncoderCtlRequest::GetLsbDepth(out),
1533            )?;
1534        }
1535        OpusMultistreamEncoderCtlRequest::SetExpertFrameDuration(value) => {
1536            encoder.variable_duration = value;
1537        }
1538        OpusMultistreamEncoderCtlRequest::GetExpertFrameDuration(out) => {
1539            *out = encoder.variable_duration;
1540        }
1541        OpusMultistreamEncoderCtlRequest::SetPredictionDisabled(value) => {
1542            for enc in &mut encoder.encoders {
1543                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetPredictionDisabled(value))?;
1544            }
1545        }
1546        OpusMultistreamEncoderCtlRequest::GetPredictionDisabled(out) => {
1547            opus_encoder_ctl(
1548                encoder
1549                    .encoders
1550                    .first_mut()
1551                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1552                OpusEncoderCtlRequest::GetPredictionDisabled(out),
1553            )?;
1554        }
1555        OpusMultistreamEncoderCtlRequest::SetPhaseInversionDisabled(value) => {
1556            for enc in &mut encoder.encoders {
1557                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetPhaseInversionDisabled(value))?;
1558            }
1559        }
1560        OpusMultistreamEncoderCtlRequest::GetPhaseInversionDisabled(out) => {
1561            opus_encoder_ctl(
1562                encoder
1563                    .encoders
1564                    .first_mut()
1565                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1566                OpusEncoderCtlRequest::GetPhaseInversionDisabled(out),
1567            )?;
1568        }
1569        OpusMultistreamEncoderCtlRequest::SetDredDuration(value) => {
1570            for enc in &mut encoder.encoders {
1571                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetDredDuration(value))?;
1572            }
1573        }
1574        OpusMultistreamEncoderCtlRequest::GetDredDuration(out) => {
1575            opus_encoder_ctl(
1576                encoder
1577                    .encoders
1578                    .first_mut()
1579                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1580                OpusEncoderCtlRequest::GetDredDuration(out),
1581            )?;
1582        }
1583        OpusMultistreamEncoderCtlRequest::SetDnnBlob(data) => {
1584            for enc in &mut encoder.encoders {
1585                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetDnnBlob(data))?;
1586            }
1587        }
1588        OpusMultistreamEncoderCtlRequest::SetForceMode(value) => {
1589            for enc in &mut encoder.encoders {
1590                opus_encoder_ctl(enc, OpusEncoderCtlRequest::SetForceMode(value))?;
1591            }
1592        }
1593        OpusMultistreamEncoderCtlRequest::GetSampleRate(out) => {
1594            opus_encoder_ctl(
1595                encoder
1596                    .encoders
1597                    .first_mut()
1598                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1599                OpusEncoderCtlRequest::GetSampleRate(out),
1600            )?;
1601        }
1602        OpusMultistreamEncoderCtlRequest::GetLookahead(out) => {
1603            opus_encoder_ctl(
1604                encoder
1605                    .encoders
1606                    .first_mut()
1607                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1608                OpusEncoderCtlRequest::GetLookahead(out),
1609            )?;
1610        }
1611        OpusMultistreamEncoderCtlRequest::GetFinalRange(out) => {
1612            let mut acc = 0u32;
1613            for enc in &mut encoder.encoders {
1614                let mut value = 0u32;
1615                opus_encoder_ctl(enc, OpusEncoderCtlRequest::GetFinalRange(&mut value))?;
1616                acc ^= value;
1617            }
1618            *out = acc;
1619        }
1620        OpusMultistreamEncoderCtlRequest::ResetState => {
1621            for enc in &mut encoder.encoders {
1622                opus_encoder_ctl(enc, OpusEncoderCtlRequest::ResetState)?;
1623            }
1624        }
1625    }
1626
1627    Ok(())
1628}
1629
1630fn encode_size(size: usize, data: &mut [u8]) -> Option<usize> {
1631    if data.is_empty() {
1632        return None;
1633    }
1634    if size < 252 {
1635        data[0] = size as u8;
1636        Some(1)
1637    } else {
1638        if data.len() < 2 {
1639            return None;
1640        }
1641        data[0] = 252 + (size & 0x3) as u8;
1642        data[1] = ((size - usize::from(data[0])) >> 2) as u8;
1643        Some(2)
1644    }
1645}
1646
1647fn extract_i16_channel(
1648    input: &[i16],
1649    input_channels: usize,
1650    channel: usize,
1651    frame_size: usize,
1652    output: &mut [i16],
1653    output_stride: usize,
1654    output_offset: usize,
1655) -> Result<(), OpusMultistreamEncoderError> {
1656    for i in 0..frame_size {
1657        let src = i
1658            .checked_mul(input_channels)
1659            .and_then(|base| base.checked_add(channel))
1660            .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1661        let dst = output_offset
1662            .checked_add(
1663                i.checked_mul(output_stride)
1664                    .ok_or(OpusMultistreamEncoderError::BadArgument)?,
1665            )
1666            .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1667        output[dst] = *input
1668            .get(src)
1669            .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1670    }
1671    Ok(())
1672}
1673
1674pub fn opus_multistream_encode_with_options(
1675    encoder: &mut OpusMultistreamEncoder<'_>,
1676    pcm: &[i16],
1677    frame_size: usize,
1678    data: &mut [u8],
1679    options: OpusMultistreamEncodeOptions<'_>,
1680) -> Result<usize, OpusMultistreamEncoderError> {
1681    let channels = encoder.layout.nb_channels;
1682    if channels == 0 || frame_size == 0 {
1683        return Err(OpusMultistreamEncoderError::BadArgument);
1684    }
1685    let required_pcm = channels
1686        .checked_mul(frame_size)
1687        .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1688    if pcm.len() < required_pcm {
1689        return Err(OpusMultistreamEncoderError::BadArgument);
1690    }
1691
1692    let nb_streams = encoder.layout.nb_streams;
1693    if nb_streams == 0 {
1694        return Err(OpusMultistreamEncoderError::BadArgument);
1695    }
1696    if let Some(masks) = options.stream_energy_masks
1697        && masks.len() != nb_streams
1698    {
1699        return Err(OpusMultistreamEncoderError::BadArgument);
1700    }
1701
1702    let smallest_packet = nb_streams
1703        .checked_mul(2)
1704        .and_then(|value| value.checked_sub(1))
1705        .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1706    if data.len() < smallest_packet {
1707        return Err(OpusMultistreamEncoderError::BufferTooSmall);
1708    }
1709
1710    let mut rates = vec![0i32; nb_streams];
1711    let _ = rate_allocation(
1712        &encoder.layout,
1713        encoder.mapping_type,
1714        encoder.bitrate_bps,
1715        encoder.lfe_stream,
1716        frame_size,
1717        encoder.sample_rate,
1718        &mut rates,
1719    );
1720
1721    let mut total_written = 0usize;
1722    for stream in 0..nb_streams {
1723        let self_delimited = stream + 1 != nb_streams;
1724        let remaining_streams = nb_streams - stream - 1;
1725        let reserve_min = remaining_streams
1726            .checked_mul(2)
1727            .and_then(|value| value.checked_sub(1))
1728            .unwrap_or(0);
1729        let available = data
1730            .len()
1731            .checked_sub(total_written)
1732            .and_then(|value| value.checked_sub(reserve_min))
1733            .ok_or(OpusMultistreamEncoderError::BufferTooSmall)?;
1734
1735        // Worst-case 2 bytes for the self-delimiting size.
1736        let size_overhead = if self_delimited { 2 } else { 0 };
1737        if available <= size_overhead + 1 {
1738            return Err(OpusMultistreamEncoderError::BufferTooSmall);
1739        }
1740        let mut tmp = vec![0u8; available - size_overhead];
1741
1742        if let Some(rate) = rates.get(stream).copied() {
1743            let _ = opus_encoder_ctl(
1744                encoder
1745                    .encoders
1746                    .get_mut(stream)
1747                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1748                OpusEncoderCtlRequest::SetBitrate(rate),
1749            );
1750        }
1751        let encode_options = OpusEncodeOptions {
1752            energy_masking: options
1753                .stream_energy_masks
1754                .and_then(|masks| masks.get(stream))
1755                .copied()
1756                .flatten(),
1757        };
1758
1759        if stream < encoder.layout.nb_coupled_streams {
1760            let left = get_left_channel(&encoder.layout, stream, None)
1761                .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1762            let right = get_right_channel(&encoder.layout, stream, None)
1763                .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1764
1765            let mut coupled_pcm = vec![0i16; frame_size * 2];
1766            extract_i16_channel(pcm, channels, left, frame_size, &mut coupled_pcm, 2, 0)?;
1767            extract_i16_channel(pcm, channels, right, frame_size, &mut coupled_pcm, 2, 1)?;
1768
1769            let len = opus_encode_with_options(
1770                encoder
1771                    .encoders
1772                    .get_mut(stream)
1773                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1774                &coupled_pcm,
1775                frame_size,
1776                &mut tmp,
1777                encode_options,
1778            )?;
1779
1780            let written =
1781                write_stream_packet(&tmp[..len], self_delimited, &mut data[total_written..])
1782                    .ok_or(OpusMultistreamEncoderError::BufferTooSmall)?;
1783            total_written += written;
1784        } else {
1785            let chan = get_mono_channel(&encoder.layout, stream, None)
1786                .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1787            let mut mono_pcm = vec![0i16; frame_size];
1788            extract_i16_channel(pcm, channels, chan, frame_size, &mut mono_pcm, 1, 0)?;
1789
1790            let len = opus_encode_with_options(
1791                encoder
1792                    .encoders
1793                    .get_mut(stream)
1794                    .ok_or(OpusMultistreamEncoderError::InternalError)?,
1795                &mono_pcm,
1796                frame_size,
1797                &mut tmp,
1798                encode_options,
1799            )?;
1800
1801            let written =
1802                write_stream_packet(&tmp[..len], self_delimited, &mut data[total_written..])
1803                    .ok_or(OpusMultistreamEncoderError::BufferTooSmall)?;
1804            total_written += written;
1805        }
1806    }
1807
1808    Ok(total_written)
1809}
1810
1811pub fn opus_multistream_encode(
1812    encoder: &mut OpusMultistreamEncoder<'_>,
1813    pcm: &[i16],
1814    frame_size: usize,
1815    data: &mut [u8],
1816) -> Result<usize, OpusMultistreamEncoderError> {
1817    opus_multistream_encode_with_options(
1818        encoder,
1819        pcm,
1820        frame_size,
1821        data,
1822        OpusMultistreamEncodeOptions::default(),
1823    )
1824}
1825
1826fn write_stream_packet(
1827    stream_packet: &[u8],
1828    self_delimited: bool,
1829    out: &mut [u8],
1830) -> Option<usize> {
1831    if !self_delimited {
1832        if out.len() < stream_packet.len() {
1833            return None;
1834        }
1835        out[..stream_packet.len()].copy_from_slice(stream_packet);
1836        return Some(stream_packet.len());
1837    }
1838    if stream_packet.is_empty() {
1839        return None;
1840    }
1841    let toc = stream_packet[0];
1842    let frame = &stream_packet[1..];
1843    if out.is_empty() {
1844        return None;
1845    }
1846    out[0] = toc;
1847    let size_bytes = encode_size(frame.len(), &mut out[1..])?;
1848    let start = 1 + size_bytes;
1849    if out.len() < start + frame.len() {
1850        return None;
1851    }
1852    out[start..start + frame.len()].copy_from_slice(frame);
1853    Some(start + frame.len())
1854}
1855
1856pub fn opus_multistream_encode_float_with_options(
1857    encoder: &mut OpusMultistreamEncoder<'_>,
1858    pcm: &[f32],
1859    frame_size: usize,
1860    data: &mut [u8],
1861    options: OpusMultistreamEncodeOptions<'_>,
1862) -> Result<usize, OpusMultistreamEncoderError> {
1863    let channels = encoder.layout.nb_channels;
1864    let required_pcm = channels
1865        .checked_mul(frame_size)
1866        .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1867    if pcm.len() < required_pcm {
1868        return Err(OpusMultistreamEncoderError::BadArgument);
1869    }
1870    let mut tmp = vec![0i16; required_pcm];
1871    for (dst, &sample) in tmp.iter_mut().zip(pcm.iter().take(required_pcm)) {
1872        let scaled = libm::roundf(sample * 32_768.0);
1873        *dst = scaled.clamp(f32::from(i16::MIN), f32::from(i16::MAX)) as i16;
1874    }
1875    opus_multistream_encode_with_options(encoder, &tmp, frame_size, data, options)
1876}
1877
1878pub fn opus_multistream_encode_float(
1879    encoder: &mut OpusMultistreamEncoder<'_>,
1880    pcm: &[f32],
1881    frame_size: usize,
1882    data: &mut [u8],
1883) -> Result<usize, OpusMultistreamEncoderError> {
1884    opus_multistream_encode_float_with_options(
1885        encoder,
1886        pcm,
1887        frame_size,
1888        data,
1889        OpusMultistreamEncodeOptions::default(),
1890    )
1891}
1892
1893pub fn opus_multistream_encode24_with_options(
1894    encoder: &mut OpusMultistreamEncoder<'_>,
1895    pcm: &[i32],
1896    frame_size: usize,
1897    data: &mut [u8],
1898    options: OpusMultistreamEncodeOptions<'_>,
1899) -> Result<usize, OpusMultistreamEncoderError> {
1900    let channels = encoder.layout.nb_channels;
1901    let required_pcm = channels
1902        .checked_mul(frame_size)
1903        .ok_or(OpusMultistreamEncoderError::BadArgument)?;
1904    if pcm.len() < required_pcm {
1905        return Err(OpusMultistreamEncoderError::BadArgument);
1906    }
1907    let mut tmp = vec![0i16; required_pcm];
1908    for (dst, &sample) in tmp.iter_mut().zip(pcm.iter().take(required_pcm)) {
1909        let shifted = (sample >> 8).clamp(i32::from(i16::MIN), i32::from(i16::MAX));
1910        *dst = shifted as i16;
1911    }
1912    opus_multistream_encode_with_options(encoder, &tmp, frame_size, data, options)
1913}
1914
1915pub fn opus_multistream_encode24(
1916    encoder: &mut OpusMultistreamEncoder<'_>,
1917    pcm: &[i32],
1918    frame_size: usize,
1919    data: &mut [u8],
1920) -> Result<usize, OpusMultistreamEncoderError> {
1921    opus_multistream_encode24_with_options(
1922        encoder,
1923        pcm,
1924        frame_size,
1925        data,
1926        OpusMultistreamEncodeOptions::default(),
1927    )
1928}
1929
1930#[derive(Debug, Clone, PartialEq, Eq)]
1931pub struct OpusMultistreamSurroundLayout {
1932    pub streams: usize,
1933    pub coupled_streams: usize,
1934    pub mapping: Vec<u8>,
1935}
1936
1937pub fn opus_multistream_surround_encoder_get_size(
1938    channels: usize,
1939    mapping_family: u8,
1940) -> Option<usize> {
1941    let (streams, coupled_streams, _) = surround_layout(channels, mapping_family).ok()?;
1942    let mut size = opus_multistream_encoder_get_size(streams, coupled_streams)?;
1943    if channels > 2 {
1944        size = size.checked_add(
1945            channels.checked_mul(
1946                120usize
1947                    .checked_mul(core::mem::size_of::<crate::celt::OpusVal32>())?
1948                    .checked_add(core::mem::size_of::<crate::celt::OpusVal32>())?,
1949            )?,
1950        )?;
1951    }
1952    Some(size)
1953}
1954
1955pub fn opus_multistream_surround_encoder_create(
1956    sample_rate: i32,
1957    channels: usize,
1958    mapping_family: u8,
1959    application: i32,
1960) -> Result<
1961    (
1962        OpusMultistreamEncoder<'static>,
1963        OpusMultistreamSurroundLayout,
1964    ),
1965    OpusMultistreamEncoderError,
1966> {
1967    let (streams, coupled_streams, mapping) = surround_layout(channels, mapping_family)?;
1968    let mut encoder = opus_multistream_encoder_create(
1969        sample_rate,
1970        channels,
1971        streams,
1972        coupled_streams,
1973        &mapping,
1974        application,
1975    )?;
1976
1977    let (mapping_type, lfe_stream) = surround_mapping_type(channels, mapping_family, streams);
1978    encoder.mapping_type = mapping_type;
1979    encoder.lfe_stream = lfe_stream;
1980
1981    Ok((
1982        encoder,
1983        OpusMultistreamSurroundLayout {
1984            streams,
1985            coupled_streams,
1986            mapping,
1987        },
1988    ))
1989}
1990
1991pub fn opus_multistream_surround_encoder_init(
1992    encoder: &mut OpusMultistreamEncoder<'_>,
1993    sample_rate: i32,
1994    channels: usize,
1995    mapping_family: u8,
1996    application: i32,
1997) -> Result<OpusMultistreamSurroundLayout, OpusMultistreamEncoderError> {
1998    let (streams, coupled_streams, mapping) = surround_layout(channels, mapping_family)?;
1999    encoder.init(
2000        sample_rate,
2001        channels,
2002        streams,
2003        coupled_streams,
2004        &mapping,
2005        application,
2006    )?;
2007
2008    let (mapping_type, lfe_stream) = surround_mapping_type(channels, mapping_family, streams);
2009    encoder.mapping_type = mapping_type;
2010    encoder.lfe_stream = lfe_stream;
2011
2012    Ok(OpusMultistreamSurroundLayout {
2013        streams,
2014        coupled_streams,
2015        mapping,
2016    })
2017}
2018
2019fn surround_mapping_type(
2020    channels: usize,
2021    mapping_family: u8,
2022    streams: usize,
2023) -> (MappingType, Option<usize>) {
2024    match mapping_family {
2025        1 if channels > 2 => (
2026            MappingType::Surround,
2027            if channels >= 6 {
2028                streams.checked_sub(1)
2029            } else {
2030                None
2031            },
2032        ),
2033        2 => (MappingType::Ambisonics, None),
2034        _ => (MappingType::None, None),
2035    }
2036}
2037
2038fn surround_layout(
2039    channels: usize,
2040    mapping_family: u8,
2041) -> Result<(usize, usize, Vec<u8>), OpusMultistreamEncoderError> {
2042    if channels == 0 || channels > 255 {
2043        return Err(OpusMultistreamEncoderError::BadArgument);
2044    }
2045
2046    let mut mapping = Vec::with_capacity(channels);
2047    match mapping_family {
2048        0 => match channels {
2049            1 => {
2050                mapping.push(0);
2051                Ok((1, 0, mapping))
2052            }
2053            2 => {
2054                mapping.extend_from_slice(&[0, 1]);
2055                Ok((1, 1, mapping))
2056            }
2057            _ => Err(OpusMultistreamEncoderError::Unimplemented),
2058        },
2059        1 => {
2060            if !(1..=8).contains(&channels) {
2061                return Err(OpusMultistreamEncoderError::Unimplemented);
2062            }
2063            let layout = &VORBIS_MAPPINGS[channels - 1];
2064            mapping.extend_from_slice(&layout.mapping[..channels]);
2065            Ok((layout.nb_streams, layout.nb_coupled_streams, mapping))
2066        }
2067        255 => {
2068            mapping.extend((0..channels).map(|v| v as u8));
2069            Ok((channels, 0, mapping))
2070        }
2071        2 => {
2072            let (streams, coupled_streams) =
2073                validate_ambisonics(channels).ok_or(OpusMultistreamEncoderError::BadArgument)?;
2074            let uncoupled_streams = streams - coupled_streams;
2075            for i in 0..uncoupled_streams {
2076                mapping.push((i + coupled_streams * 2) as u8);
2077            }
2078            for i in 0..coupled_streams * 2 {
2079                mapping.push(i as u8);
2080            }
2081            Ok((streams, coupled_streams, mapping))
2082        }
2083        _ => Err(OpusMultistreamEncoderError::Unimplemented),
2084    }
2085}
2086
2087#[cfg(test)]
2088mod tests {
2089    use super::*;
2090    use crate::opus_decoder::{opus_decode, opus_decoder_create};
2091    use crate::opus_encoder::opus_encode;
2092    use alloc::vec;
2093
2094    fn layout_from_mapping(
2095        nb_channels: usize,
2096        nb_streams: usize,
2097        nb_coupled_streams: usize,
2098        mapping_slice: &[u8],
2099    ) -> ChannelLayout {
2100        let mut mapping = [u8::MAX; 256];
2101        let count = mapping_slice.len().min(mapping.len());
2102        mapping[..count].copy_from_slice(&mapping_slice[..count]);
2103        ChannelLayout {
2104            nb_channels,
2105            nb_streams,
2106            nb_coupled_streams,
2107            mapping,
2108        }
2109    }
2110
2111    #[test]
2112    fn accepts_valid_layout() {
2113        let layout = layout_from_mapping(3, 2, 1, &[0, 1, 2]);
2114        assert!(validate_layout(&layout));
2115    }
2116
2117    #[test]
2118    fn rejects_out_of_range_stream_indices() {
2119        let layout = layout_from_mapping(1, 1, 0, &[1]);
2120        assert!(!validate_layout(&layout));
2121    }
2122
2123    #[test]
2124    fn rejects_when_stream_count_exceeds_byte_limit() {
2125        let layout = layout_from_mapping(2, 200, 60, &[0, 1]);
2126        assert!(!validate_layout(&layout));
2127    }
2128
2129    #[test]
2130    fn iterates_all_channels_for_a_stream() {
2131        let layout = layout_from_mapping(4, 3, 1, &[0, 0, 1, 2]);
2132
2133        assert_eq!(get_left_channel(&layout, 0, None), Some(0));
2134        assert_eq!(get_left_channel(&layout, 0, Some(0)), Some(1));
2135        assert_eq!(get_left_channel(&layout, 0, Some(1)), None);
2136
2137        assert_eq!(get_right_channel(&layout, 0, None), Some(2));
2138        assert_eq!(get_right_channel(&layout, 0, Some(2)), None);
2139
2140        assert_eq!(get_mono_channel(&layout, 1, None), Some(3));
2141        assert_eq!(get_mono_channel(&layout, 1, Some(3)), None);
2142    }
2143
2144    #[test]
2145    fn validate_encoder_layout_rejects_missing_channel() {
2146        let layout = layout_from_mapping(2, 1, 1, &[0, u8::MAX]);
2147        assert!(!validate_encoder_layout(&layout));
2148    }
2149
2150    #[test]
2151    fn validate_encoder_layout_accepts_complete_mapping() {
2152        let layout = layout_from_mapping(2, 1, 1, &[0, 1]);
2153        assert!(validate_encoder_layout(&layout));
2154    }
2155
2156    #[test]
2157    fn validate_ambisonics_computes_stream_and_coupling_counts() {
2158        assert_eq!(validate_ambisonics(1), Some((1, 0)));
2159        assert_eq!(validate_ambisonics(6), Some((5, 1)));
2160        assert_eq!(validate_ambisonics(7), None);
2161        assert_eq!(validate_ambisonics(228), None);
2162    }
2163
2164    #[test]
2165    fn rate_allocation_handles_stereo_surround_defaults() {
2166        let layout = layout_from_mapping(2, 1, 1, &[0, 1]);
2167        let mut rates = [0; 1];
2168
2169        let sum = rate_allocation(
2170            &layout,
2171            MappingType::Surround,
2172            OPUS_AUTO,
2173            None,
2174            960,
2175            48_000,
2176            &mut rates,
2177        )
2178        .expect("allocation");
2179
2180        assert_eq!(sum, 120_000);
2181        assert_eq!(rates, [120_000]);
2182    }
2183
2184    #[test]
2185    fn rate_allocation_accounts_for_lfe_stream() {
2186        let layout = layout_from_mapping(6, 4, 2, &[0, 4, 1, 2, 3, 5]);
2187        let mut rates = [0; 4];
2188
2189        let sum = rate_allocation(
2190            &layout,
2191            MappingType::Surround,
2192            256_000,
2193            Some(3),
2194            960,
2195            48_000,
2196            &mut rates,
2197        )
2198        .expect("allocation");
2199
2200        assert_eq!(sum, 255_995);
2201        assert_eq!(rates, [95_120, 95_120, 57_560, 8_195]);
2202    }
2203
2204    #[test]
2205    fn rate_allocation_splits_evenly_for_ambisonics() {
2206        let layout = layout_from_mapping(4, 4, 0, &[0, 1, 2, 3]);
2207        let mut rates = [0; 4];
2208
2209        let sum = rate_allocation(
2210            &layout,
2211            MappingType::Ambisonics,
2212            OPUS_AUTO,
2213            None,
2214            960,
2215            48_000,
2216            &mut rates,
2217        )
2218        .expect("allocation");
2219
2220        assert_eq!(sum, 264_000);
2221        assert_eq!(rates, [66_000; 4]);
2222    }
2223
2224    #[test]
2225    fn rate_allocation_rejects_insufficient_rate_storage() {
2226        let layout = layout_from_mapping(2, 1, 1, &[0, 1]);
2227        let mut rates: [i32; 0] = [];
2228
2229        assert!(
2230            rate_allocation(
2231                &layout,
2232                MappingType::Surround,
2233                64_000,
2234                None,
2235                960,
2236                48_000,
2237                &mut rates
2238            )
2239            .is_none()
2240        );
2241    }
2242
2243    #[test]
2244    fn multistream_decoder_size_matches_aligned_components() {
2245        let coupled = opus_decoder_get_size(2).expect("coupled size");
2246        let mono = opus_decoder_get_size(1).expect("mono size");
2247        let expected =
2248            align(core::mem::size_of::<OpusMsDecoderLayout>()) + align(coupled) + align(mono);
2249        let reported = opus_multistream_decoder_get_size(2, 1).expect("reported size");
2250
2251        assert_eq!(reported, expected);
2252        assert!(opus_multistream_decoder_get_size(0, 0).is_none());
2253        assert!(opus_multistream_decoder_get_size(2, 3).is_none());
2254    }
2255
2256    #[test]
2257    fn multistream_decoder_creation_validates_arguments() {
2258        let mapping = [0u8, 1];
2259        let err = opus_multistream_decoder_create(48_000, 0, 1, 0, &mapping).unwrap_err();
2260        assert_eq!(err, OpusMultistreamDecoderError::BadArgument);
2261
2262        let short_map = [0u8];
2263        let err = opus_multistream_decoder_create(48_000, 2, 1, 1, &short_map).unwrap_err();
2264        assert_eq!(err, OpusMultistreamDecoderError::BadArgument);
2265    }
2266
2267    #[test]
2268    fn multistream_decoder_ctl_round_trips_gain_and_complexity() {
2269        let mapping = [0u8, 1];
2270        let mut decoder =
2271            opus_multistream_decoder_create(48_000, 2, 1, 1, &mapping).expect("decoder");
2272
2273        opus_multistream_decoder_ctl(&mut decoder, OpusMultistreamDecoderCtlRequest::SetGain(-12))
2274            .unwrap();
2275
2276        let mut gain = 0;
2277        opus_multistream_decoder_ctl(
2278            &mut decoder,
2279            OpusMultistreamDecoderCtlRequest::GetGain(&mut gain),
2280        )
2281        .unwrap();
2282        assert_eq!(gain, -12);
2283
2284        opus_multistream_decoder_ctl(
2285            &mut decoder,
2286            OpusMultistreamDecoderCtlRequest::SetComplexity(5),
2287        )
2288        .unwrap();
2289        let mut complexity = 0;
2290        opus_multistream_decoder_ctl(
2291            &mut decoder,
2292            OpusMultistreamDecoderCtlRequest::GetComplexity(&mut complexity),
2293        )
2294        .unwrap();
2295        assert_eq!(complexity, 5);
2296
2297        let mut fs = 0;
2298        opus_multistream_decoder_ctl(
2299            &mut decoder,
2300            OpusMultistreamDecoderCtlRequest::GetSampleRate(&mut fs),
2301        )
2302        .unwrap();
2303        assert_eq!(fs, 48_000);
2304
2305        let err = opus_multistream_decoder_ctl(
2306            &mut decoder,
2307            OpusMultistreamDecoderCtlRequest::SetComplexity(11),
2308        )
2309        .unwrap_err();
2310        assert_eq!(
2311            err,
2312            OpusMultistreamDecoderError::DecoderCtl(OpusDecoderCtlError::BadArgument)
2313        );
2314    }
2315
2316    #[test]
2317    fn packet_validation_accepts_self_delimited_streams() {
2318        // First stream is self-delimited (size=1), second stream is the tail packet.
2319        let packet = [0x00, 0x01, 0xAA, 0x00, 0xBB];
2320        let samples =
2321            opus_multistream_packet_validate(&packet, packet.len(), 2, 48_000).expect("packet");
2322        assert_eq!(samples, 480);
2323    }
2324
2325    #[test]
2326    fn packet_validation_rejects_mismatched_sample_counts() {
2327        // Second stream advertises a 60 ms frame, which does not match the first stream.
2328        let packet = [0x00, 0x01, 0xAA, 0x18, 0xBB];
2329        let err = opus_multistream_packet_validate(&packet, packet.len(), 2, 48_000).unwrap_err();
2330        assert_eq!(err, OpusMultistreamDecoderError::InvalidPacket);
2331    }
2332
2333    #[test]
2334    fn decode_returns_unimplemented_after_validation() {
2335        let mapping = [0u8, 1];
2336        let mut decoder =
2337            opus_multistream_decoder_create(48_000, 2, 1, 1, &mapping).expect("decoder");
2338        let packet = [0x00, 0xAA];
2339        let mut pcm = vec![0i16; 2 * 960];
2340
2341        let decoded =
2342            opus_multistream_decode(&mut decoder, &packet, packet.len(), &mut pcm, 960, false)
2343                .expect("decode");
2344        assert!(decoded > 0);
2345    }
2346
2347    #[test]
2348    fn multistream_decode_matches_single_stream_decoder_for_stereo() {
2349        let mapping = [0u8, 1];
2350        let mut encoder = opus_encoder_create(48_000, 2, 2048).expect("encoder");
2351        let pcm_in = vec![0i16; 2 * 960];
2352        let mut packet = vec![0u8; 1500];
2353        let len = opus_encode(&mut encoder, &pcm_in, 960, &mut packet).expect("encode");
2354
2355        let mut ms_decoder =
2356            opus_multistream_decoder_create(48_000, 2, 1, 1, &mapping).expect("ms decoder");
2357        let mut single = opus_decoder_create(48_000, 2).expect("single decoder");
2358
2359        let mut ms_out = vec![0i16; 2 * 960];
2360        let mut single_out = vec![0i16; 2 * 960];
2361
2362        let ms_decoded =
2363            opus_multistream_decode(&mut ms_decoder, &packet, len, &mut ms_out, 960, false)
2364                .expect("ms decode");
2365        let single_decoded = opus_decode(
2366            &mut single,
2367            Some(&packet[..len]),
2368            len,
2369            &mut single_out,
2370            960,
2371            false,
2372        )
2373        .expect("single decode");
2374        assert_eq!(ms_decoded, single_decoded);
2375        assert_eq!(ms_out[..ms_decoded * 2], single_out[..single_decoded * 2]);
2376    }
2377
2378    #[test]
2379    fn multistream_decode_routes_two_coupled_streams() {
2380        let mapping = [0u8, 1, 2, 3];
2381        let mut ms_encoder =
2382            opus_multistream_encoder_create(48_000, 4, 2, 2, &mapping, 2048).expect("ms encoder");
2383        let pcm_in = vec![0i16; 4 * 960];
2384        let mut packet = vec![0u8; 4000];
2385        let len =
2386            opus_multistream_encode(&mut ms_encoder, &pcm_in, 960, &mut packet).expect("encode");
2387
2388        let mut ms_decoder =
2389            opus_multistream_decoder_create(48_000, 4, 2, 2, &mapping).expect("ms decoder");
2390
2391        let mut ms_out = vec![0i16; 4 * 960];
2392        let decoded =
2393            opus_multistream_decode(&mut ms_decoder, &packet, len, &mut ms_out, 960, false)
2394                .expect("ms decode");
2395        assert!(decoded > 0);
2396
2397        let mut offset = 0usize;
2398        let mut remaining = len;
2399        let mut expected = vec![0i16; 4 * decoded];
2400        for stream in 0..2 {
2401            let self_delimited = stream == 0;
2402            let parsed = opus_packet_parse_impl(&packet[offset..], remaining, self_delimited)
2403                .expect("parse");
2404            let packet_offset = parsed.packet_offset;
2405            let mut dec = opus_decoder_create(48_000, 2).expect("decoder");
2406            let mut stream_out = vec![0i16; 2 * decoded];
2407            let stream_packet = if self_delimited {
2408                let toc = packet[offset];
2409                let payload_start = offset + parsed.payload_offset;
2410                let payload_end = offset + parsed.packet_offset;
2411                let mut reconstructed = vec![0u8; 1 + (payload_end - payload_start)];
2412                reconstructed[0] = toc;
2413                reconstructed[1..].copy_from_slice(&packet[payload_start..payload_end]);
2414                reconstructed
2415            } else {
2416                packet[offset..offset + packet_offset].to_vec()
2417            };
2418
2419            let stream_decoded = opus_decode(
2420                &mut dec,
2421                Some(&stream_packet),
2422                stream_packet.len(),
2423                &mut stream_out,
2424                decoded,
2425                false,
2426            )
2427            .expect("decode");
2428            assert_eq!(stream_decoded, decoded);
2429
2430            for i in 0..decoded {
2431                expected[i * 4 + stream * 2] = stream_out[i * 2];
2432                expected[i * 4 + stream * 2 + 1] = stream_out[i * 2 + 1];
2433            }
2434
2435            offset += packet_offset;
2436            remaining -= packet_offset;
2437        }
2438
2439        assert_eq!(ms_out[..decoded * 4], expected[..decoded * 4]);
2440    }
2441
2442    #[test]
2443    fn multistream_decode_zero_fills_muted_channel() {
2444        let mapping = [0u8, 1, u8::MAX];
2445        let mut encoder = opus_encoder_create(48_000, 2, 2048).expect("encoder");
2446        let pcm_in = vec![0i16; 2 * 960];
2447        let mut packet = vec![0u8; 1500];
2448        let len = opus_encode(&mut encoder, &pcm_in, 960, &mut packet).expect("encode");
2449
2450        let mut ms_decoder =
2451            opus_multistream_decoder_create(48_000, 3, 1, 1, &mapping).expect("ms decoder");
2452        let mut out = vec![0i16; 3 * 960];
2453        let decoded = opus_multistream_decode(&mut ms_decoder, &packet, len, &mut out, 960, false)
2454            .expect("decode");
2455
2456        for i in 0..decoded {
2457            assert_eq!(out[i * 3 + 2], 0);
2458        }
2459    }
2460
2461    #[test]
2462    fn multistream_encode_respects_minimum_packet_size() {
2463        let mapping = [0u8, 1];
2464        let mut ms_encoder =
2465            opus_multistream_encoder_create(48_000, 2, 1, 1, &mapping, 2048).expect("ms encoder");
2466        let pcm_in = vec![0i16; 2 * 960];
2467        let mut packet = vec![0u8; 2];
2468        let err = opus_multistream_encode(&mut ms_encoder, &pcm_in, 960, &mut packet).unwrap_err();
2469        assert_eq!(err, OpusMultistreamEncoderError::BufferTooSmall);
2470    }
2471
2472    #[test]
2473    fn multistream_encoder_ctl_round_trips_lsb_and_prediction() {
2474        let mapping = [0u8, 1];
2475        let mut encoder =
2476            opus_multistream_encoder_create(48_000, 2, 2, 0, &mapping, 2048).expect("ms encoder");
2477
2478        let mut lsb = 0;
2479        opus_multistream_encoder_ctl(
2480            &mut encoder,
2481            OpusMultistreamEncoderCtlRequest::GetLsbDepth(&mut lsb),
2482        )
2483        .unwrap();
2484        assert!(lsb >= 16);
2485
2486        opus_multistream_encoder_ctl(
2487            &mut encoder,
2488            OpusMultistreamEncoderCtlRequest::SetLsbDepth(12),
2489        )
2490        .unwrap();
2491        let mut updated = 0;
2492        opus_multistream_encoder_ctl(
2493            &mut encoder,
2494            OpusMultistreamEncoderCtlRequest::GetLsbDepth(&mut updated),
2495        )
2496        .unwrap();
2497        assert_eq!(updated, 12);
2498
2499        let mut pred = false;
2500        opus_multistream_encoder_ctl(
2501            &mut encoder,
2502            OpusMultistreamEncoderCtlRequest::GetPredictionDisabled(&mut pred),
2503        )
2504        .unwrap();
2505        opus_multistream_encoder_ctl(
2506            &mut encoder,
2507            OpusMultistreamEncoderCtlRequest::SetPredictionDisabled(!pred),
2508        )
2509        .unwrap();
2510        let mut pred_after = false;
2511        opus_multistream_encoder_ctl(
2512            &mut encoder,
2513            OpusMultistreamEncoderCtlRequest::GetPredictionDisabled(&mut pred_after),
2514        )
2515        .unwrap();
2516        assert_eq!(pred_after, !pred);
2517
2518        {
2519            let stream =
2520                opus_multistream_encoder_get_encoder_state(&mut encoder, 1).expect("stream");
2521            let mut stream_lsb = 0;
2522            opus_encoder_ctl(stream, OpusEncoderCtlRequest::GetLsbDepth(&mut stream_lsb)).unwrap();
2523            assert_eq!(stream_lsb, 12);
2524        }
2525
2526        assert_eq!(
2527            opus_multistream_encoder_get_encoder_state(&mut encoder, 2).unwrap_err(),
2528            OpusMultistreamEncoderError::BadArgument
2529        );
2530    }
2531
2532    #[cfg(feature = "dred")]
2533    #[test]
2534    fn multistream_encoder_ctl_round_trips_dred_duration() {
2535        let mapping = [0u8, 1];
2536        let mut encoder =
2537            opus_multistream_encoder_create(48_000, 2, 2, 0, &mapping, 2048).expect("ms encoder");
2538
2539        opus_multistream_encoder_ctl(
2540            &mut encoder,
2541            OpusMultistreamEncoderCtlRequest::SetDredDuration(8),
2542        )
2543        .unwrap();
2544        let mut duration = 0;
2545        opus_multistream_encoder_ctl(
2546            &mut encoder,
2547            OpusMultistreamEncoderCtlRequest::GetDredDuration(&mut duration),
2548        )
2549        .unwrap();
2550        assert_eq!(duration, 8);
2551    }
2552
2553    #[test]
2554    fn surround_encoder_layout_matches_vorbis_mapping() {
2555        let (encoder, layout) =
2556            opus_multistream_surround_encoder_create(48_000, 6, 1, 2048).expect("encoder");
2557
2558        assert_eq!(layout.streams, 4);
2559        assert_eq!(layout.coupled_streams, 2);
2560        assert_eq!(layout.mapping, vec![0, 4, 1, 2, 3, 5]);
2561        assert_eq!(encoder.layout.nb_channels, 6);
2562        assert_eq!(encoder.layout.nb_streams, 4);
2563        assert_eq!(encoder.layout.nb_coupled_streams, 2);
2564
2565        // LFE is the last stream for 5.1+ layouts.
2566        assert_eq!(encoder.lfe_stream, Some(3));
2567        assert_eq!(encoder.mapping_type, MappingType::Surround);
2568    }
2569
2570    #[test]
2571    fn surround_encoder_ambisonics_layout_matches_reference_ordering() {
2572        let (_encoder, layout) =
2573            opus_multistream_surround_encoder_create(48_000, 6, 2, 2048).expect("encoder");
2574        assert_eq!(layout.streams, 5);
2575        assert_eq!(layout.coupled_streams, 1);
2576        assert_eq!(layout.mapping, vec![2, 3, 4, 5, 0, 1]);
2577    }
2578
2579    #[test]
2580    fn surround_encoder_get_size_matches_reference_overhead() {
2581        let size = opus_multistream_surround_encoder_get_size(6, 1).expect("size");
2582        let base = opus_multistream_encoder_get_size(4, 2).expect("base");
2583        let overhead = 6
2584            * (120 * core::mem::size_of::<crate::celt::OpusVal32>()
2585                + core::mem::size_of::<crate::celt::OpusVal32>());
2586        assert_eq!(size, base + overhead);
2587    }
2588}