1#![allow(unsafe_op_in_unsafe_fn)]
2#![allow(clippy::too_many_arguments)]
3#![allow(clippy::needless_range_loop)]
4
5pub mod bands;
6pub mod celt;
7pub mod celt_lpc;
8pub mod hp_cutoff;
9pub mod kiss_fft;
10pub mod mdct;
11pub mod modes;
12pub mod pitch;
13pub mod pvq;
14pub mod quant_bands;
15pub mod range_coder;
16pub mod rate;
17pub mod silk;
18
19pub use silk::{SilkResampler, SilkResamplerDown1_3, SilkResamplerDown1_6};
20
21pub use celt::{CeltDecoder, CeltEncoder};
22use hp_cutoff::hp_cutoff;
23use range_coder::RangeCoder;
24use silk::control_codec::silk_control_encoder;
25use silk::enc_api::silk_encode;
26use silk::init_encoder::silk_init_encoder;
27use silk::lin2log::silk_lin2log;
28use silk::log2lin::silk_log2lin;
29use silk::macros::*;
30use silk::resampler::{silk_resampler_down2, silk_resampler_down2_3};
31use silk::structs::SilkEncoderState;
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34pub enum Application {
35 Voip = 2048,
36 Audio = 2049,
37 RestrictedLowDelay = 2051,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub enum Bandwidth {
42 Auto = -1000,
43 Narrowband = 1101,
44 Mediumband = 1102,
45 Wideband = 1103,
46 Superwideband = 1104,
47 Fullband = 1105,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51enum OpusMode {
52 SilkOnly,
53 Hybrid,
54 CeltOnly,
55}
56
57pub struct OpusEncoder {
58 celt_enc: CeltEncoder,
59 silk_enc: Box<SilkEncoderState>,
60 application: Application,
61 sampling_rate: i32,
62 channels: usize,
63 bandwidth: Bandwidth,
64 pub bitrate_bps: i32,
65 pub complexity: i32,
66 pub use_cbr: bool,
67
68 pub use_inband_fec: bool,
69
70 pub packet_loss_perc: i32,
71 silk_initialized: bool,
72 mode: OpusMode,
73 prev_enc_mode: Option<OpusMode>,
74
75 variable_hp_smth2_q15: i32,
76 hp_mem: Vec<i32>,
77
78 buf_filtered: Vec<i16>,
79 buf_silk_input: Vec<i16>,
80 buf_stereo_mid: Vec<i16>,
81 buf_stereo_side: Vec<i16>,
82 buf_celt_input: Vec<f32>,
83 down2_state_first: [i32; 2],
84 down2_state_second: [i32; 2],
85 down2_3_state: [i32; 6],
86 down_1_3_state: silk::resampler::SilkResamplerDown1_3,
87
88 rc: RangeCoder,
89}
90
91fn compute_equiv_rate(
92 bitrate: i32,
93 channels: usize,
94 frame_rate: i32,
95 vbr: bool,
96 complexity: i32,
97 loss: i32,
98) -> i32 {
99 let mut equiv = bitrate;
100 if frame_rate > 50 {
101 equiv -= (40 * channels as i32 + 20) * (frame_rate - 50);
102 }
103 if !vbr {
104 equiv -= equiv / 12;
105 }
106 equiv = equiv * (90 + complexity) / 100;
107 if loss > 0 {
108 equiv -= equiv * loss / (12 * loss + 20);
109 }
110 equiv
111}
112
113fn compute_mode_threshold(
114 application: Application,
115 channels: usize,
116 prev_was_celt: bool,
117 has_prev_mode: bool,
118 voice_est: i32,
119) -> i32 {
120 let mode_voice = if channels == 1 { 64000 } else { 44000 };
121 let mode_music = 10000;
122
123 let diff = mode_voice - mode_music;
124 let offset = (voice_est * voice_est * diff) >> 14;
125 let mut threshold = mode_music + offset;
126
127 if application == Application::Voip {
128 threshold += 8000;
129 }
130
131 if has_prev_mode {
132 if prev_was_celt {
133 threshold -= 4000;
134 } else {
135 threshold += 4000;
136 }
137 }
138
139 if application == Application::RestrictedLowDelay {
140 threshold = 0;
141 }
142
143 threshold
144}
145
146fn compute_silk_rate_for_hybrid(rate_bps: i32, frame20ms: bool) -> i32 {
147 const RATE_TABLE: &[(i32, i32, i32)] = &[
148 (0, 0, 0),
149 (12000, 10000, 10000),
150 (16000, 13500, 13500),
151 (20000, 16000, 16000),
152 (24000, 18000, 18000),
153 (32000, 22000, 22000),
154 (64000, 38000, 38000),
155 ];
156 let n = RATE_TABLE.len();
157 let mut i = 1;
158 while i < n && RATE_TABLE[i].0 <= rate_bps {
159 i += 1;
160 }
161 if i == n {
162 let (x_last, r10_last, r20_last) = RATE_TABLE[n - 1];
163 let base = if frame20ms { r20_last } else { r10_last };
164 base + (rate_bps - x_last) / 2
165 } else {
166 let (x0, lo10, lo20) = RATE_TABLE[i - 1];
167 let (x1, hi10, hi20) = RATE_TABLE[i];
168 let (lo, hi) = if frame20ms {
169 (lo20, hi20)
170 } else {
171 (lo10, hi10)
172 };
173 (lo * (x1 - rate_bps) + hi * (rate_bps - x0)) / (x1 - x0)
174 }
175}
176
177#[cfg(test)]
178mod silk_rate_tests {
179 use super::compute_silk_rate_for_hybrid;
180
181 #[test]
182 fn test_reference_table_exact_entries() {
183 assert_eq!(compute_silk_rate_for_hybrid(12000, true), 10000);
184 assert_eq!(compute_silk_rate_for_hybrid(16000, true), 13500);
185 assert_eq!(compute_silk_rate_for_hybrid(20000, true), 16000);
186 assert_eq!(compute_silk_rate_for_hybrid(24000, true), 18000);
187 assert_eq!(compute_silk_rate_for_hybrid(32000, true), 22000);
188 assert_eq!(compute_silk_rate_for_hybrid(64000, true), 38000);
189 }
190
191 #[test]
192 fn test_32kbps_gives_22kbps_silk() {
193 assert_eq!(compute_silk_rate_for_hybrid(32000, true), 22000);
194 }
195
196 #[test]
197 fn test_interpolation_between_table_entries() {
198 let r = compute_silk_rate_for_hybrid(18000, true);
199 assert_eq!(r, 14750);
200 }
201
202 #[test]
203 fn test_above_table_max_gives_half_extra() {
204 let r = compute_silk_rate_for_hybrid(72000, true);
205 assert_eq!(r, 38000 + (72000 - 64000) / 2);
206 }
207}
208
209impl OpusEncoder {
210 pub fn new(
211 sampling_rate: i32,
212 channels: usize,
213 application: Application,
214 ) -> Result<Self, &'static str> {
215 if ![8000, 12000, 16000, 24000, 48000].contains(&sampling_rate) {
216 return Err("Invalid sampling rate");
217 }
218 if ![1, 2].contains(&channels) {
219 return Err("Invalid number of channels");
220 }
221
222 let mode = modes::default_mode();
223 let celt_enc = CeltEncoder::new(mode, channels);
224
225 let mut silk_enc = Box::new(SilkEncoderState::default());
226 if silk_init_encoder(&mut silk_enc, 0) != 0 {
227 return Err("SILK encoder initialization failed");
228 }
229
230 let (opus_mode, bw) = match application {
231 Application::Voip => {
232 let bw = match sampling_rate {
233 8000 => Bandwidth::Narrowband,
234 12000 => Bandwidth::Mediumband,
235 16000 => Bandwidth::Wideband,
236 24000 => Bandwidth::Superwideband,
237 48000 => Bandwidth::Fullband,
238 _ => Bandwidth::Narrowband,
239 };
240
241 let mode = if sampling_rate > 16000 {
242 OpusMode::Hybrid
243 } else {
244 OpusMode::SilkOnly
245 };
246 (mode, bw)
247 }
248 Application::RestrictedLowDelay => {
249 let bw = match sampling_rate {
250 8000 => Bandwidth::Narrowband,
251 12000 => Bandwidth::Mediumband,
252 16000 => Bandwidth::Wideband,
253 24000 => Bandwidth::Superwideband,
254 _ => Bandwidth::Fullband,
255 };
256 (OpusMode::CeltOnly, bw)
257 }
258 Application::Audio => {
259 if sampling_rate <= 16000 {
260 let bw = match sampling_rate {
261 8000 => Bandwidth::Narrowband,
262 12000 => Bandwidth::Mediumband,
263 _ => Bandwidth::Wideband,
264 };
265 (OpusMode::SilkOnly, bw)
266 } else {
267 let bw = match sampling_rate {
268 24000 => Bandwidth::Superwideband,
269 _ => Bandwidth::Fullband,
270 };
271 (OpusMode::Hybrid, bw)
272 }
273 }
274 };
275
276 use silk::lin2log::silk_lin2log;
277 let variable_hp_smth2_q15 = silk_lin2log(60) << 8;
278
279 Ok(Self {
280 celt_enc,
281 silk_enc,
282 application,
283 sampling_rate,
284 channels,
285 bandwidth: bw,
286 bitrate_bps: 64000,
287 complexity: 9,
288 use_cbr: false,
289 use_inband_fec: false,
290 packet_loss_perc: 0,
291 silk_initialized: false,
292 prev_enc_mode: None,
293 mode: opus_mode,
294 variable_hp_smth2_q15,
295 hp_mem: vec![0; channels * 2],
296
297 buf_filtered: Vec::new(),
298 buf_silk_input: Vec::new(),
299 buf_stereo_mid: Vec::new(),
300 buf_stereo_side: Vec::new(),
301 buf_celt_input: Vec::new(),
302 down2_state_first: [0; 2],
303 down2_state_second: [0; 2],
304 down2_3_state: [0; 6],
305 down_1_3_state: silk::resampler::SilkResamplerDown1_3::default(),
306 rc: RangeCoder::new_encoder(1),
307 })
308 }
309
310 pub fn enable_hybrid_mode(&mut self) -> Result<(), &'static str> {
311 if self.sampling_rate != 24000 && self.sampling_rate != 48000 {
312 return Err("Hybrid mode requires 24kHz or 48kHz sampling rate");
313 }
314 let bw = if self.sampling_rate == 48000 {
315 Bandwidth::Fullband
316 } else {
317 Bandwidth::Superwideband
318 };
319 self.mode = OpusMode::Hybrid;
320 self.bandwidth = bw;
321 self.silk_initialized = false;
322 Ok(())
323 }
324
325 pub fn encode(
326 &mut self,
327 input: &[f32],
328 frame_size: usize,
329 output: &mut [u8],
330 ) -> Result<usize, &'static str> {
331 if output.len() < 2 {
332 return Err("Output buffer too small");
333 }
334
335 let frame_rate = frame_rate_from_params(self.sampling_rate, frame_size)
336 .ok_or("Invalid frame size for sampling rate")?;
337
338 let mut mode = if self.application == Application::RestrictedLowDelay {
342 OpusMode::CeltOnly
343 } else {
344 let equiv = compute_equiv_rate(
345 self.bitrate_bps,
346 self.channels,
347 frame_rate,
348 !self.use_cbr,
349 self.complexity,
350 self.packet_loss_perc,
351 );
352 let prev_was_celt = self.prev_enc_mode == Some(OpusMode::CeltOnly);
353 let has_prev_mode = self.prev_enc_mode.is_some();
354 let voice_est = match self.application {
355 Application::Voip => 115,
356 Application::Audio => 48,
357 Application::RestrictedLowDelay => 0,
358 };
359 let threshold = compute_mode_threshold(
360 self.application,
361 self.channels,
362 prev_was_celt,
363 has_prev_mode,
364 voice_est,
365 );
366 if equiv >= threshold && self.sampling_rate >= 24000 {
367 OpusMode::CeltOnly
368 } else {
369 OpusMode::SilkOnly
370 }
371 };
372
373 let curr_bw = self.bandwidth;
374 if mode == OpusMode::SilkOnly
375 && (curr_bw == Bandwidth::Superwideband || curr_bw == Bandwidth::Fullband)
376 {
377 mode = OpusMode::Hybrid;
378 }
379 if mode == OpusMode::Hybrid
380 && (curr_bw == Bandwidth::Narrowband
381 || curr_bw == Bandwidth::Mediumband
382 || curr_bw == Bandwidth::Wideband)
383 {
384 mode = OpusMode::SilkOnly;
385 }
386
387 if mode == OpusMode::CeltOnly {
388 match frame_rate {
389 400 | 200 | 100 | 50 => {}
390 _ => return Err("Unsupported frame size for CELT-only mode"),
391 }
392 }
393
394 if mode == OpusMode::Hybrid {
395 match frame_rate {
396 100 | 50 => {}
397 _ => return Err("Unsupported frame size for Hybrid mode"),
398 }
399 }
400
401 if mode == OpusMode::SilkOnly {
402 match frame_rate {
403 400 | 200 | 100 | 50 | 25 => {}
404 _ => return Err("Unsupported frame size for SILK-only mode"),
405 }
406 }
407
408 let toc = gen_toc(mode, frame_rate, self.bandwidth, self.channels);
409 output[0] = toc;
410
411 let target_bits =
412 (self.bitrate_bps as i64 * frame_size as i64 / self.sampling_rate as i64) as i32;
413 let cbr_bytes = ((target_bits + 4) / 8) as usize;
414 let max_data_bytes = output.len();
415
416 let n_bytes = cbr_bytes.min(max_data_bytes).max(1);
417
418 let init_rc_size = n_bytes - 1;
419 self.rc.reset_for_encode(init_rc_size as u32);
420
421 if mode == OpusMode::SilkOnly || mode == OpusMode::Hybrid {
422 let silk_fs_khz = if mode == OpusMode::Hybrid {
423 16
424 } else {
425 self.sampling_rate.min(16000) / 1000
426 };
427
428 let frame_ms = (frame_size as i32 * 1000) / self.sampling_rate;
429 if !self.silk_initialized || self.silk_enc.s_cmn.fs_khz != silk_fs_khz {
430 let silk_init_bitrate = (((n_bytes - 1) * 8) as i64 * self.sampling_rate as i64
431 / frame_size as i64) as i32;
432 silk_control_encoder(
433 &mut self.silk_enc,
434 silk_fs_khz,
435 frame_ms,
436 silk_init_bitrate,
437 self.complexity,
438 );
439 self.silk_enc.s_cmn.use_cbr = if self.use_cbr { 1 } else { 0 };
440
441 self.silk_enc.s_cmn.n_channels = self.channels as i32;
442 self.silk_initialized = true;
443 self.down2_state_first = [0; 2];
444 self.down2_state_second = [0; 2];
445 self.down2_3_state = [0; 6];
446 self.down_1_3_state = silk::resampler::SilkResamplerDown1_3::default();
447 }
448
449 self.silk_enc.s_cmn.use_in_band_fec = if self.use_inband_fec { 1 } else { 0 };
450 self.silk_enc.s_cmn.packet_loss_perc = self.packet_loss_perc.clamp(0, 100);
451
452 self.silk_enc.s_cmn.lbrr_enabled = if self.use_inband_fec { 1 } else { 0 };
453
454 if self.silk_enc.s_cmn.lbrr_gain_increases == 0 {
455 self.silk_enc.s_cmn.lbrr_gain_increases = 2;
456 }
457
458 let hp_freq_smth1 = if mode == OpusMode::CeltOnly {
459 silk_lin2log(60) << 8
460 } else {
461 self.silk_enc.s_cmn.variable_hp_smth1_q15
462 };
463
464 const VARIABLE_HP_SMTH_COEF2_Q16: i32 = 984;
465 self.variable_hp_smth2_q15 = silk_smlawb(
466 self.variable_hp_smth2_q15,
467 hp_freq_smth1 - self.variable_hp_smth2_q15,
468 VARIABLE_HP_SMTH_COEF2_Q16,
469 );
470
471 let cutoff_hz = silk_log2lin(silk_rshift(self.variable_hp_smth2_q15, 8));
472
473 let required_size = frame_size * self.channels;
474 self.buf_filtered.resize(required_size, 0);
475 if self.application == Application::Voip {
476 hp_cutoff(
477 input,
478 cutoff_hz,
479 &mut self.buf_filtered,
480 &mut self.hp_mem,
481 frame_size,
482 self.channels,
483 self.sampling_rate,
484 );
485 } else {
486 for (i, &x) in input.iter().enumerate() {
487 self.buf_filtered[i] = (x * 32768.0).clamp(-32768.0, 32767.0) as i16;
488 }
489 }
490
491 let input_i16 = &self.buf_filtered;
492
493 let silk_input: &[i16] = if mode == OpusMode::SilkOnly && self.sampling_rate > 16000 {
494 if self.sampling_rate == 48000 {
495 let stage1_size = frame_size / 2;
496 let mut stage1_buf = [0i16; 480];
497 silk_resampler_down2(
498 &mut self.down2_state_first,
499 &mut stage1_buf[..stage1_size],
500 input_i16,
501 frame_size as i32,
502 );
503 let silk_frame_size = stage1_size * 2 / 3;
504 self.buf_silk_input.resize(silk_frame_size, 0);
505 silk_resampler_down2_3(
506 &mut self.down2_3_state,
507 &mut self.buf_silk_input,
508 &stage1_buf[..stage1_size],
509 stage1_size as i32,
510 );
511 &self.buf_silk_input
512 } else if self.sampling_rate == 24000 {
513 let silk_frame_size = frame_size * 2 / 3;
514 self.buf_silk_input.resize(silk_frame_size, 0);
515 silk_resampler_down2_3(
516 &mut self.down2_3_state,
517 &mut self.buf_silk_input,
518 input_i16,
519 frame_size as i32,
520 );
521 &self.buf_silk_input
522 } else {
523 input_i16
524 }
525 } else if mode == OpusMode::SilkOnly && self.channels == 2 {
526 let frame_length = input_i16.len() / 2;
527 self.buf_stereo_mid.resize(frame_length, 0);
528 self.buf_stereo_side.resize(frame_length, 0);
529 for i in 0..frame_length {
530 let l = input_i16[2 * i] as i32;
531 let r = input_i16[2 * i + 1] as i32;
532 self.buf_stereo_mid[i] = ((l + r) / 2) as i16;
533 self.buf_stereo_side[i] = (l - r) as i16;
534 }
535
536 self.silk_enc.stereo.side.resize(frame_length, 0);
537 self.silk_enc
538 .stereo
539 .side
540 .copy_from_slice(&self.buf_stereo_side[..frame_length]);
541 &self.buf_stereo_mid
542 } else if mode == OpusMode::Hybrid && self.sampling_rate > 16000 {
543 if self.sampling_rate == 48000 {
544 let silk_frame_size = frame_size / 3;
545 self.buf_silk_input.resize(silk_frame_size, 0);
546 silk::resampler::silk_resampler_down_1_3(
547 &mut self.down_1_3_state,
548 &mut self.buf_silk_input,
549 input_i16,
550 );
551 } else {
552 let silk_frame_size = frame_size * 2 / 3;
553 self.buf_silk_input.resize(silk_frame_size, 0);
554 silk_resampler_down2_3(
555 &mut self.down2_3_state,
556 &mut self.buf_silk_input,
557 input_i16,
558 frame_size as i32,
559 );
560 }
561 &self.buf_silk_input
562 } else {
563 input_i16
564 };
565
566 let mut pn_bytes = 0;
567
568 let silk_rate_for_calc = if mode == OpusMode::Hybrid {
569 16000
570 } else {
571 self.sampling_rate
572 };
573 let silk_frame_len = silk_input.len();
574
575 let silk_bitrate = if mode == OpusMode::Hybrid {
576 let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
577 let frame20ms = frame_duration_ms >= 20;
578 compute_silk_rate_for_hybrid(self.bitrate_bps, frame20ms)
579 } else {
580 (8i64 * (n_bytes - 1) as i64 * silk_rate_for_calc as i64 / silk_frame_len as i64)
581 as i32
582 };
583 let silk_max_bits = if mode == OpusMode::Hybrid {
584 let total_max_bits = ((n_bytes - 1) * 8) as i32;
585 if self.use_cbr {
586 let silk_bits = (silk_bitrate as i64 * silk_frame_len as i64
587 / silk_rate_for_calc as i64) as i32;
588 let other_bits = 0i32.max(total_max_bits - silk_bits);
589 0i32.max(total_max_bits - other_bits * 3 / 4)
590 } else {
591 let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
592 let frame20ms = frame_duration_ms >= 20;
593 let max_bit_rate = compute_silk_rate_for_hybrid(
594 total_max_bits * self.sampling_rate / frame_size as i32,
595 frame20ms,
596 );
597 max_bit_rate * frame_size as i32 / self.sampling_rate
598 }
599 } else {
600 ((n_bytes - 1) * 8) as i32
601 };
602 let silk_use_cbr = if mode == OpusMode::Hybrid && self.use_cbr {
603 0
604 } else if self.use_cbr {
605 1
606 } else {
607 0
608 };
609 let ret = silk_encode(
610 &mut self.silk_enc,
611 silk_input,
612 silk_input.len(),
613 &mut self.rc,
614 &mut pn_bytes,
615 silk_bitrate,
616 silk_max_bits,
617 silk_use_cbr,
618 1,
619 );
620 if ret != 0 {
621 return Err("SILK encoding failed");
622 }
623 }
624
625 if mode == OpusMode::Hybrid {
626 self.rc.encode_bit_logp(false, 12); }
628
629 if mode == OpusMode::Hybrid {
630 let nb_compr_bytes = (n_bytes - 1) as u32;
631 self.rc.shrink(nb_compr_bytes);
632 }
633
634 let silk_ret_bytes = if mode == OpusMode::SilkOnly {
635 ((self.rc.tell() + 7) >> 3) as usize
636 } else {
637 0
638 };
639
640 if mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid {
641 self.celt_enc.complexity = self.complexity;
642 let start_band = if mode == OpusMode::Hybrid { 17 } else { 0 };
643 let total_packet_bits = ((n_bytes - 1) * 8) as i32;
644
645 let celt_input: &[f32] = if self.channels == 1 {
646 input
647 } else {
648 let n = frame_size * self.channels;
649 self.buf_celt_input.resize(n, 0.0);
650 for i in 0..frame_size {
651 for ch in 0..self.channels {
652 self.buf_celt_input[ch * frame_size + i] = input[i * self.channels + ch];
653 }
654 }
655 &self.buf_celt_input
656 };
657
658 if self.rc.tell() <= total_packet_bits {
659 self.celt_enc.encode_with_budget(
660 celt_input,
661 frame_size,
662 &mut self.rc,
663 start_band,
664 total_packet_bits,
665 );
666 }
667 }
668
669 self.rc.done();
670
671 if mode == OpusMode::SilkOnly {
672 let mut ret = silk_ret_bytes.min(self.rc.storage as usize);
673 while ret > 2 && self.rc.buf[ret - 1] == 0 {
674 ret -= 1;
675 }
676
677 let target_total = if self.use_cbr {
678 n_bytes.min(output.len())
679 } else {
680 (ret + 1).min(output.len())
681 };
682
683 let silk_len = ret;
684
685 if !self.use_cbr || silk_len + 1 >= target_total {
686 output[0] = toc;
688 let copy_len = silk_len.min(target_total - 1);
689 output[1..1 + copy_len].copy_from_slice(&self.rc.buf[..copy_len]);
690 return Ok((copy_len + 1).min(output.len()));
691 }
692
693 output[0] = toc | 0x03;
694
695 if silk_len + 2 >= target_total {
696 output[1] = 0x01;
697 let copy_len = (target_total - 2).min(silk_len);
698 output[2..2 + copy_len].copy_from_slice(&self.rc.buf[..copy_len]);
699 self.prev_enc_mode = Some(mode);
700 return Ok(target_total.min(output.len()));
701 }
702
703 let pad_amount = target_total - silk_len - 2;
704 output[1] = 0x41;
705
706 let nb_255s = (pad_amount - 1) / 255;
707 let mut ptr = 2;
708 for _ in 0..nb_255s {
709 output[ptr] = 255;
710 ptr += 1;
711 }
712 output[ptr] = (pad_amount - 255 * nb_255s - 1) as u8;
713 ptr += 1;
714
715 output[ptr..ptr + silk_len].copy_from_slice(&self.rc.buf[..silk_len]);
716 ptr += silk_len;
717
718 let fill_end = target_total.min(output.len());
719 for byte in output[ptr..fill_end].iter_mut() {
720 *byte = 0;
721 }
722
723 self.prev_enc_mode = Some(mode);
724 return Ok(target_total.min(output.len()));
725 }
726
727 let payload_len = n_bytes - 1;
728 output[1..1 + payload_len].copy_from_slice(&self.rc.buf[..payload_len]);
729 self.prev_enc_mode = Some(mode);
730 Ok(n_bytes)
731 }
732}
733
734pub struct OpusDecoder {
735 celt_dec: CeltDecoder,
736 silk_dec: silk::dec_api::SilkDecoder,
737 sampling_rate: i32,
738 channels: usize,
739
740 prev_mode: Option<OpusMode>,
741
742 prev_redundancy: bool,
744 frame_size: usize,
745
746 bandwidth: Bandwidth,
747
748 stream_channels: usize,
749
750 silk_resampler: silk::resampler::SilkResampler,
751
752 silk_resampler_2: silk::resampler::SilkResampler,
754
755 prev_internal_rate: i32,
756
757 pub hybrid_skip_celt: bool,
758
759 w_pcm_i16: Vec<i16>,
760 w_silk_out: Vec<f32>,
761 w_pcm_resampled: Vec<i16>,
762 w_celt_planar: Vec<f32>,
763 w_celt_out: Vec<f32>,
764
765 prev_pcm_tail: Vec<f32>,
768}
769
770impl OpusDecoder {
771 pub fn new(sampling_rate: i32, channels: usize) -> Result<Self, &'static str> {
772 if ![8000, 12000, 16000, 24000, 48000].contains(&sampling_rate) {
773 return Err("Invalid sampling rate");
774 }
775 if ![1, 2].contains(&channels) {
776 return Err("Invalid number of channels");
777 }
778
779 let mode = modes::default_mode();
780 let celt_dec = CeltDecoder::new(mode, channels, sampling_rate);
781
782 let mut silk_dec = silk::dec_api::SilkDecoder::new();
783 silk_dec.init(sampling_rate.min(16000), channels as i32);
784 silk_dec.channel_state[0].fs_api_hz = sampling_rate;
785
786 Ok(Self {
787 celt_dec,
788 silk_dec,
789 sampling_rate,
790 channels,
791 prev_mode: None,
792 prev_redundancy: false,
793 frame_size: 0,
794 bandwidth: Bandwidth::Auto,
795 stream_channels: channels,
796 silk_resampler: silk::resampler::SilkResampler::default(),
797 silk_resampler_2: silk::resampler::SilkResampler::default(),
798 prev_internal_rate: 0,
799 hybrid_skip_celt: false,
800
801 w_pcm_i16: vec![0i16; 960 * channels],
802
803 w_silk_out: vec![0.0f32; 5760 * channels],
804 w_pcm_resampled: vec![0i16; 5760 * channels],
805 w_celt_planar: vec![0.0f32; 5760 * channels],
806 w_celt_out: vec![0.0f32; 5760 * channels],
807
808 prev_pcm_tail: vec![0.0f32; 240 * channels],
809 })
810 }
811
812 pub fn decode(
813 &mut self,
814 input: &[u8],
815 frame_size: usize,
816 output: &mut [f32],
817 ) -> Result<usize, &'static str> {
818 if input.is_empty() {
819 return Err("Input packet empty");
820 }
821
822 let toc = input[0];
823 let mode = mode_from_toc(toc);
824 let packet_channels = channels_from_toc(toc);
825 let bandwidth = bandwidth_from_toc(toc);
826 let frame_duration_ms = frame_duration_ms_from_toc(toc);
827
828 let lost_frame = input.len() <= 1;
832
833 if packet_channels != self.channels {
834 return Err("Channel count mismatch between packet and decoder");
835 }
836
837 let code = toc & 0x03;
838 let frame_count: usize;
839 let frame_payloads: Vec<&[u8]>;
840
841 match code {
842 0 => {
843 frame_count = 1;
844 frame_payloads = vec![&input[1..]];
845 }
846 1 => {
847 frame_count = 2;
848 let data_len = input.len() - 1;
849 if data_len % 2 != 0 {
852 return Err("Code 1: payload length must be even");
853 }
854 let half = data_len / 2;
855 if half == 0 {
856 return Err("Code 1: empty frame");
857 }
858 frame_payloads = vec![&input[1..1 + half], &input[1 + half..]];
859 }
860 2 => {
861 frame_count = 2;
862 let data = &input[1..];
863 if data.is_empty() {
864 return Err("Code 2 packet has no data");
865 }
866 let (first_len, header_size) = parse_frame_size(data)?;
867 if header_size + first_len > data.len() {
868 return Err("Code 2: first frame size exceeds packet");
869 }
870 frame_payloads = vec![
871 &data[header_size..header_size + first_len],
872 &data[header_size + first_len..],
873 ];
874 }
875 3 => {
876 if input.len() < 2 {
877 return Err("Code 3 packet too short");
878 }
879 let count_byte = input[1];
880 let n_frames = (count_byte & 0x3F) as usize;
881 if n_frames < 1 || n_frames > 48 {
882 return Err("Code 3: invalid frame count");
883 }
884 frame_count = n_frames;
885 let padding_flag = (count_byte & 0x40) != 0;
887 let vbr = (count_byte & 0x80) != 0;
888
889 let mut ptr = 2usize;
893 let mut pad_len = 0usize;
894 if padding_flag {
895 loop {
896 if ptr >= input.len() {
897 return Err("Code 3: padding overflow");
898 }
899 let p = input[ptr] as usize;
900 ptr += 1;
901 if p == 255 {
902 pad_len += 254;
903 } else {
904 pad_len += p;
905 break;
906 }
907 }
908 }
909 if ptr + pad_len > input.len() {
910 return Err("Code 3: padding exceeds packet");
911 }
912 let payload_end = input.len() - pad_len;
913 let payload = &input[ptr..payload_end];
914
915 let mut payloads: Vec<&[u8]> = Vec::with_capacity(frame_count);
916 if frame_count == 1 {
917 payloads.push(payload);
920 } else if vbr {
921 let mut cursor = 0usize;
924 for i in 0..frame_count {
925 if i + 1 < frame_count {
926 if cursor >= payload.len() {
927 return Err("Code 3: unexpected end in VBR header");
928 }
929 let (frame_len, header_bytes) =
930 parse_frame_size(&payload[cursor..])?;
931 cursor += header_bytes;
932 if cursor + frame_len > payload.len() {
933 return Err("Code 3: frame length exceeds packet");
934 }
935 payloads.push(&payload[cursor..cursor + frame_len]);
936 cursor += frame_len;
937 } else {
938 if cursor > payload.len() {
940 return Err("Code 3: no data for last frame");
941 }
942 payloads.push(&payload[cursor..]);
943 }
944 }
945 } else {
946 if payload.len() % frame_count != 0 {
950 return Err("Code 3 CBR: payload not divisible by frame count");
951 }
952 let frame_len = payload.len() / frame_count;
953 for i in 0..frame_count {
954 payloads.push(&payload[i * frame_len..(i + 1) * frame_len]);
955 }
956 }
957 frame_payloads = payloads;
958 }
959 _ => unreachable!(),
960 }
961
962 self.frame_size = frame_size;
963 self.bandwidth = bandwidth;
964 self.stream_channels = packet_channels;
965
966 let toc_frame_size = frame_samples_from_toc(toc, self.sampling_rate)
971 .ok_or("Invalid TOC for sampling rate")?;
972 let decoded_total = toc_frame_size * frame_count;
973 if frame_size < decoded_total {
974 return Err("frame_size too small for packet");
975 }
976 if output.len() < decoded_total * self.channels {
977 return Err("Output buffer too small for packet");
978 }
979 if output.len() > decoded_total * self.channels {
982 for v in &mut output[decoded_total * self.channels..] {
983 *v = 0.0;
984 }
985 }
986 let sub_frame_size = toc_frame_size;
987 let sub_output_len = sub_frame_size * self.channels;
988
989 let mode_transition = match self.prev_mode {
995 Some(prev) if prev != mode && !self.prev_redundancy => true,
996 _ => false,
997 };
998 if mode_transition {
999 self.celt_dec.reset_state();
1000 }
1001
1002 let f5_bridge = self.sampling_rate as usize / 200; if mode_transition
1008 && f5_bridge > 0
1009 && matches!(
1010 self.prev_mode,
1011 Some(OpusMode::SilkOnly) | Some(OpusMode::Hybrid)
1012 )
1013 && self.prev_internal_rate > 0
1014 {
1015 let internal_rate = self.prev_internal_rate;
1016 let plc_internal_len = (10 * internal_rate / 1000) as usize;
1017 let mut plc_rc = RangeCoder::new_decoder(&[]);
1018 let mut plc_i16 = vec![0i16; plc_internal_len * self.channels];
1019 let n = self.silk_dec.decode(
1020 &mut plc_rc,
1021 &mut plc_i16,
1022 silk::decode_frame::FLAG_PACKET_LOST,
1023 true,
1024 10,
1025 internal_rate,
1026 );
1027 if n > 0 {
1028 let bridge_ch = f5_bridge * self.channels;
1029 let bridge_len = bridge_ch.min(self.prev_pcm_tail.len());
1030 if internal_rate == self.sampling_rate {
1031 let n_us = n as usize;
1033 for ch in 0..self.channels {
1034 let src_base = ch * n_us;
1035 for i in 0..(bridge_len / self.channels).min(n_us) {
1036 let dst = i * self.channels + ch;
1037 if dst < bridge_len {
1038 self.prev_pcm_tail[dst] = plc_i16[src_base + i] as f32 / 32768.0;
1039 }
1040 }
1041 }
1042 } else if self.silk_resampler.is_initialized() {
1043 let ratio = self.sampling_rate as f64 / internal_rate as f64;
1045 let out_len = ((n as f64 * ratio) as usize).min(f5_bridge);
1046 let n_us = n as usize;
1047 let mut resampled = vec![0i16; out_len];
1048 self.silk_resampler.process(
1049 &mut resampled,
1050 &plc_i16[..n_us],
1051 n,
1052 );
1053 for i in 0..out_len {
1054 if i < bridge_len / self.channels {
1055 for ch in 0..self.channels {
1056 self.prev_pcm_tail[i * self.channels + ch] =
1057 resampled[i] as f32 / 32768.0;
1058 }
1059 }
1060 }
1061 }
1062 }
1063 }
1064
1065 let mut has_redundancy = false;
1067
1068 match mode {
1069 OpusMode::SilkOnly => {
1070 let internal_sample_rate = match bandwidth {
1071 Bandwidth::Narrowband => 8000,
1072 Bandwidth::Mediumband => 12000,
1073 Bandwidth::Wideband => 16000,
1074 _ => 16000,
1075 };
1076 let internal_frame_size =
1077 (frame_duration_ms * internal_sample_rate / 1000) as usize;
1078
1079 if self.sampling_rate != internal_sample_rate
1080 && internal_sample_rate != self.prev_internal_rate
1081 {
1082 self.silk_resampler
1083 .init(internal_sample_rate, self.sampling_rate);
1084 self.silk_resampler_2
1085 .init(internal_sample_rate, self.sampling_rate);
1086 }
1087 self.prev_internal_rate = internal_sample_rate;
1091
1092 for (fi, payload) in frame_payloads.iter().enumerate() {
1093 let mut rc = RangeCoder::new_decoder(payload);
1094 let pcm_i16_len = internal_frame_size * self.channels;
1095 debug_assert!(pcm_i16_len <= self.w_pcm_i16.len());
1096
1097 let ret = {
1098 let (silk_dec, pcm_i16) = (&mut self.silk_dec, &mut self.w_pcm_i16);
1099 let lost_flag = if lost_frame {
1100 silk::decode_frame::FLAG_PACKET_LOST
1101 } else {
1102 silk::decode_frame::FLAG_DECODE_NORMAL
1103 };
1104 silk_dec.decode(
1105 &mut rc,
1106 &mut pcm_i16[..pcm_i16_len],
1107 lost_flag,
1108 true,
1109 frame_duration_ms,
1110 internal_sample_rate,
1111 )
1112 };
1113
1114 if ret < 0 {
1115 return Err("SILK decoding failed");
1116 }
1117
1118 let decoded_samples = ret as usize;
1119 let out_start = fi * sub_output_len;
1120
1121 if self.sampling_rate == internal_sample_rate {
1123 let frames = decoded_samples.min(sub_frame_size);
1124 for i in 0..frames {
1125 for ch in 0..self.channels {
1126 let src = if ch == 0 { i } else { internal_frame_size + i };
1127 let v = self.w_pcm_i16[src] as f32 / 32768.0;
1128 let idx = out_start + i * self.channels + ch;
1129 if idx < output.len() {
1130 output[idx] = v;
1131 }
1132 }
1133 }
1134 } else {
1135 let ratio = self.sampling_rate as f64 / internal_sample_rate as f64;
1136 let out_len =
1137 ((decoded_samples as f64 * ratio) as usize).min(sub_frame_size);
1138 debug_assert!(out_len * self.channels <= self.w_pcm_resampled.len());
1139 {
1141 let (res, inp, out) = (
1142 &mut self.silk_resampler,
1143 &self.w_pcm_i16,
1144 &mut self.w_pcm_resampled,
1145 );
1146 res.process(
1147 &mut out[..out_len],
1148 &inp[..decoded_samples],
1149 decoded_samples as i32,
1150 );
1151 }
1152 if self.channels == 2 {
1154 let (res, inp, out) = (
1155 &mut self.silk_resampler_2,
1156 &self.w_pcm_i16,
1157 &mut self.w_pcm_resampled,
1158 );
1159 res.process(
1160 &mut out[out_len..2 * out_len],
1161 &inp[internal_frame_size..internal_frame_size + decoded_samples],
1162 decoded_samples as i32,
1163 );
1164 }
1165 let frames = out_len.min(sub_frame_size);
1166 for i in 0..frames {
1167 for ch in 0..self.channels {
1168 let v = self.w_pcm_resampled[ch * out_len + i] as f32 / 32768.0;
1169 let idx = out_start + i * self.channels + ch;
1170 if idx < output.len() {
1171 output[idx] = v;
1172 }
1173 }
1174 }
1175 }
1176 }
1177 decoded_total
1178 }
1179
1180 OpusMode::CeltOnly => {
1181 let celt_end_band = self.celt_end_band_from_toc(toc);
1182
1183 for (fi, payload) in frame_payloads.iter().enumerate() {
1184 let mut rc = RangeCoder::new_decoder(payload);
1185 let total_bits = (payload.len() * 8) as i32;
1186 let needed = sub_frame_size * self.channels;
1187 let out_start = fi * needed;
1188 let out_end = (out_start + needed).min(output.len());
1189
1190 if output.len() < out_end {
1191 return Err("Output buffer too small");
1192 }
1193
1194 if self.channels == 1 {
1195 self.celt_dec.decode_from_range_coder_with_band_range(
1196 &mut rc,
1197 total_bits,
1198 sub_frame_size,
1199 &mut output[out_start..out_end],
1200 0,
1201 celt_end_band,
1202 );
1203 for sample in &mut output[out_start..out_end] {
1204 *sample = sample.clamp(-1.0, 1.0);
1205 }
1206 } else {
1207 self.celt_dec.decode_from_range_coder_with_band_range(
1208 &mut rc,
1209 total_bits,
1210 sub_frame_size,
1211 &mut self.w_celt_planar[..needed],
1212 0,
1213 celt_end_band,
1214 );
1215 for i in 0..sub_frame_size {
1216 for ch in 0..self.channels {
1217 let idx = out_start + i * self.channels + ch;
1218 output[idx] =
1219 self.w_celt_planar[ch * sub_frame_size + i].clamp(-1.0, 1.0);
1220 }
1221 }
1222 }
1223 }
1224 decoded_total
1225 }
1226
1227 OpusMode::Hybrid => {
1228 let internal_sample_rate = 16000;
1229 let internal_frame_size =
1230 (frame_duration_ms * internal_sample_rate / 1000) as usize;
1231 let celt_end_band = self.celt_end_band_from_toc(toc);
1232
1233 if self.sampling_rate != internal_sample_rate
1234 && internal_sample_rate != self.prev_internal_rate
1235 {
1236 self.silk_resampler
1237 .init(internal_sample_rate, self.sampling_rate);
1238 self.silk_resampler_2
1239 .init(internal_sample_rate, self.sampling_rate);
1240 }
1241 self.prev_internal_rate = internal_sample_rate;
1242
1243 for (fi, payload) in frame_payloads.iter().enumerate() {
1244 let mut rc = RangeCoder::new_decoder(payload);
1245 let pcm_silk_i16_len = internal_frame_size * self.channels;
1246 debug_assert!(pcm_silk_i16_len <= self.w_pcm_i16.len());
1247
1248 let ret = {
1249 let (silk_dec, pcm_i16) = (&mut self.silk_dec, &mut self.w_pcm_i16);
1250 let lost_flag = if lost_frame {
1251 silk::decode_frame::FLAG_PACKET_LOST
1252 } else {
1253 silk::decode_frame::FLAG_DECODE_NORMAL
1254 };
1255 silk_dec.decode(
1256 &mut rc,
1257 &mut pcm_i16[..pcm_silk_i16_len],
1258 lost_flag,
1259 true,
1260 frame_duration_ms,
1261 internal_sample_rate,
1262 )
1263 };
1264
1265 if ret < 0 {
1266 return Err("SILK decoding failed");
1267 }
1268
1269 let silk_out_len = sub_frame_size * self.channels;
1270 self.w_silk_out[..silk_out_len].fill(0.0);
1271 if ret > 0 {
1272 let decoded_samples = ret as usize;
1273 if self.sampling_rate == internal_sample_rate {
1275 let frames = decoded_samples.min(sub_frame_size);
1276 for i in 0..frames {
1277 for ch in 0..self.channels {
1278 let src = if ch == 0 { i } else { internal_frame_size + i };
1279 let v = self.w_pcm_i16[src] as f32 / 32768.0;
1280 let idx = i * self.channels + ch;
1281 if idx < silk_out_len {
1282 self.w_silk_out[idx] = v;
1283 }
1284 }
1285 }
1286 } else {
1287 let ratio = self.sampling_rate as f64 / internal_sample_rate as f64;
1288 let out_len =
1289 ((decoded_samples as f64 * ratio) as usize).min(sub_frame_size);
1290 debug_assert!(out_len * self.channels <= self.w_pcm_resampled.len());
1291 {
1293 let (res, inp, out) = (
1294 &mut self.silk_resampler,
1295 &self.w_pcm_i16,
1296 &mut self.w_pcm_resampled,
1297 );
1298 res.process(
1299 &mut out[..out_len],
1300 &inp[..decoded_samples],
1301 decoded_samples as i32,
1302 );
1303 }
1304 if self.channels == 2 {
1306 let (res, inp, out) = (
1307 &mut self.silk_resampler_2,
1308 &self.w_pcm_i16,
1309 &mut self.w_pcm_resampled,
1310 );
1311 res.process(
1312 &mut out[out_len..2 * out_len],
1313 &inp[internal_frame_size..internal_frame_size + decoded_samples],
1314 decoded_samples as i32,
1315 );
1316 }
1317 let frames = out_len.min(sub_frame_size);
1318 for i in 0..frames {
1319 for ch in 0..self.channels {
1320 let v = self.w_pcm_resampled[ch * out_len + i] as f32 / 32768.0;
1321 let idx = i * self.channels + ch;
1322 if idx < silk_out_len {
1323 self.w_silk_out[idx] = v;
1324 }
1325 }
1326 }
1327 }
1328 }
1329
1330 let total_bits = (payload.len() * 8) as i32;
1331 let redundancy = rc.decode_bit_logp(12);
1332 let skip_celt = if redundancy {
1333 let _celt_to_silk = rc.decode_bit_logp(1);
1334 has_redundancy = true;
1335 true
1341 } else {
1342 false
1343 };
1344
1345 if skip_celt {
1346 self.w_celt_out[..silk_out_len].fill(0.0);
1347 } else {
1348 let (celt_dec, celt_planar) = (&mut self.celt_dec, &mut self.w_celt_planar);
1349 celt_dec.decode_from_range_coder_with_band_range(
1350 &mut rc,
1351 total_bits,
1352 sub_frame_size,
1353 &mut celt_planar[..silk_out_len],
1354 17,
1355 celt_end_band,
1356 );
1357
1358 if self.channels == 1 {
1359 self.w_celt_out[..silk_out_len]
1360 .copy_from_slice(&self.w_celt_planar[..silk_out_len]);
1361 } else {
1362 for i in 0..sub_frame_size {
1363 for ch in 0..self.channels {
1364 self.w_celt_out[i * self.channels + ch] =
1365 self.w_celt_planar[ch * sub_frame_size + i];
1366 }
1367 }
1368 }
1369 }
1370
1371 let out_start = fi * silk_out_len;
1372 let total = silk_out_len.min(output.len() - out_start);
1373 for j in 0..total {
1374 output[out_start + j] =
1375 (self.w_silk_out[j] + self.w_celt_out[j]).clamp(-1.0, 1.0);
1376 }
1377 }
1378 decoded_total
1379 }
1380 };
1381
1382 let f2_5 = self.sampling_rate as usize / 400;
1388 let f5 = f2_5 * 2;
1389 if mode_transition && f5 > 0 && decoded_total >= f5 {
1390 let window = modes::default_mode().window;
1391 let inc = (48000 / self.sampling_rate) as usize;
1392 let f2_5_ch = f2_5 * self.channels;
1393 let f5_ch = f5 * self.channels;
1394 output[..f2_5_ch].copy_from_slice(&self.prev_pcm_tail[..f2_5_ch]);
1396 let new_mid: Vec<f32> = output[f2_5_ch..f5_ch].to_vec();
1398 smooth_fade(
1399 &self.prev_pcm_tail[f2_5_ch..f5_ch],
1400 &new_mid,
1401 &mut output[f2_5_ch..f5_ch],
1402 f2_5,
1403 self.channels,
1404 window,
1405 inc,
1406 );
1407 }
1408
1409 let tail_len = f5 * self.channels;
1411 let out_total = decoded_total * self.channels;
1412 if out_total >= tail_len && tail_len <= self.prev_pcm_tail.len() {
1413 self.prev_pcm_tail[..tail_len]
1414 .copy_from_slice(&output[out_total - tail_len..out_total]);
1415 }
1416
1417 self.prev_mode = Some(mode);
1418 self.prev_redundancy = has_redundancy;
1419 Ok(decoded_total)
1420 }
1421}
1422
1423impl OpusDecoder {
1424 #[inline(always)]
1425 fn celt_end_band_from_toc(&self, toc: u8) -> usize {
1426 let mode = modes::default_mode();
1427 let top = mode.eff_ebands;
1428 if mode_from_toc(toc) == OpusMode::CeltOnly && toc >= 0x80 {
1429 const FROM_OPUS_TABLE: [u8; 16] = [
1430 0x80, 0x88, 0x90, 0x98, 0x40, 0x48, 0x50, 0x58, 0x20, 0x28, 0x30, 0x38, 0x00, 0x08,
1431 0x10, 0x18,
1432 ];
1433 let idx = ((toc >> 3) - 16) as usize;
1434 let data0 = FROM_OPUS_TABLE[idx] | (toc & 0x7);
1435 let trim = (data0 >> 5) as usize;
1436 return top.saturating_sub(2 * trim).max(1);
1437 }
1438 top
1439 }
1440}
1441
1442fn frame_rate_from_params(sampling_rate: i32, frame_size: usize) -> Option<i32> {
1443 let frame_size = frame_size as i32;
1444 if frame_size == 0 || sampling_rate % frame_size != 0 {
1445 return None;
1446 }
1447 Some(sampling_rate / frame_size)
1448}
1449
1450fn gen_toc(mode: OpusMode, frame_rate: i32, bandwidth: Bandwidth, channels: usize) -> u8 {
1451 let mut rate = frame_rate;
1452 let mut period = 0;
1453 while rate < 400 {
1454 rate <<= 1;
1455 period += 1;
1456 }
1457
1458 let mut toc = match mode {
1459 OpusMode::SilkOnly => {
1460 let bw = (bandwidth as i32 - Bandwidth::Narrowband as i32) << 5;
1461 let per = (period - 2) << 3;
1462 (bw | per) as u8
1463 }
1464 OpusMode::CeltOnly => {
1465 let mut tmp = bandwidth as i32 - Bandwidth::Mediumband as i32;
1466 if tmp < 0 {
1467 tmp = 0;
1468 }
1469 let per = period << 3;
1470 (0x80 | (tmp << 5) | per) as u8
1471 }
1472 OpusMode::Hybrid => {
1473 let base_config = if bandwidth == Bandwidth::Superwideband {
1474 12
1475 } else {
1476 14
1477 };
1478 let period_offset = if frame_rate >= 100 { 0 } else { 1 };
1479 ((base_config + period_offset) << 3) as u8
1480 }
1481 };
1482
1483 if channels == 2 {
1484 toc |= 0x04;
1485 }
1486 toc
1487}
1488
1489fn mode_from_toc(toc: u8) -> OpusMode {
1490 if toc & 0x80 != 0 {
1491 OpusMode::CeltOnly
1492 } else if toc & 0x60 == 0x60 {
1493 OpusMode::Hybrid
1494 } else {
1495 OpusMode::SilkOnly
1496 }
1497}
1498
1499fn bandwidth_from_toc(toc: u8) -> Bandwidth {
1500 let mode = mode_from_toc(toc);
1501 match mode {
1502 OpusMode::SilkOnly => {
1503 let bw_bits = (toc >> 5) & 0x03;
1504 match bw_bits {
1505 0 => Bandwidth::Narrowband,
1506 1 => Bandwidth::Mediumband,
1507 2 => Bandwidth::Wideband,
1508 _ => Bandwidth::Wideband,
1509 }
1510 }
1511 OpusMode::Hybrid => {
1512 let bw_bit = (toc >> 4) & 0x01;
1513 if bw_bit == 0 {
1514 Bandwidth::Superwideband
1515 } else {
1516 Bandwidth::Fullband
1517 }
1518 }
1519 OpusMode::CeltOnly => {
1520 let bw_bits = (toc >> 5) & 0x03;
1521 match bw_bits {
1522 0 => Bandwidth::Mediumband,
1523 1 => Bandwidth::Wideband,
1524 2 => Bandwidth::Superwideband,
1525 3 => Bandwidth::Fullband,
1526 _ => Bandwidth::Fullband,
1527 }
1528 }
1529 }
1530}
1531
1532fn frame_duration_ms_from_toc(toc: u8) -> i32 {
1533 let mode = mode_from_toc(toc);
1534 match mode {
1535 OpusMode::SilkOnly => {
1536 let config = (toc >> 3) & 0x03;
1537 match config {
1538 0 => 10,
1539 1 => 20,
1540 2 => 40,
1541 3 => 60,
1542 _ => 20,
1543 }
1544 }
1545 OpusMode::Hybrid => {
1546 let config = (toc >> 3) & 0x01;
1547 if config == 0 { 10 } else { 20 }
1548 }
1549 OpusMode::CeltOnly => {
1550 let config = (toc >> 3) & 0x03;
1551 match config {
1552 0 => 2,
1553 1 => 5,
1554 2 => 10,
1555 3 => 20,
1556 _ => 20,
1557 }
1558 }
1559 }
1560}
1561
1562fn frame_samples_from_toc(toc: u8, sampling_rate: i32) -> Option<usize> {
1566 let mode = mode_from_toc(toc);
1567 match mode {
1568 OpusMode::CeltOnly => {
1569 let period = ((toc >> 3) & 0x03) as i32;
1570 let frame_rate = 400 >> period;
1571 if frame_rate == 0 || sampling_rate % frame_rate != 0 {
1572 return None;
1573 }
1574 Some((sampling_rate / frame_rate) as usize)
1575 }
1576 OpusMode::SilkOnly | OpusMode::Hybrid => {
1577 let duration_ms = frame_duration_ms_from_toc(toc);
1578 Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
1579 }
1580 }
1581}
1582
1583fn channels_from_toc(toc: u8) -> usize {
1584 if toc & 0x04 != 0 { 2 } else { 1 }
1585}
1586
1587fn smooth_fade(
1590 in1: &[f32],
1591 in2: &[f32],
1592 out: &mut [f32],
1593 overlap: usize,
1594 channels: usize,
1595 window: &[f32],
1596 inc: usize,
1597) {
1598 for c in 0..channels {
1599 for i in 0..overlap {
1600 let wi = i * inc;
1601 if wi >= window.len() {
1602 break;
1603 }
1604 let w = window[wi] * window[wi];
1605 out[i * channels + c] = w * in2[i * channels + c] + (1.0 - w) * in1[i * channels + c];
1606 }
1607 }
1608}
1609
1610fn parse_frame_size(data: &[u8]) -> Result<(usize, usize), &'static str> {
1618 let first = *data.first().ok_or("truncated frame length")? as usize;
1619 if first < 252 {
1620 Ok((first, 1))
1621 } else {
1622 let second = *data.get(1).ok_or("truncated frame length")? as usize;
1623 Ok((second * 4 + first, 2))
1624 }
1625}
1626
1627#[cfg(test)]
1628mod tests {
1629 use super::*;
1630
1631 fn frame_size_from_toc(toc: u8, sampling_rate: i32) -> Option<usize> {
1632 let mode = mode_from_toc(toc);
1633 match mode {
1634 OpusMode::CeltOnly => {
1635 let period = ((toc >> 3) & 0x03) as i32;
1636 let frame_rate = 400 >> period;
1637 if frame_rate == 0 || sampling_rate % frame_rate != 0 {
1638 return None;
1639 }
1640 Some((sampling_rate / frame_rate) as usize)
1641 }
1642 OpusMode::SilkOnly => {
1643 let duration_ms = frame_duration_ms_from_toc(toc);
1644 Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
1645 }
1646 OpusMode::Hybrid => {
1647 let duration_ms = frame_duration_ms_from_toc(toc);
1648 Some((sampling_rate as i64 * duration_ms as i64 / 1000) as usize)
1649 }
1650 }
1651 }
1652
1653 #[test]
1654 fn gen_toc_matches_celt_reference_values() {
1655 let sampling_rate = 48_000;
1656 let cases = [
1657 (120usize, 0xE0u8),
1658 (240usize, 0xE8u8),
1659 (480usize, 0xF0u8),
1660 (960usize, 0xF8u8),
1661 ];
1662
1663 for (frame_size, expected_toc) in cases {
1664 let frame_rate = frame_rate_from_params(sampling_rate, frame_size).unwrap();
1665 let toc = gen_toc(OpusMode::CeltOnly, frame_rate, Bandwidth::Fullband, 1);
1666 assert_eq!(
1667 toc, expected_toc,
1668 "frame_size {} expected TOC {:02X} got {:02X}",
1669 frame_size, expected_toc, toc
1670 );
1671 let decoded_size = frame_size_from_toc(toc, sampling_rate).unwrap();
1672 assert_eq!(decoded_size, frame_size);
1673 }
1674
1675 let stereo_toc = gen_toc(
1676 OpusMode::CeltOnly,
1677 frame_rate_from_params(sampling_rate, 960).unwrap(),
1678 Bandwidth::Fullband,
1679 2,
1680 );
1681 assert_eq!(channels_from_toc(stereo_toc), 2);
1682 }
1683
1684 #[test]
1685 fn test_celt_decoder_large_frame_sizes() {
1686 let sampling_rate = 48000;
1687 let channels = 1;
1688
1689 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
1690
1691 let frame_sizes = [120, 240, 480, 960];
1692
1693 for frame_size in frame_sizes {
1694 let toc = gen_toc(
1695 OpusMode::CeltOnly,
1696 frame_rate_from_params(sampling_rate, frame_size).unwrap(),
1697 Bandwidth::Fullband,
1698 channels,
1699 );
1700 let packet = [toc, 0, 0, 0, 0];
1701
1702 let mut output = vec![0.0f32; frame_size * channels];
1703
1704 let _ = decoder.decode(&packet, frame_size, &mut output);
1705 }
1706
1707 let channels = 2;
1708 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
1709
1710 for frame_size in frame_sizes {
1711 let toc = gen_toc(
1712 OpusMode::CeltOnly,
1713 frame_rate_from_params(sampling_rate, frame_size).unwrap(),
1714 Bandwidth::Fullband,
1715 channels,
1716 );
1717 let packet = [toc, 0, 0, 0, 0];
1718
1719 let mut output = vec![0.0f32; frame_size * channels];
1720 let _ = decoder.decode(&packet, frame_size, &mut output);
1721 }
1722 }
1723
1724 #[test]
1725 fn test_celt_decoder_edge_case_frame_sizes() {
1726 let sampling_rate = 48000;
1727 let channels = 1;
1728 let mut decoder = OpusDecoder::new(sampling_rate, channels).unwrap();
1729
1730 let edge_sizes = [2048, 2167, 2168, 2169, 2880, 3072];
1731
1732 for frame_size in edge_sizes {
1733 let mut output = vec![0.0f32; frame_size * channels];
1734
1735 let _ = decoder.decode(&[0x80, 0, 0, 0], frame_size, &mut output);
1736 }
1737 }
1738
1739 #[test]
1746 fn test_invalid_small_frame_size_returns_error_not_panic() {
1747 let mut enc = OpusEncoder::new(48000, 2, Application::Voip).unwrap();
1748 enc.bitrate_bps = 64000;
1749 enc.complexity = 5;
1750 enc.use_cbr = true;
1751
1752 let input = vec![0.0f32; 48 * 2]; let mut output = vec![0u8; 256];
1755
1756 let result = enc.encode(&input, 48, &mut output);
1757 assert!(
1758 result.is_err(),
1759 "encode with invalid frame_size=48 should return Err, not panic"
1760 );
1761 }
1762
1763 #[test]
1766 fn test_invalid_small_frame_size_audio_application_returns_error() {
1767 let mut enc = OpusEncoder::new(48000, 1, Application::Audio).unwrap();
1768 let input = vec![0.0f32; 48];
1769 let mut output = vec![0u8; 256];
1770
1771 let result = enc.encode(&input, 48, &mut output);
1772 assert!(
1773 result.is_err(),
1774 "Audio/48kHz encoder with frame_size=48 should return Err"
1775 );
1776 }
1777}