1use crate::decoder::ChannelDecodeState;
32use crate::range_encoder::RangeEncoder;
33use crate::silk_decode::{
34 encode_silk_frame, SilkFrameConfig, SilkFrameDecoded, SilkFrameSymbols, StereoHeaderContext,
35};
36use crate::silk_excitation::SilkFrameSize;
37use crate::silk_header::{silk_frame_count, PerFrameLbrr, SilkChannelHeader, SilkHeaderBits};
38use crate::toc::{Bandwidth, FrameCountCode, Mode, OpusTocByte};
39use crate::Error;
40
41pub fn encode_silk_only_packet_mono(
58 bandwidth: Bandwidth,
59 frame_size_tenths_ms: u16,
60 frames: &[SilkFrameSymbols<'_>],
61) -> Result<(Vec<u8>, Vec<SilkFrameDecoded>), Error> {
62 let n = silk_frame_count(frame_size_tenths_ms).ok_or(Error::MalformedPacket)? as usize;
63 let no_lbrr = vec![None; n];
64 let (packet, regular, _) =
65 encode_silk_only_packet_mono_with_lbrr(bandwidth, frame_size_tenths_ms, frames, &no_lbrr)?;
66 Ok((packet, regular))
67}
68
69#[allow(clippy::type_complexity)]
82pub fn encode_silk_only_packet_mono_with_lbrr(
83 bandwidth: Bandwidth,
84 frame_size_tenths_ms: u16,
85 frames: &[SilkFrameSymbols<'_>],
86 lbrr: &[Option<SilkFrameSymbols<'_>>],
87) -> Result<
88 (
89 Vec<u8>,
90 Vec<SilkFrameDecoded>,
91 Vec<Option<SilkFrameDecoded>>,
92 ),
93 Error,
94> {
95 let num_silk_frames = silk_frame_count(frame_size_tenths_ms).ok_or(Error::MalformedPacket)?;
96 if frames.len() != num_silk_frames as usize || lbrr.len() != num_silk_frames as usize {
97 return Err(Error::MalformedPacket);
98 }
99 let frame_size = if frame_size_tenths_ms == 100 {
100 SilkFrameSize::TenMs
101 } else {
102 SilkFrameSize::TwentyMs
103 };
104
105 let toc = OpusTocByte::compose_byte(
107 Mode::SilkOnly,
108 bandwidth,
109 frame_size_tenths_ms,
110 false,
111 FrameCountCode::One,
112 )?;
113
114 let mut re = RangeEncoder::new();
115
116 let mut vad_flags = 0u8;
119 for (idx, f) in frames.iter().enumerate() {
120 if f.header.frame_type >= 2 {
121 vad_flags |= 1 << idx;
122 }
123 }
124 let mut lbrr_bits = 0u8;
125 for (idx, l) in lbrr.iter().enumerate() {
126 if l.is_some() {
127 lbrr_bits |= 1 << idx;
128 }
129 }
130 let header = SilkHeaderBits {
131 num_silk_frames,
132 mid: SilkChannelHeader {
133 vad_flags,
134 lbrr_flag: lbrr_bits != 0,
135 },
136 side: None,
137 per_frame_lbrr: PerFrameLbrr {
138 mid: lbrr_bits,
139 side: 0,
140 },
141 };
142 header.encode(&mut re)?;
143
144 let mut lbrr_prev_gain: Option<u8> = None;
149 let mut lbrr_prev_lag: Option<i32> = None;
150 let mut lbrr_first = true;
151 let mut lbrr_predictions: Vec<Option<SilkFrameDecoded>> = Vec::with_capacity(lbrr.len());
152 for entry in lbrr.iter() {
153 let Some(symbols) = entry else {
154 lbrr_predictions.push(None);
155 continue;
156 };
157 if symbols.header.frame_type < 2 {
158 return Err(Error::MalformedPacket);
160 }
161 let cfg = SilkFrameConfig {
162 bandwidth,
163 frame_size,
164 voice_active: true,
165 first_subframe_independent: lbrr_first || lbrr_prev_gain.is_none(),
166 previous_log_gain: lbrr_prev_gain,
167 previous_primary_lag: lbrr_prev_lag,
168 ltp_scaling_present: lbrr_first,
169 lsf_interp_after_reset: lbrr_first,
170 previous_nlsf_q15: None,
171 previous_nlsf_len: 0,
172 stereo: None,
173 };
174 let decoded = encode_silk_frame(&mut re, cfg, symbols)?;
175 lbrr_prev_gain = Some(decoded.gains.last_log_gain());
176 lbrr_prev_lag = Some(decoded.ltp.primary_lag());
177 lbrr_first = false;
178 lbrr_predictions.push(Some(decoded));
179 }
180
181 let mut prev_gain: Option<u8> = None;
184 let mut prev_lag: Option<i32> = None;
185 let mut prev_nlsf: Option<[i16; crate::silk_lsf_stage2::D_LPC_MAX]> = None;
186 let mut prev_nlsf_len = 0usize;
187 let mut first = true;
188 let mut predictions = Vec::with_capacity(frames.len());
189 for (idx, symbols) in frames.iter().enumerate() {
190 let cfg = SilkFrameConfig {
191 bandwidth,
192 frame_size,
193 voice_active: (vad_flags >> idx) & 1 == 1,
194 first_subframe_independent: first || prev_gain.is_none(),
195 previous_log_gain: prev_gain,
196 previous_primary_lag: prev_lag,
197 ltp_scaling_present: first,
198 lsf_interp_after_reset: first || prev_nlsf.is_none(),
199 previous_nlsf_q15: prev_nlsf,
200 previous_nlsf_len: prev_nlsf_len,
201 stereo: None,
202 };
203 let decoded = encode_silk_frame(&mut re, cfg, symbols)?;
204 prev_gain = Some(decoded.gains.last_log_gain());
205 prev_lag = Some(decoded.ltp.primary_lag());
206 prev_nlsf = Some(decoded.nlsf_q15);
207 prev_nlsf_len = decoded.d_lpc;
208 first = false;
209 predictions.push(decoded);
210 }
211
212 let body = re.finish();
215 let mut packet = Vec::with_capacity(1 + body.len());
216 packet.push(toc);
217 packet.extend_from_slice(&body);
218 Ok((packet, predictions, lbrr_predictions))
219}
220
221#[derive(Debug, Clone, Copy)]
237pub struct StereoIntervalScripts<'a> {
238 pub mid: SilkFrameSymbols<'a>,
241 pub side: Option<SilkFrameSymbols<'a>>,
244}
245
246#[derive(Debug, Clone)]
250pub struct StereoPacketPredictions {
251 pub mid: Vec<SilkFrameDecoded>,
253 pub side: Vec<Option<SilkFrameDecoded>>,
256}
257
258pub fn encode_silk_only_packet_stereo(
273 bandwidth: Bandwidth,
274 frame_size_tenths_ms: u16,
275 intervals: &[StereoIntervalScripts<'_>],
276) -> Result<(Vec<u8>, StereoPacketPredictions), Error> {
277 let n = silk_frame_count(frame_size_tenths_ms).ok_or(Error::MalformedPacket)? as usize;
278 let no_lbrr = vec![StereoIntervalLbrr::default(); n];
279 let (packet, regular, _) = encode_silk_only_packet_stereo_with_lbrr(
280 bandwidth,
281 frame_size_tenths_ms,
282 intervals,
283 &no_lbrr,
284 )?;
285 Ok((packet, regular))
286}
287
288#[derive(Debug, Clone, Copy, Default)]
304pub struct StereoIntervalLbrr<'a> {
305 pub mid: Option<SilkFrameSymbols<'a>>,
307 pub side: Option<SilkFrameSymbols<'a>>,
309}
310
311pub fn encode_silk_only_packet_stereo_with_lbrr(
322 bandwidth: Bandwidth,
323 frame_size_tenths_ms: u16,
324 intervals: &[StereoIntervalScripts<'_>],
325 lbrr: &[StereoIntervalLbrr<'_>],
326) -> Result<(Vec<u8>, StereoPacketPredictions, StereoLbrrPredictions), Error> {
327 let num_silk_frames = silk_frame_count(frame_size_tenths_ms).ok_or(Error::MalformedPacket)?;
328 if intervals.len() != num_silk_frames as usize || lbrr.len() != num_silk_frames as usize {
329 return Err(Error::MalformedPacket);
330 }
331 let frame_size = if frame_size_tenths_ms == 100 {
332 SilkFrameSize::TenMs
333 } else {
334 SilkFrameSize::TwentyMs
335 };
336
337 let toc = OpusTocByte::compose_byte(
339 Mode::SilkOnly,
340 bandwidth,
341 frame_size_tenths_ms,
342 true,
343 FrameCountCode::One,
344 )?;
345
346 let mut re = RangeEncoder::new();
347
348 let mut mid_vad_flags = 0u8;
353 let mut side_vad_flags = 0u8;
354 for (idx, iv) in intervals.iter().enumerate() {
355 if iv.mid.header.frame_type >= 2 {
356 mid_vad_flags |= 1 << idx;
357 }
358 if let Some(side) = &iv.side {
359 if side.header.frame_type >= 2 {
360 side_vad_flags |= 1 << idx;
361 }
362 }
363 }
364 let mut mid_lbrr_bits = 0u8;
365 let mut side_lbrr_bits = 0u8;
366 for (idx, l) in lbrr.iter().enumerate() {
367 if l.mid.is_some() {
368 mid_lbrr_bits |= 1 << idx;
369 }
370 if l.side.is_some() {
371 side_lbrr_bits |= 1 << idx;
372 }
373 }
374 let header = SilkHeaderBits {
375 num_silk_frames,
376 mid: SilkChannelHeader {
377 vad_flags: mid_vad_flags,
378 lbrr_flag: mid_lbrr_bits != 0,
379 },
380 side: Some(SilkChannelHeader {
381 vad_flags: side_vad_flags,
382 lbrr_flag: side_lbrr_bits != 0,
383 }),
384 per_frame_lbrr: PerFrameLbrr {
385 mid: mid_lbrr_bits,
386 side: side_lbrr_bits,
387 },
388 };
389 header.encode(&mut re)?;
390
391 let mut lbrr_mid_state = ChannelDecodeState::new();
396 let mut lbrr_side_state = ChannelDecodeState::new();
397 let mut lbrr_mid_pred: Vec<Option<SilkFrameDecoded>> = Vec::with_capacity(lbrr.len());
398 let mut lbrr_side_pred: Vec<Option<SilkFrameDecoded>> = Vec::with_capacity(lbrr.len());
399 for entry in lbrr.iter() {
400 let side_lbrr = entry.side.is_some();
401 if let Some(mid_sym) = &entry.mid {
402 if mid_sym.header.frame_type < 2 {
403 return Err(Error::MalformedPacket);
405 }
406 if !side_lbrr && mid_sym.header.mid_only_flag != Some(true) {
412 return Err(Error::MalformedPacket);
413 }
414 let stereo_ctx = StereoHeaderContext {
415 has_mid_only_flag: !side_lbrr,
416 };
417 let decoded = encode_silk_frame(
418 &mut re,
419 lbrr_mid_state.config(bandwidth, frame_size, true, Some(stereo_ctx)),
420 mid_sym,
421 )?;
422 lbrr_mid_state.advance(&decoded);
423 lbrr_mid_pred.push(Some(decoded));
424 } else {
425 lbrr_mid_pred.push(None);
426 }
427 if let Some(side_sym) = &entry.side {
428 if side_sym.header.frame_type < 2 {
429 return Err(Error::MalformedPacket);
430 }
431 let decoded = encode_silk_frame(
432 &mut re,
433 lbrr_side_state.config(bandwidth, frame_size, true, None),
434 side_sym,
435 )?;
436 lbrr_side_state.advance(&decoded);
437 lbrr_side_pred.push(Some(decoded));
438 } else {
439 lbrr_side_pred.push(None);
440 }
441 }
442
443 let mut mid_state = ChannelDecodeState::new();
446 let mut side_state = ChannelDecodeState::new();
447 let mut mid_pred: Vec<SilkFrameDecoded> = Vec::with_capacity(intervals.len());
448 let mut side_pred: Vec<Option<SilkFrameDecoded>> = Vec::with_capacity(intervals.len());
449 for (idx, iv) in intervals.iter().enumerate() {
450 let side_active = (side_vad_flags >> idx) & 1 == 1;
451 match iv.mid.header.mid_only_flag {
455 Some(flag) => {
456 if side_active || flag != iv.side.is_none() {
457 return Err(Error::MalformedPacket);
458 }
459 }
460 None => {
461 if !side_active || iv.side.is_none() {
463 return Err(Error::MalformedPacket);
464 }
465 }
466 }
467 let stereo_ctx = StereoHeaderContext {
468 has_mid_only_flag: !side_active,
469 };
470 let mid_decoded = encode_silk_frame(
471 &mut re,
472 mid_state.config(
473 bandwidth,
474 frame_size,
475 (mid_vad_flags >> idx) & 1 == 1,
476 Some(stereo_ctx),
477 ),
478 &iv.mid,
479 )?;
480 mid_state.advance(&mid_decoded);
481 mid_pred.push(mid_decoded);
482
483 if let Some(side_sym) = &iv.side {
484 let side_decoded = encode_silk_frame(
485 &mut re,
486 side_state.config(bandwidth, frame_size, side_active, None),
487 side_sym,
488 )?;
489 side_state.advance(&side_decoded);
490 side_pred.push(Some(side_decoded));
491 } else {
492 side_pred.push(None);
495 }
496 }
497
498 let body = re.finish();
500 let mut packet = Vec::with_capacity(1 + body.len());
501 packet.push(toc);
502 packet.extend_from_slice(&body);
503 Ok((
504 packet,
505 StereoPacketPredictions {
506 mid: mid_pred,
507 side: side_pred,
508 },
509 StereoLbrrPredictions {
510 mid: lbrr_mid_pred,
511 side: lbrr_side_pred,
512 },
513 ))
514}
515
516#[derive(Debug, Clone)]
519pub struct StereoLbrrPredictions {
520 pub mid: Vec<Option<SilkFrameDecoded>>,
522 pub side: Vec<Option<SilkFrameDecoded>>,
524}
525
526#[cfg(test)]
527mod tests {
528 use super::*;
529 use crate::decoder::{FrameDecodeStatus, OpusDecoder};
530 use crate::range_decoder::RangeDecoder;
531 use crate::silk_decode::decode_silk_frame;
532 use crate::silk_excitation::{shell_block_count, ExcitationSymbols, SHELL_BLOCK_SAMPLES};
533 use crate::silk_frame::SilkHeaderSymbols;
534 use crate::silk_gains::GainSymbol;
535 use crate::silk_ltp::{LagSymbols, LtpSymbols, LTP_MAX_SUBFRAMES};
536
537 struct Lcg(u64);
539 impl Lcg {
540 fn next_u32(&mut self) -> u32 {
541 self.0 = self
542 .0
543 .wrapping_mul(6364136223846793005)
544 .wrapping_add(1442695040888963407);
545 (self.0 >> 32) as u32
546 }
547 fn below(&mut self, n: u32) -> u32 {
548 self.next_u32() % n
549 }
550 }
551
552 struct ScriptBufs {
555 gains: Vec<GainSymbol>,
556 i2: Vec<i8>,
557 lsb_counts: Vec<u8>,
558 e_raw: Vec<i32>,
559 header: SilkHeaderSymbols,
560 lsf_stage1: u8,
561 lsf_interp_w_q2: Option<u8>,
562 ltp: Option<LtpSymbols>,
563 lcg_seed: u8,
564 rate_level: u8,
565 }
566
567 fn random_frame_script(
568 rng: &mut Lcg,
569 bandwidth: Bandwidth,
570 frame_size: SilkFrameSize,
571 first: bool,
572 has_prev_lag: bool,
573 ) -> ScriptBufs {
574 let num_subframes = if frame_size == SilkFrameSize::TenMs {
575 2usize
576 } else {
577 4
578 };
579 let frame_type = rng.below(6) as u8;
580 let voiced = frame_type >= 4;
581 let gains: Vec<GainSymbol> = (0..num_subframes)
582 .map(|k| {
583 if k == 0 && first {
584 GainSymbol::Independent(rng.below(64) as u8)
585 } else {
586 GainSymbol::Delta(rng.below(41) as u8)
587 }
588 })
589 .collect();
590 let d_lpc = if bandwidth == Bandwidth::Wb { 16 } else { 10 };
591 let i2: Vec<i8> = (0..d_lpc).map(|_| rng.below(21) as i8 - 10).collect();
592 let ltp = voiced.then(|| {
593 let lag_low_count = match bandwidth {
594 Bandwidth::Nb => 4u32,
595 Bandwidth::Mb => 6,
596 _ => 8,
597 };
598 let lag = if has_prev_lag {
599 if rng.below(2) == 0 {
600 LagSymbols::RelativeDelta {
601 delta_index: 1 + rng.below(20) as u8,
602 }
603 } else {
604 LagSymbols::RelativeFallback {
605 lag_high: rng.below(32) as u8,
606 lag_low: rng.below(lag_low_count) as u8,
607 }
608 }
609 } else {
610 LagSymbols::Absolute {
611 lag_high: rng.below(32) as u8,
612 lag_low: rng.below(lag_low_count) as u8,
613 }
614 };
615 let contour_cells = match (bandwidth, num_subframes) {
616 (Bandwidth::Nb, 2) => 3u32,
617 (Bandwidth::Nb, 4) => 11,
618 (_, 2) => 12,
619 _ => 34,
620 };
621 let periodicity_index = rng.below(3) as u8;
622 let filter_cells = [8u32, 16, 32][periodicity_index as usize];
623 let mut filter_indices = [0u8; LTP_MAX_SUBFRAMES];
624 for f in filter_indices.iter_mut().take(num_subframes) {
625 *f = rng.below(filter_cells) as u8;
626 }
627 LtpSymbols {
628 lag,
629 contour_index: rng.below(contour_cells) as u8,
630 periodicity_index,
631 filter_indices,
632 ltp_scaling_index: first.then(|| rng.below(3) as u8),
634 }
635 });
636 let blocks = shell_block_count(bandwidth, frame_size).unwrap();
637 let total = blocks * SHELL_BLOCK_SAMPLES;
638 let mut lsb_counts = vec![0u8; blocks];
639 let mut e_raw = vec![0i32; total];
640 for (b, lc) in lsb_counts.iter_mut().enumerate() {
641 let lsbs = if rng.below(4) == 0 { 1 } else { 0 };
642 *lc = lsbs as u8;
643 let budget = rng.below(17);
644 let base = b * SHELL_BLOCK_SAMPLES;
645 let mut spent = 0u32;
646 while spent < budget {
647 let i = base + rng.below(16) as usize;
648 let add = 1 + rng.below(budget - spent);
649 e_raw[i] += (add << lsbs) as i32;
650 spent += add;
651 }
652 for slot in e_raw[base..base + SHELL_BLOCK_SAMPLES].iter_mut() {
653 if lsbs > 0 {
654 *slot += (rng.next_u32() & 1) as i32;
655 }
656 if *slot != 0 && rng.below(2) == 0 {
657 *slot = -*slot;
658 }
659 }
660 }
661 ScriptBufs {
662 gains,
663 i2,
664 lsb_counts,
665 e_raw,
666 header: SilkHeaderSymbols {
667 stereo: None,
668 mid_only_flag: None,
669 frame_type,
670 },
671 lsf_stage1: rng.below(32) as u8,
672 lsf_interp_w_q2: (frame_size == SilkFrameSize::TwentyMs).then(|| rng.below(5) as u8),
673 ltp,
674 lcg_seed: rng.below(4) as u8,
675 rate_level: rng.below(9) as u8,
676 }
677 }
678
679 fn symbols_of(bufs: &ScriptBufs) -> SilkFrameSymbols<'_> {
680 SilkFrameSymbols {
681 header: bufs.header,
682 gains: &bufs.gains,
683 lsf_stage1: bufs.lsf_stage1,
684 lsf_stage2_i2: &bufs.i2,
685 lsf_interp_w_q2: bufs.lsf_interp_w_q2,
686 ltp: bufs.ltp,
687 lcg_seed: bufs.lcg_seed,
688 excitation: ExcitationSymbols {
689 rate_level: bufs.rate_level,
690 lsb_counts: &bufs.lsb_counts,
691 e_raw: &bufs.e_raw,
692 },
693 }
694 }
695
696 #[test]
703 fn packet_encode_decodes_end_to_end() {
704 let mut rng = Lcg(0x0AC4_E701);
705 for round in 0..120 {
706 let bandwidth = match rng.below(3) {
707 0 => Bandwidth::Nb,
708 1 => Bandwidth::Mb,
709 _ => Bandwidth::Wb,
710 };
711 let fs_tenths: u16 = [100u16, 200, 400, 600][rng.below(4) as usize];
712 let frame_size = if fs_tenths == 100 {
713 SilkFrameSize::TenMs
714 } else {
715 SilkFrameSize::TwentyMs
716 };
717 let n = silk_frame_count(fs_tenths).unwrap() as usize;
718 let bufs: Vec<ScriptBufs> = (0..n)
719 .map(|idx| random_frame_script(&mut rng, bandwidth, frame_size, idx == 0, idx > 0))
720 .collect();
721 let scripts: Vec<SilkFrameSymbols<'_>> = bufs.iter().map(symbols_of).collect();
722
723 let (packet, predictions) =
724 encode_silk_only_packet_mono(bandwidth, fs_tenths, &scripts)
725 .expect("packet encode");
726 assert_eq!(predictions.len(), n);
727
728 let mut dec = OpusDecoder::new();
730 let out = dec.decode_packet(&packet).expect("packet decode");
731 assert_eq!(out.channels, 1, "round {round}");
732 assert_eq!(out.frame_outcomes.len(), 1, "round {round}");
733 assert_eq!(
734 out.frame_outcomes[0].status,
735 FrameDecodeStatus::SilkParamsDecoded,
736 "round {round} bw={bandwidth:?} fs={fs_tenths}"
737 );
738 assert_eq!(
740 out.samples_per_channel() as u32,
741 48_000 * fs_tenths as u32 / 10_000,
742 "round {round}"
743 );
744
745 let mut rd = RangeDecoder::new(&packet[1..]);
748 let header = SilkHeaderBits::decode(&mut rd, n as u8, false).expect("header bits");
749 assert!(!header.mid.lbrr_flag);
750 let mut prev_gain: Option<u8> = None;
751 let mut prev_lag: Option<i32> = None;
752 let mut prev_nlsf: Option<[i16; crate::silk_lsf_stage2::D_LPC_MAX]> = None;
753 let mut prev_nlsf_len = 0usize;
754 let mut first = true;
755 for (idx, expected) in predictions.iter().enumerate() {
756 let cfg = SilkFrameConfig {
757 bandwidth,
758 frame_size,
759 voice_active: header.mid_vad(idx as u8),
760 first_subframe_independent: first || prev_gain.is_none(),
761 previous_log_gain: prev_gain,
762 previous_primary_lag: prev_lag,
763 ltp_scaling_present: first,
764 lsf_interp_after_reset: first || prev_nlsf.is_none(),
765 previous_nlsf_q15: prev_nlsf,
766 previous_nlsf_len: prev_nlsf_len,
767 stereo: None,
768 };
769 let decoded = decode_silk_frame(&mut rd, cfg).expect("frame decode");
770 assert_eq!(&decoded, expected, "round {round} frame {idx}");
771 prev_gain = Some(decoded.gains.last_log_gain());
772 prev_lag = Some(decoded.ltp.primary_lag());
773 prev_nlsf = Some(decoded.nlsf_q15);
774 prev_nlsf_len = decoded.d_lpc;
775 first = false;
776 }
777 assert!(!rd.has_error());
778 }
779 }
780
781 #[test]
787 fn packet_encode_with_lbrr_fec_roundtrip() {
788 use crate::decoder::FecDecodeStatus;
789 let mut rng = Lcg(0xFEC0_0382);
790 for round in 0..60 {
791 let bandwidth = match rng.below(3) {
792 0 => Bandwidth::Nb,
793 1 => Bandwidth::Mb,
794 _ => Bandwidth::Wb,
795 };
796 let fs_tenths: u16 = [100u16, 200, 400, 600][rng.below(4) as usize];
797 let frame_size = if fs_tenths == 100 {
798 SilkFrameSize::TenMs
799 } else {
800 SilkFrameSize::TwentyMs
801 };
802 let n = silk_frame_count(fs_tenths).unwrap() as usize;
803 let bufs: Vec<ScriptBufs> = (0..n)
804 .map(|idx| random_frame_script(&mut rng, bandwidth, frame_size, idx == 0, idx > 0))
805 .collect();
806 let scripts: Vec<SilkFrameSymbols<'_>> = bufs.iter().map(symbols_of).collect();
807
808 let mut which = vec![false; n];
813 which[rng.below(n as u32) as usize] = true;
814 for w in which.iter_mut() {
815 if rng.below(2) == 0 {
816 *w = true;
817 }
818 }
819 let mut lbrr_bufs: Vec<Option<ScriptBufs>> = Vec::with_capacity(n);
820 let mut coded_first = true;
821 for &w in &which {
822 if !w {
823 lbrr_bufs.push(None);
824 continue;
825 }
826 let mut b =
827 random_frame_script(&mut rng, bandwidth, frame_size, coded_first, !coded_first);
828 if b.header.frame_type < 2 {
832 b.header.frame_type += 2; }
834 lbrr_bufs.push(Some(b));
835 coded_first = false;
836 }
837 let lbrr_scripts: Vec<Option<SilkFrameSymbols<'_>>> = lbrr_bufs
838 .iter()
839 .map(|b| b.as_ref().map(symbols_of))
840 .collect();
841
842 let (packet, regular, lbrr_pred) = encode_silk_only_packet_mono_with_lbrr(
843 bandwidth,
844 fs_tenths,
845 &scripts,
846 &lbrr_scripts,
847 )
848 .expect("packet encode with lbrr");
849 assert_eq!(regular.len(), n);
850 assert_eq!(
851 lbrr_pred.iter().filter(|p| p.is_some()).count(),
852 which.iter().filter(|&&w| w).count()
853 );
854
855 let mut dec = OpusDecoder::new();
858 let out = dec.decode_packet(&packet).expect("packet decode");
859 assert_eq!(
860 out.frame_outcomes[0].status,
861 FrameDecodeStatus::SilkParamsDecoded,
862 "round {round} bw={bandwidth:?} fs={fs_tenths}"
863 );
864
865 let mut fec_dec = OpusDecoder::new();
867 let rec = fec_dec.decode_packet_fec(&packet).expect("fec decode");
868 assert_eq!(
869 rec.status,
870 FecDecodeStatus::Recovered,
871 "round {round} bw={bandwidth:?} fs={fs_tenths}"
872 );
873 assert_eq!(
874 rec.pcm.len() as u32,
875 48_000 * fs_tenths as u32 / 10_000,
876 "round {round}"
877 );
878 }
879
880 let bufs = random_frame_script(
882 &mut rng,
883 Bandwidth::Nb,
884 SilkFrameSize::TwentyMs,
885 true,
886 false,
887 );
888 let script = symbols_of(&bufs);
889 let (packet, _) =
890 encode_silk_only_packet_mono(Bandwidth::Nb, 200, &[script]).expect("encode");
891 let mut dec = OpusDecoder::new();
892 let rec = dec.decode_packet_fec(&packet).expect("fec decode");
893 assert_eq!(rec.status, FecDecodeStatus::NoLbrr);
894 }
895
896 use crate::silk_frame::StereoWeightSymbols;
897
898 fn random_weights(rng: &mut Lcg) -> StereoWeightSymbols {
899 StereoWeightSymbols {
900 n: rng.below(25) as u8,
901 i0: rng.below(3) as u8,
902 i1: rng.below(5) as u8,
903 i2: rng.below(3) as u8,
904 i3: rng.below(5) as u8,
905 }
906 }
907
908 #[derive(Clone, Copy, PartialEq)]
910 enum SidePattern {
911 Active,
914 InactiveCoded,
917 MidOnly,
919 }
920
921 #[allow(clippy::too_many_arguments)]
927 fn random_stereo_interval(
928 rng: &mut Lcg,
929 bandwidth: Bandwidth,
930 frame_size: SilkFrameSize,
931 pattern: SidePattern,
932 mid_first: bool,
933 mid_has_prev_lag: bool,
934 side_first: bool,
935 side_has_prev_lag: bool,
936 ) -> (ScriptBufs, Option<ScriptBufs>) {
937 let mut mid = random_frame_script(rng, bandwidth, frame_size, mid_first, mid_has_prev_lag);
938 mid.header.stereo = Some(random_weights(rng));
939 mid.header.mid_only_flag = match pattern {
940 SidePattern::Active => None,
941 SidePattern::InactiveCoded => Some(false),
942 SidePattern::MidOnly => Some(true),
943 };
944 let side = match pattern {
945 SidePattern::MidOnly => None,
946 SidePattern::Active => {
947 let mut s =
948 random_frame_script(rng, bandwidth, frame_size, side_first, side_has_prev_lag);
949 if s.header.frame_type < 2 {
950 s.header.frame_type += 2;
953 }
954 Some(s)
955 }
956 SidePattern::InactiveCoded => {
957 let mut s =
958 random_frame_script(rng, bandwidth, frame_size, side_first, side_has_prev_lag);
959 if s.header.frame_type >= 2 {
960 s.header.frame_type %= 2;
963 s.ltp = None;
964 }
965 Some(s)
966 }
967 };
968 (mid, side)
969 }
970
971 #[test]
977 fn stereo_packet_encode_decodes_end_to_end() {
978 let mut rng = Lcg(0x57E2_E001);
979 for round in 0..120 {
980 let bandwidth = match rng.below(3) {
981 0 => Bandwidth::Nb,
982 1 => Bandwidth::Mb,
983 _ => Bandwidth::Wb,
984 };
985 let fs_tenths: u16 = [100u16, 200, 400, 600][rng.below(4) as usize];
986 let frame_size = if fs_tenths == 100 {
987 SilkFrameSize::TenMs
988 } else {
989 SilkFrameSize::TwentyMs
990 };
991 let n = silk_frame_count(fs_tenths).unwrap() as usize;
992
993 let mut interval_bufs: Vec<(ScriptBufs, Option<ScriptBufs>)> = Vec::with_capacity(n);
994 let mut patterns: Vec<SidePattern> = Vec::with_capacity(n);
995 let mut side_first = true;
996 let mut side_has_prev = false;
997 for idx in 0..n {
998 let pattern = match rng.below(3) {
999 0 => SidePattern::Active,
1000 1 => SidePattern::InactiveCoded,
1001 _ => SidePattern::MidOnly,
1002 };
1003 let iv = random_stereo_interval(
1004 &mut rng,
1005 bandwidth,
1006 frame_size,
1007 pattern,
1008 idx == 0,
1009 idx > 0,
1010 side_first,
1011 side_has_prev,
1012 );
1013 if pattern != SidePattern::MidOnly {
1014 side_first = false;
1015 side_has_prev = true;
1016 }
1017 patterns.push(pattern);
1018 interval_bufs.push(iv);
1019 }
1020 let intervals: Vec<StereoIntervalScripts<'_>> = interval_bufs
1021 .iter()
1022 .map(|(m, s)| StereoIntervalScripts {
1023 mid: symbols_of(m),
1024 side: s.as_ref().map(symbols_of),
1025 })
1026 .collect();
1027
1028 let (packet, predictions) =
1029 encode_silk_only_packet_stereo(bandwidth, fs_tenths, &intervals)
1030 .expect("stereo packet encode");
1031 assert_eq!(predictions.mid.len(), n);
1032 assert_eq!(predictions.side.len(), n);
1033
1034 let mut dec = OpusDecoder::new();
1036 let out = dec.decode_packet(&packet).expect("packet decode");
1037 assert_eq!(out.channels, 2, "round {round}");
1038 assert_eq!(
1039 out.frame_outcomes[0].status,
1040 FrameDecodeStatus::SilkStereoDecoded,
1041 "round {round} bw={bandwidth:?} fs={fs_tenths}"
1042 );
1043 assert_eq!(
1044 out.samples_per_channel() as u32,
1045 48_000 * fs_tenths as u32 / 10_000,
1046 "round {round}"
1047 );
1048 assert_eq!(
1049 out.pcm.len() as u32,
1050 2 * 48_000 * fs_tenths as u32 / 10_000,
1051 "round {round}"
1052 );
1053
1054 let mut rd = RangeDecoder::new(&packet[1..]);
1057 let header = SilkHeaderBits::decode(&mut rd, n as u8, true).expect("header bits");
1058 assert!(!header.mid.lbrr_flag);
1059 assert!(header.side.is_some_and(|s| !s.lbrr_flag));
1060 let mut mid_state = crate::decoder::ChannelDecodeState::new();
1061 let mut side_state = crate::decoder::ChannelDecodeState::new();
1062 for (idx, pattern) in patterns.iter().enumerate() {
1063 let side_active = header.side_vad(idx as u8);
1064 assert_eq!(
1065 side_active,
1066 *pattern == SidePattern::Active,
1067 "round {round} interval {idx}"
1068 );
1069 let stereo_ctx = crate::silk_decode::StereoHeaderContext {
1070 has_mid_only_flag: !side_active,
1071 };
1072 let mid_decoded = decode_silk_frame(
1073 &mut rd,
1074 mid_state.config(
1075 bandwidth,
1076 frame_size,
1077 header.mid_vad(idx as u8),
1078 Some(stereo_ctx),
1079 ),
1080 )
1081 .expect("mid decode");
1082 assert_eq!(
1083 &mid_decoded, &predictions.mid[idx],
1084 "round {round} mid {idx}"
1085 );
1086 let side_coded = side_active || mid_decoded.mid_only_flag == Some(false);
1087 mid_state.advance(&mid_decoded);
1088 if side_coded {
1089 let side_decoded = decode_silk_frame(
1090 &mut rd,
1091 side_state.config(bandwidth, frame_size, side_active, None),
1092 )
1093 .expect("side decode");
1094 assert_eq!(
1095 Some(&side_decoded),
1096 predictions.side[idx].as_ref(),
1097 "round {round} side {idx}"
1098 );
1099 side_state.advance(&side_decoded);
1100 } else {
1101 assert!(predictions.side[idx].is_none(), "round {round} side {idx}");
1102 }
1103 }
1104 assert!(!rd.has_error());
1105 }
1106 }
1107
1108 #[test]
1114 fn stereo_packet_encode_with_lbrr_fec_roundtrip() {
1115 use crate::decoder::FecDecodeStatus;
1116 let mut rng = Lcg(0xFEC0_57E2);
1117 for round in 0..60 {
1118 let bandwidth = match rng.below(3) {
1119 0 => Bandwidth::Nb,
1120 1 => Bandwidth::Mb,
1121 _ => Bandwidth::Wb,
1122 };
1123 let fs_tenths: u16 = [100u16, 200, 400, 600][rng.below(4) as usize];
1124 let frame_size = if fs_tenths == 100 {
1125 SilkFrameSize::TenMs
1126 } else {
1127 SilkFrameSize::TwentyMs
1128 };
1129 let n = silk_frame_count(fs_tenths).unwrap() as usize;
1130
1131 let mut interval_bufs: Vec<(ScriptBufs, Option<ScriptBufs>)> = Vec::with_capacity(n);
1134 for idx in 0..n {
1135 interval_bufs.push(random_stereo_interval(
1136 &mut rng,
1137 bandwidth,
1138 frame_size,
1139 SidePattern::Active,
1140 idx == 0,
1141 idx > 0,
1142 idx == 0,
1143 idx > 0,
1144 ));
1145 }
1146 let intervals: Vec<StereoIntervalScripts<'_>> = interval_bufs
1147 .iter()
1148 .map(|(m, s)| StereoIntervalScripts {
1149 mid: symbols_of(m),
1150 side: s.as_ref().map(symbols_of),
1151 })
1152 .collect();
1153
1154 let mut kinds = vec![0u32; n];
1157 kinds[rng.below(n as u32) as usize] = 1 + rng.below(3);
1158 for k in kinds.iter_mut() {
1159 if *k == 0 && rng.below(2) == 0 {
1160 *k = 1 + rng.below(3);
1161 }
1162 }
1163 let mut lbrr_bufs: Vec<(Option<ScriptBufs>, Option<ScriptBufs>)> =
1164 Vec::with_capacity(n);
1165 let mut mid_first = true;
1166 let mut mid_prev = false;
1167 let mut side_first = true;
1168 let mut side_prev = false;
1169 for &kind in &kinds {
1170 let want_mid = kind == 1 || kind == 2;
1171 let want_side = kind == 2 || kind == 3;
1172 let mid = want_mid.then(|| {
1173 let mut b =
1174 random_frame_script(&mut rng, bandwidth, frame_size, mid_first, mid_prev);
1175 if b.header.frame_type < 2 {
1176 b.header.frame_type += 2; }
1178 b.header.stereo = Some(random_weights(&mut rng));
1179 b.header.mid_only_flag = (!want_side).then_some(true);
1180 mid_first = false;
1181 mid_prev = true;
1182 b
1183 });
1184 let side = want_side.then(|| {
1185 let mut b =
1186 random_frame_script(&mut rng, bandwidth, frame_size, side_first, side_prev);
1187 if b.header.frame_type < 2 {
1188 b.header.frame_type += 2;
1189 }
1190 side_first = false;
1191 side_prev = true;
1192 b
1193 });
1194 lbrr_bufs.push((mid, side));
1195 }
1196 let lbrr_scripts: Vec<StereoIntervalLbrr<'_>> = lbrr_bufs
1197 .iter()
1198 .map(|(m, s)| StereoIntervalLbrr {
1199 mid: m.as_ref().map(symbols_of),
1200 side: s.as_ref().map(symbols_of),
1201 })
1202 .collect();
1203
1204 let (packet, regular, lbrr_pred) = encode_silk_only_packet_stereo_with_lbrr(
1205 bandwidth,
1206 fs_tenths,
1207 &intervals,
1208 &lbrr_scripts,
1209 )
1210 .expect("stereo packet encode with lbrr");
1211 assert_eq!(regular.mid.len(), n);
1212 assert_eq!(
1213 lbrr_pred.mid.iter().filter(|p| p.is_some()).count(),
1214 kinds.iter().filter(|&&k| k == 1 || k == 2).count()
1215 );
1216 assert_eq!(
1217 lbrr_pred.side.iter().filter(|p| p.is_some()).count(),
1218 kinds.iter().filter(|&&k| k == 2 || k == 3).count()
1219 );
1220
1221 let mut dec = OpusDecoder::new();
1224 let out = dec.decode_packet(&packet).expect("packet decode");
1225 assert_eq!(
1226 out.frame_outcomes[0].status,
1227 FrameDecodeStatus::SilkStereoDecoded,
1228 "round {round} bw={bandwidth:?} fs={fs_tenths} kinds={kinds:?}"
1229 );
1230
1231 let any_mid_lbrr = kinds.iter().any(|&k| k == 1 || k == 2);
1238 let mut fec_dec = OpusDecoder::new();
1239 let rec = fec_dec.decode_packet_fec(&packet).expect("fec decode");
1240 assert_eq!(
1241 rec.status,
1242 if any_mid_lbrr {
1243 FecDecodeStatus::Recovered
1244 } else {
1245 FecDecodeStatus::NoLbrr
1246 },
1247 "round {round} bw={bandwidth:?} fs={fs_tenths} kinds={kinds:?}"
1248 );
1249 assert_eq!(rec.channels, 2, "round {round}");
1250 assert_eq!(
1251 rec.pcm.len() as u32,
1252 2 * 48_000 * fs_tenths as u32 / 10_000,
1253 "round {round}"
1254 );
1255 }
1256 }
1257
1258 #[test]
1263 fn stereo_packet_encode_rejects_inconsistent_scripts() {
1264 let mut rng = Lcg(0xBAD5_7E2E);
1265 let (mid, side) = random_stereo_interval(
1266 &mut rng,
1267 Bandwidth::Wb,
1268 SilkFrameSize::TwentyMs,
1269 SidePattern::Active,
1270 true,
1271 false,
1272 true,
1273 false,
1274 );
1275 let side = side.unwrap();
1276
1277 let iv = StereoIntervalScripts {
1279 mid: symbols_of(&mid),
1280 side: Some(symbols_of(&side)),
1281 };
1282 assert!(encode_silk_only_packet_stereo(Bandwidth::Wb, 400, &[iv]).is_err());
1283
1284 let mut mid_no_w = symbols_of(&mid);
1286 mid_no_w.header.stereo = None;
1287 let iv = StereoIntervalScripts {
1288 mid: mid_no_w,
1289 side: Some(symbols_of(&side)),
1290 };
1291 assert!(encode_silk_only_packet_stereo(Bandwidth::Wb, 200, &[iv]).is_err());
1292
1293 let mut mid_bad_flag = symbols_of(&mid);
1295 mid_bad_flag.header.mid_only_flag = Some(false);
1296 let iv = StereoIntervalScripts {
1297 mid: mid_bad_flag,
1298 side: Some(symbols_of(&side)),
1299 };
1300 assert!(encode_silk_only_packet_stereo(Bandwidth::Wb, 200, &[iv]).is_err());
1301
1302 let (mid_mo, _) = random_stereo_interval(
1307 &mut rng,
1308 Bandwidth::Wb,
1309 SilkFrameSize::TwentyMs,
1310 SidePattern::MidOnly,
1311 true,
1312 false,
1313 true,
1314 false,
1315 );
1316 let mut side_inactive = random_frame_script(
1317 &mut rng,
1318 Bandwidth::Wb,
1319 SilkFrameSize::TwentyMs,
1320 true,
1321 false,
1322 );
1323 if side_inactive.header.frame_type >= 2 {
1324 side_inactive.header.frame_type %= 2;
1325 side_inactive.ltp = None;
1326 }
1327 let iv = StereoIntervalScripts {
1328 mid: symbols_of(&mid_mo),
1329 side: Some(symbols_of(&side_inactive)),
1330 };
1331 assert!(encode_silk_only_packet_stereo(Bandwidth::Wb, 200, &[iv]).is_err());
1332
1333 let mut side_with_w = symbols_of(&side);
1336 side_with_w.header.stereo = Some(random_weights(&mut rng));
1337 let iv = StereoIntervalScripts {
1338 mid: symbols_of(&mid),
1339 side: Some(side_with_w),
1340 };
1341 assert!(encode_silk_only_packet_stereo(Bandwidth::Wb, 200, &[iv]).is_err());
1342
1343 let (mid_ok, side_ok) = random_stereo_interval(
1345 &mut rng,
1346 Bandwidth::Wb,
1347 SilkFrameSize::TwentyMs,
1348 SidePattern::Active,
1349 true,
1350 false,
1351 true,
1352 false,
1353 );
1354 let side_ok = side_ok.unwrap();
1355 let mut lbrr_mid = random_frame_script(
1356 &mut rng,
1357 Bandwidth::Wb,
1358 SilkFrameSize::TwentyMs,
1359 true,
1360 false,
1361 );
1362 if lbrr_mid.header.frame_type >= 2 {
1363 lbrr_mid.header.frame_type %= 2;
1364 lbrr_mid.ltp = None;
1365 }
1366 lbrr_mid.header.stereo = Some(random_weights(&mut rng));
1367 lbrr_mid.header.mid_only_flag = Some(true);
1368 let iv = StereoIntervalScripts {
1369 mid: symbols_of(&mid_ok),
1370 side: Some(symbols_of(&side_ok)),
1371 };
1372 let lbrr = StereoIntervalLbrr {
1373 mid: Some(symbols_of(&lbrr_mid)),
1374 side: None,
1375 };
1376 assert!(
1377 encode_silk_only_packet_stereo_with_lbrr(Bandwidth::Wb, 200, &[iv], &[lbrr]).is_err()
1378 );
1379
1380 let mut lbrr_mid_bad = random_frame_script(
1382 &mut rng,
1383 Bandwidth::Wb,
1384 SilkFrameSize::TwentyMs,
1385 true,
1386 false,
1387 );
1388 if lbrr_mid_bad.header.frame_type < 2 {
1389 lbrr_mid_bad.header.frame_type += 2;
1390 }
1391 lbrr_mid_bad.header.stereo = Some(random_weights(&mut rng));
1392 lbrr_mid_bad.header.mid_only_flag = Some(false);
1393 let iv = StereoIntervalScripts {
1394 mid: symbols_of(&mid_ok),
1395 side: Some(symbols_of(&side_ok)),
1396 };
1397 let lbrr = StereoIntervalLbrr {
1398 mid: Some(symbols_of(&lbrr_mid_bad)),
1399 side: None,
1400 };
1401 assert!(
1402 encode_silk_only_packet_stereo_with_lbrr(Bandwidth::Wb, 200, &[iv], &[lbrr]).is_err()
1403 );
1404 }
1405
1406 #[test]
1408 fn packet_encode_rejects_bad_shape() {
1409 let mut rng = Lcg(7);
1410 let bufs = random_frame_script(
1411 &mut rng,
1412 Bandwidth::Nb,
1413 SilkFrameSize::TwentyMs,
1414 true,
1415 false,
1416 );
1417 let script = symbols_of(&bufs);
1418 assert!(encode_silk_only_packet_mono(Bandwidth::Nb, 400, &[script]).is_err());
1420 let script = symbols_of(&bufs);
1422 assert!(encode_silk_only_packet_mono(Bandwidth::Nb, 25, &[script]).is_err());
1423 let script = symbols_of(&bufs);
1425 assert!(encode_silk_only_packet_mono(Bandwidth::Swb, 200, &[script]).is_err());
1426 }
1427}