opus_pure/encoder.rs
1//! The Opus encoder.
2
3use crate::analysis;
4use crate::celt::{self, CeltEncoder};
5use crate::config::{Application, Bandwidth, OpusMode, RateControl, Signal};
6use crate::hp_cutoff::hp_cutoff;
7use crate::range_coder::RangeCoder;
8use crate::silk::{
9 self, control_codec::silk_control_encoder, enc_api::silk_encode,
10 init_encoder::silk_init_encoder, macros::*, structs::SilkEncoder,
11};
12use crate::soft_clip::i16_to_float;
13use crate::toc::{celt_endband_for_bandwidth, frame_rate_from_params, gen_toc};
14use crate::{Error, Result};
15
16/// An Opus encoder: PCM in, Opus packets out.
17///
18/// One encoder handles one stream, and carries state between packets, so the
19/// same instance has to be fed the whole stream in order. The settings below
20/// are public fields rather than setters, and every one of them may be changed
21/// between packets; only the sample rate, channel count and
22/// [`Application`] are fixed at construction.
23///
24/// The encoder decides per packet which of the three Opus layers to use, what
25/// audio [`Bandwidth`] to code, and how many bits to spend. Those decisions are
26/// what [`bitrate_bps`](Self::bitrate_bps), [`complexity`](Self::complexity)
27/// and the rest steer.
28///
29/// ```
30/// use opus_pure::{Application, OpusEncoder};
31///
32/// let mut encoder = OpusEncoder::new(48_000, 2, Application::Audio)?;
33/// encoder.bitrate_bps = 96_000;
34///
35/// let pcm = vec![0.0f32; 960 * 2]; // 20 ms of stereo
36/// let mut packet = vec![0u8; 4000];
37/// let n = encoder.encode(&pcm, 960, &mut packet)?;
38/// assert!(n > 0);
39/// # Ok::<(), opus_pure::Error>(())
40/// ```
41pub struct OpusEncoder {
42 celt_enc: CeltEncoder,
43 silk_enc: Box<SilkEncoder>,
44 application: Application,
45 sampling_rate: i32,
46 channels: usize,
47 bandwidth: Bandwidth,
48 /// Target bitrate in bits per second, across all channels. Default 64000.
49 ///
50 /// This is a target rather than a cap: the default is variable-rate, so an
51 /// individual packet is as large as its content needs and the rate is met
52 /// on average. See [`rate_control`](Self::rate_control) to make it a per-packet size
53 /// instead.
54 ///
55 /// It is also the single strongest input to the encoder's own decisions.
56 /// Coding mode and audio bandwidth are both chosen from it, so lowering it
57 /// does not simply degrade the same signal: below roughly 20 kb/s the
58 /// encoder moves to SILK and narrows the bandwidth, because spending the
59 /// remaining bits on a smaller spectrum sounds better than spreading them
60 /// over all of it.
61 pub bitrate_bps: i32,
62 /// How much CPU the encoder may spend, from 0 to 10. Default 9.
63 ///
64 /// Lower settings take shortcuts in pitch analysis and quantisation, and
65 /// below 7 the content analysis is skipped entirely, which is what
66 /// otherwise informs the speech/music decision. It is not purely a speed
67 /// control: the encoder scales its own idea of the bitrate by
68 /// `(90 + complexity) / 100` when choosing a mode and bandwidth, so a lower
69 /// complexity also codes a narrower band at the same rate.
70 pub complexity: i32,
71 /// How much the size of each packet may vary. Default
72 /// [`ConstrainedVbr`](RateControl::ConstrainedVbr), which is libopus's.
73 ///
74 /// [`Cbr`](RateControl::Cbr) pads every packet to the same size, which is
75 /// what a fixed-capacity channel wants and what a file does not: it spends
76 /// bits on silence that VBR would have given to the difficult passages. It
77 /// also costs quality at a given rate, and the encoder accounts for that by
78 /// discounting its working bitrate by a twelfth when deciding mode and
79 /// bandwidth.
80 ///
81 /// Note this is the opposite polarity from libopus's `OPUS_SET_VBR`: the
82 /// default here is named for what it does rather than for what it is not.
83 pub rate_control: RateControl,
84
85 /// Code a low-bitrate copy of the *previous* frame into each packet, so one
86 /// lost packet can be partly recovered from the next. Default `false`.
87 ///
88 /// The redundant copy costs bits that would otherwise go to the current
89 /// frame, so this is only worth enabling when loss is actually expected,
90 /// and the encoder decides per packet whether to spend them, using
91 /// [`packet_loss_perc`](Self::packet_loss_perc) as its estimate of how
92 /// likely that is. FEC needs SILK, so it has no effect on packets the
93 /// encoder codes as CELT.
94 ///
95 /// A decoder recovers the copy with
96 /// [`OpusDecoder::decode_fec`](crate::OpusDecoder::decode_fec), which must
97 /// be called on the packet *after* the missing one.
98 pub use_inband_fec: bool,
99
100 /// Discontinuous transmission: after enough consecutive inactive frames,
101 /// emit a 1-byte (TOC-only) packet so the decoder runs comfort-noise/PLC.
102 pub use_dtx: bool,
103 /// Consecutive inactive milliseconds, in Q1 (opus_encoder.c nb_no_activity).
104 nb_no_activity_ms_q1: i32,
105 /// Final range-coder state of the last packet (0 for DTX/PLC packets, which
106 /// carry no coded range — opus_encoder.c st->rangeFinal).
107 range_final: u32,
108
109 /// Expected packet loss, 0 to 100 percent. Default 0.
110 ///
111 /// This is what tells the encoder how defensively to code. A non-zero value
112 /// makes the quantiser less reliant on inter-frame prediction, so a lost
113 /// packet corrupts less of what follows, and it is the input
114 /// [`use_inband_fec`](Self::use_inband_fec) uses to decide whether a
115 /// redundant copy is worth its bits. Both cost quality on the packets that
116 /// do arrive, so an estimate far above the real loss rate is not a safe
117 /// default.
118 pub packet_loss_perc: i32,
119 /// Whether the current packet codes in-band FEC. Decided per packet by
120 /// [`decide_fec`], which needs the previous answer for its hysteresis.
121 lbrr_coded: bool,
122 silk_initialized: bool,
123 prev_enc_mode: Option<OpusMode>,
124
125 variable_hp_smth2_q15: i32,
126 /// Rate-dependent automatic bandwidth (libopus auto_bandwidth), stored as the
127 /// Bandwidth discriminant (1101 NB .. 1105 FB). Hysteresis state.
128 auto_bandwidth: i32,
129 first_frame: bool,
130 /// Overrides automatic bandwidth selection when set (OPUS_SET_BANDWIDTH).
131 pub force_bandwidth: Option<Bandwidth>,
132 /// OPUS_SET_SIGNAL: force the voice/music bias (None = auto from analysis).
133 pub signal_type: Option<Signal>,
134 /// OPUS_SET_MAX_BANDWIDTH: cap the automatically-selected bandwidth.
135 pub max_bandwidth: Bandwidth,
136 /// Tonality/music/bandwidth analysis (libopus src/analysis.c); runs when
137 /// complexity >= 7 and the API rate is >= 16 kHz.
138 /// Bit depth in force for the packet being coded: the lesser of what the
139 /// entry point implies and what the caller asked for, which is libopus's
140 /// `lsb_depth = IMIN(lsb_depth, st->lsb_depth)` at the top of
141 /// `opus_encode_native`. It is per-call rather than a setting because the
142 /// float and 16-bit entry points imply different depths, so the two cannot
143 /// share one stored value.
144 coded_lsb_depth: i32,
145 tonality: analysis::TonalityAnalysisState,
146 analysis_kfft: Option<celt::kiss_fft::KissFftState>,
147 /// Input bit depth assumed by the analysis noise floors. The float API
148 /// default is 24; set 16 for s16-sourced content (opus_demo parity).
149 pub lsb_depth: i32,
150 /// 0..100 voice probability from the analysis (-1 = unknown), C voice_ratio.
151 voice_ratio: i32,
152 detected_bandwidth: i32,
153 hp_mem: Vec<i32>,
154
155 /// Holds the converted input for [`OpusEncoder::encode_s16`], so a caller
156 /// feeding integer PCM does not pay an allocation per packet.
157 buf_from_s16: Vec<f32>,
158
159 buf_filtered: Vec<i16>,
160 buf_silk_input: Vec<i16>,
161 buf_stereo_mid: Vec<i16>,
162 buf_stereo_side: Vec<i16>,
163 buf_celt_input: Vec<f32>,
164 down_fir_l: Option<silk::resampler::SilkEncoderResampler>,
165 down_fir_r: Option<silk::resampler::SilkEncoderResampler>,
166 /// Last 10 ms of API-rate mono input, for the SILK prefill after a
167 /// CELT-only -> SILK/hybrid transition (opus_encoder.c:1449 prefill=1).
168 silk_prefill_tail: Vec<i16>,
169 silk_prefill_pending: bool,
170 buf_left: Vec<i16>,
171 buf_right: Vec<i16>,
172 /// Last 2.5 ms of input before the next CELT frame begins (planar), for the
173 /// CELT prefill after a mode-transition reset (opus_encoder.c:2060).
174 celt_prefill_tail: Vec<f32>,
175 /// Input the CELT layer has not consumed yet: the most recent
176 /// [`celt_delay_samples`] per channel, planar, oldest first.
177 ///
178 /// This is libopus's `delay_buffer` narrowed to what CELT actually reads
179 /// from it. It advances on *every* frame, SILK-only ones included, because
180 /// it is a position on the input timeline rather than a coder state; letting
181 /// it stall through a SILK run would step CELT forward by that much when the
182 /// mode came back.
183 celt_delay: Vec<f32>,
184 /// The spare half of the CELT delay line's double buffer. Swapped with
185 /// `celt_delay` each frame so neither allocation is dropped.
186 celt_delay_next: Vec<f32>,
187
188 rc: RangeCoder<'static>,
189}
190
191/// Input bit depth the analysis noise floors assume (opus_encoder.c float-API
192/// default). The floor is `(5.7e-4 / 2^(lsb_depth-8))^2`, so s16-sourced material
193/// wants 16, which is what [`OpusEncoder::encode_s16`] uses.
194const DEFAULT_LSB_DEPTH: i32 = 24;
195
196/// Precision the float entry point declares its input to have (libopus
197/// `MAX_ENCODING_DEPTH`). The 16-bit entry point declares 16 instead.
198pub(crate) const MAX_ENCODING_DEPTH: i32 = 24;
199
200/// Force `mode` to one that can code a packet of `packet_rate` packets per
201/// second at all.
202///
203/// The mode decision looks at bitrate, bandwidth and the content analysis, none
204/// of which know the caller's frame size, so it can pick a mode RFC 6716 §3.1
205/// has no configuration for at that duration. Only the two shortest durations
206/// need forcing: 2.5 and 5 ms exist for CELT alone, and no amount of splitting
207/// produces something SILK can code. Every duration longer than 20 ms that a
208/// mode cannot code as one frame is reached by [`PacketDuration::layout`]
209/// splitting the packet into frames the mode *can* code, which is what libopus
210/// does (`opus_encoder.c` `enc_frame_size`).
211fn coerce_mode_for_packet_rate(mode: OpusMode, packet_rate: i32) -> OpusMode {
212 match packet_rate {
213 400 | 200 => OpusMode::CeltOnly,
214 _ => mode,
215 }
216}
217
218/// One of the nine packet durations RFC 6716 admits, in tenths of a millisecond
219/// so that 2.5 ms is an integer.
220///
221/// A duration is not a frame size: 80, 100 and 120 ms have no single-frame
222/// configuration at all, and 40 and 60 ms have one only for SILK. What a
223/// duration becomes on the wire is [`PacketDuration::layout`].
224#[derive(Clone, Copy, Debug, PartialEq, Eq)]
225struct PacketDuration(i32);
226
227impl PacketDuration {
228 /// Recognise `frame_size` samples per channel as a packet duration, or
229 /// reject it.
230 ///
231 /// The relations are written as exact integer products, the way
232 /// `opus_encoder.c` writes them, so that the durations no sample rate
233 /// divides evenly (60 and 120 ms at every rate, 100 ms at none) need no
234 /// special case.
235 fn classify(sampling_rate: i32, frame_size: usize) -> Option<Self> {
236 let fs = i32::try_from(frame_size).ok()?;
237 if fs <= 0 {
238 return None;
239 }
240 let tenths_ms = if 400 * fs == sampling_rate {
241 25
242 } else if 200 * fs == sampling_rate {
243 50
244 } else if 100 * fs == sampling_rate {
245 100
246 } else if 50 * fs == sampling_rate {
247 200
248 } else if 25 * fs == sampling_rate {
249 400
250 } else if 50 * fs == 3 * sampling_rate {
251 600
252 } else if 25 * fs == 2 * sampling_rate {
253 800
254 } else if 10 * fs == sampling_rate {
255 1000
256 } else if 25 * fs == 3 * sampling_rate {
257 1200
258 } else {
259 return None;
260 };
261 Some(PacketDuration(tenths_ms))
262 }
263
264 /// How this duration is laid out as coded frames when the packet is coded in
265 /// `mode` (`opus_encoder.c:1698`).
266 ///
267 /// Only SILK has configurations past 20 ms, and the CELT transform has no
268 /// frame longer than 20 ms outright, so anything else becomes several frames
269 /// sharing one TOC (RFC 6716 §3.2).
270 fn layout(self, sampling_rate: i32, mode: OpusMode) -> PacketLayout {
271 let ms20 = (sampling_rate / 50) as usize;
272 let ms40 = (sampling_rate / 25) as usize;
273 let ms60 = (3 * sampling_rate / 50) as usize;
274
275 let frame_size = (sampling_rate as i64 * self.0 as i64 / 10_000) as usize;
276
277 let silk = mode == OpusMode::SilkOnly;
278 let enc_frame_size = match self.0 {
279 // 20 ms and shorter is one frame, whatever the mode.
280 d if d <= 200 => frame_size,
281 // SILK keeps its long frames whole: 40 and 60 ms as themselves,
282 // 80 ms as two 40s and 120 ms as two 60s.
283 400 | 800 if silk => ms40,
284 600 | 1200 if silk => ms60,
285 // Everything else is 20 ms frames, including 100 ms in every mode,
286 // because no legal duration halves it.
287 _ => ms20,
288 };
289
290 PacketLayout {
291 enc_frame_size,
292 nb_frames: frame_size / enc_frame_size,
293 frame_rate: frame_rate_from_params(sampling_rate, enc_frame_size)
294 .expect("every frame size `layout` produces is a coded frame duration"),
295 }
296 }
297}
298
299/// How one `encode` call's audio is laid out as coded frames in one packet.
300#[derive(Clone, Copy, Debug, PartialEq, Eq)]
301struct PacketLayout {
302 /// Samples per channel in each coded frame.
303 enc_frame_size: usize,
304 /// Frames in the packet. 1 means the frame is coded straight into the
305 /// caller's buffer, with no repacketizing.
306 nb_frames: usize,
307 /// Frames per second of `enc_frame_size`, as the TOC codes it.
308 frame_rate: i32,
309}
310
311/// Worst-case bytes the framing of an `nb_frames`-frame packet can cost
312/// (`opus_encoder.c` `max_header_bytes`): a code 2 packet for two frames, and a
313/// code 3 VBR packet, whose per-frame length fields run to two bytes, above that.
314fn max_header_bytes(nb_frames: usize) -> usize {
315 if nb_frames == 2 {
316 3
317 } else {
318 2 + (nb_frames - 1) * 2
319 }
320}
321
322/// Whether the CELT layer can code a frame of `frame_size` samples per channel.
323///
324/// The CELT layer always runs the 48 kHz mode regardless of the API rate, so the
325/// only frame sizes it can transform are `SHORT_MDCT_SIZE << lm` for
326/// `lm` in `0..=max_lm` — 120, 240, 480 and 960 samples. Frame sizes the Opus API
327/// otherwise allows (2.5 ms at 12 kHz is 30 samples, 5 ms at 24 kHz is 120 but
328/// 2.5 ms is 60) have no matching `lm`.
329/// The widest bandwidth an input at `sampling_rate` can actually carry: coding
330/// above the input's Nyquist rate asks the encoder for bands that hold no
331/// signal. Mirrors the final clamp in `opus_encoder.c`.
332fn bandwidth_from_i32(v: i32) -> Bandwidth {
333 match v {
334 x if x == Bandwidth::Narrowband as i32 => Bandwidth::Narrowband,
335 x if x == Bandwidth::Mediumband as i32 => Bandwidth::Mediumband,
336 x if x == Bandwidth::Superwideband as i32 => Bandwidth::Superwideband,
337 x if x == Bandwidth::Fullband as i32 => Bandwidth::Fullband,
338 _ => Bandwidth::Wideband,
339 }
340}
341
342fn clamp_bandwidth_to_rate(bw: Bandwidth, sampling_rate: i32) -> Bandwidth {
343 let max = match sampling_rate {
344 r if r <= 8000 => Bandwidth::Narrowband,
345 r if r <= 12000 => Bandwidth::Mediumband,
346 r if r <= 16000 => Bandwidth::Wideband,
347 r if r <= 24000 => Bandwidth::Superwideband,
348 _ => Bandwidth::Fullband,
349 };
350 if (bw as i32) > (max as i32) { max } else { bw }
351}
352
353fn celt_can_code_frame(frame_size_48k: usize) -> bool {
354 let blocks = frame_size_48k / celt::modes::SHORT_MDCT_SIZE;
355 frame_size_48k.is_multiple_of(celt::modes::SHORT_MDCT_SIZE)
356 && blocks.is_power_of_two()
357 && blocks <= 1 << celt::modes::MAX_LM
358}
359
360/// 48 kHz samples per input sample at `sampling_rate` (libopus
361/// `resampling_factor`). The CELT layer only has the 48 kHz mode, so a lower
362/// API rate is coded by zero-stuffing up to 48 kHz.
363fn celt_upsample(sampling_rate: i32) -> usize {
364 (48_000 / sampling_rate) as usize
365}
366
367/// Input samples per channel used to prefill a freshly-reset CELT encoder: one
368/// short MDCT block, 2.5 ms, expressed at the API rate. Scaled by
369/// [`celt_upsample`] it is always exactly `SHORT_MDCT_SIZE` at 48 kHz, which is
370/// the only frame size a fresh CELT encoder can transform.
371fn celt_prefill_samples(sampling_rate: i32) -> usize {
372 celt::modes::SHORT_MDCT_SIZE / celt_upsample(sampling_rate)
373}
374
375/// Samples the CELT layer's input trails the caller's, `st->delay_compensation`
376/// in libopus (`opus_encoder.c:313`).
377///
378/// CELT has a shorter algorithmic delay than SILK, so an encoder that fed both
379/// the same samples would emit a stream whose timeline jumps by the difference
380/// every time the mode changes. libopus closes that by handing CELT input that
381/// lags by 4 ms: it builds `pcm_buf` as this much history followed by the new
382/// frame, gives SILK the new frame (`:2211`) and CELT the buffer from the start
383/// (`:2493`). The two layers then line up at the decoder, and the constant total
384/// delay is what [`crate::ogg::OpusHead::RECOMMENDED_PRE_SKIP`] counts.
385///
386/// Zero for [`Application::RestrictedLowDelay`], which trades the mode switch
387/// away for the lower delay (`opus_encoder.c:1904`).
388fn celt_delay_samples(sampling_rate: i32, application: Application) -> usize {
389 match application {
390 Application::RestrictedLowDelay => 0,
391 _ => (sampling_rate / 250) as usize,
392 }
393}
394
395/// The largest packet [`OpusEncoder::encode`] can produce, and therefore the
396/// output buffer size that never costs you bitrate.
397///
398/// This has to be exact rather than merely generous. [`OpusEncoder::encode`]
399/// takes the output slice's length as the packet's byte budget, the way libopus
400/// takes `max_data_bytes`, so a buffer smaller than this does not fail — it
401/// quietly codes a smaller packet, and the stream comes out under the rate you
402/// asked for.
403///
404/// RFC 6716 §3.4 caps a coded frame at 1275 bytes. The longest duration one call
405/// can ask for is 120 ms, which the encoder lays out as six 20 ms frames sharing
406/// a TOC byte, a frame-count byte and a two-byte length for all but the last.
407///
408/// ```
409/// # use opus_pure::{Application, OpusEncoder, MAX_PACKET_BYTES};
410/// let mut packet = vec![0u8; MAX_PACKET_BYTES];
411/// # let mut encoder = OpusEncoder::new(48_000, 2, Application::Audio)?;
412/// # let n = encoder.encode(&vec![0.0; 960 * 2], 960, &mut packet)?;
413/// # Ok::<(), opus_pure::Error>(())
414/// ```
415pub const MAX_PACKET_BYTES: usize = 6 * 1275 + 2 + 5 * 2;
416
417/// Lowest bitrate the encoder will act on, matching libopus's `OPUS_SET_BITRATE`
418/// floor. Anything positive below it is raised to it.
419const MIN_BITRATE_BPS: i32 = 500;
420
421/// Highest bitrate per channel, matching libopus's `OPUS_SET_BITRATE` ceiling.
422/// Anything above `MAX_BITRATE_BPS_PER_CHANNEL * channels` is lowered to it.
423const MAX_BITRATE_BPS_PER_CHANNEL: i32 = 300_000;
424
425/// Largest packet that can hold its payload as a single unframed Opus frame.
426///
427/// RFC 6716 §3.4 caps one frame at 1275 bytes, so a code 0 packet tops out at
428/// 1276 including the TOC. libopus applies the same bound in
429/// `opus_encode_frame_native` (`max_data_bytes = IMIN(orig_max_data_bytes, 1276)`).
430const MAX_ONE_FRAME_PACKET: usize = 1276;
431
432/// Write `frame` into `output` as a complete one-frame packet of `target_total`
433/// bytes, returning how many bytes were written.
434///
435/// A CBR target can be larger than a frame is allowed to be: 60 ms stereo above
436/// roughly 170 kbps asks for more than 1275 bytes. The surplus becomes code 3
437/// padding rather than an over-long frame, which is how libopus reconciles its
438/// packet target with the frame limit (`opus_packet_pad` at the end of
439/// `opus_encode_frame_native`).
440fn emit_one_frame_packet(output: &mut [u8], toc: u8, frame: &[u8], target_total: usize) -> usize {
441 let target_total = target_total.min(output.len());
442
443 // The frame already fills the target: plain code 0, no framing overhead.
444 if frame.len() + 1 >= target_total {
445 output[0] = toc;
446 let copy_len = frame.len().min(target_total - 1);
447 output[1..1 + copy_len].copy_from_slice(&frame[..copy_len]);
448 return copy_len + 1;
449 }
450
451 // Code 3, CBR, one frame. The frame-count byte absorbs the single spare byte.
452 output[0] = toc | 0x03;
453 if frame.len() + 2 >= target_total {
454 output[1] = 0x01;
455 output[2..2 + frame.len()].copy_from_slice(frame);
456 return target_total;
457 }
458
459 // Code 3 with padding. `pad_amount` counts the length bytes themselves: a
460 // 255 stands for 254 further padding bytes and demands another length byte,
461 // so `nb_255s * 255 + 1 + last` bytes are accounted for (RFC 6716 §3.2.5).
462 // The padding data itself goes after the frame, at the end of the packet.
463 output[1] = 0x41;
464 let pad_amount = target_total - frame.len() - 2;
465 let nb_255s = (pad_amount - 1) / 255;
466 let mut ptr = 2;
467 for _ in 0..nb_255s {
468 output[ptr] = 255;
469 ptr += 1;
470 }
471 output[ptr] = (pad_amount - 255 * nb_255s - 1) as u8;
472 ptr += 1;
473
474 output[ptr..ptr + frame.len()].copy_from_slice(frame);
475 ptr += frame.len();
476 output[ptr..target_total].fill(0);
477
478 target_total
479}
480
481// libopus opus_encoder.c bandwidth thresholds: (threshold, hysteresis) pairs for
482// NB<->MB, MB<->WB, WB<->SWB, SWB<->FB, interpolated voice<->music by voice_est^2.
483const MONO_VOICE_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 13500, 1000, 14000, 2000];
484const MONO_MUSIC_BANDWIDTH_THRESHOLDS: [i32; 8] = [9000, 700, 9000, 700, 11000, 1000, 12000, 2000];
485const STEREO_VOICE_BANDWIDTH_THRESHOLDS: [i32; 8] =
486 [9000, 700, 9000, 700, 13500, 1000, 14000, 2000];
487const STEREO_MUSIC_BANDWIDTH_THRESHOLDS: [i32; 8] =
488 [9000, 700, 9000, 700, 11000, 1000, 12000, 2000];
489
490/// Port of libopus `decide_fec` (src/opus_encoder.c).
491///
492/// In-band FEC is not free: the redundant copy has to come out of the same
493/// budget as the primary stream, so below a bitrate threshold enabling it costs
494/// more quality than the loss it insures against. libopus keeps a per-bandwidth
495/// threshold with hysteresis, scales it down as the reported loss rises (at high
496/// loss FEC is worth more), and above 5% loss will narrow the coded bandwidth to
497/// find room rather than give FEC up — which is why `bandwidth` is in/out.
498///
499/// Returns whether LBRR should be coded.
500fn decide_fec(
501 use_inband_fec: bool,
502 packet_loss_perc: i32,
503 last_fec: bool,
504 mode: OpusMode,
505 bandwidth: &mut i32,
506 rate: i32,
507) -> bool {
508 /// `(threshold_bps, hysteresis_bps)` per bandwidth, narrowband first.
509 const FEC_THRESHOLDS: [(i32, i32); 5] = [
510 (12000, 1000), // NB
511 (14000, 1000), // MB
512 (16000, 1000), // WB
513 (20000, 1000), // SWB
514 (22000, 1000), // FB
515 ];
516 if !use_inband_fec || packet_loss_perc == 0 || mode == OpusMode::CeltOnly {
517 return false;
518 }
519 let nb = Bandwidth::Narrowband as i32;
520 let orig_bandwidth = *bandwidth;
521 loop {
522 let idx = ((*bandwidth - nb) as usize).min(FEC_THRESHOLDS.len() - 1);
523 let (thres, hysteresis) = FEC_THRESHOLDS[idx];
524 let mut lbrr_rate_thres_bps = if last_fec {
525 thres - hysteresis
526 } else {
527 thres + hysteresis
528 };
529 lbrr_rate_thres_bps =
530 silk_smulwb(lbrr_rate_thres_bps * (125 - packet_loss_perc.min(25)), 655);
531 if rate > lbrr_rate_thres_bps {
532 return true;
533 } else if packet_loss_perc <= 5 {
534 return false;
535 } else if *bandwidth > nb {
536 *bandwidth -= 1;
537 } else {
538 break;
539 }
540 }
541 // No bandwidth left that makes FEC affordable; keep what was asked for.
542 *bandwidth = orig_bandwidth;
543 false
544}
545
546fn compute_equiv_rate(
547 bitrate: i32,
548 channels: usize,
549 frame_rate: i32,
550 vbr: bool,
551 complexity: i32,
552 loss: i32,
553) -> i32 {
554 let mut equiv = bitrate;
555 if frame_rate > 50 {
556 equiv -= (40 * channels as i32 + 20) * (frame_rate - 50);
557 }
558 if !vbr {
559 equiv -= equiv / 12;
560 }
561 equiv = equiv * (90 + complexity) / 100;
562 if loss > 0 {
563 equiv -= equiv * loss / (12 * loss + 20);
564 }
565 equiv
566}
567
568fn compute_mode_threshold(
569 application: Application,
570 channels: usize,
571 prev_was_celt: bool,
572 has_prev_mode: bool,
573 voice_est: i32,
574) -> i32 {
575 let mode_voice = if channels == 1 { 64000 } else { 44000 };
576 let mode_music = 10000;
577
578 let diff = mode_voice - mode_music;
579 let offset = (voice_est * voice_est * diff) >> 14;
580 let mut threshold = mode_music + offset;
581
582 if application == Application::Voip {
583 threshold += 8000;
584 }
585
586 if has_prev_mode {
587 if prev_was_celt {
588 threshold -= 4000;
589 } else {
590 threshold += 4000;
591 }
592 }
593
594 if application == Application::RestrictedLowDelay {
595 threshold = 0;
596 }
597
598 threshold
599}
600
601/// `celt.h`. The factor of six carries the one frame duration whose rate is not
602/// an integer: at 60 ms there are 16.67 frames per second, and `6*Fs/frame_size`
603/// keeps that exact where a plain division would not.
604fn bits_to_bitrate(bits: i32, fs: i32, frame_size: i32) -> i32 {
605 ((bits as i64 * (6 * fs / frame_size) as i64) / 6) as i32
606}
607
608fn bitrate_to_bits(bitrate: i32, fs: i32, frame_size: i32) -> i32 {
609 ((bitrate as i64 * 6) / (6 * fs / frame_size) as i64) as i32
610}
611
612/// The SILK share of a hybrid packet's rate (`opus_encoder.c`).
613///
614/// The allocation is per channel: the total is divided down, the table is read
615/// at the single-channel rate, and the result is scaled back up. Reading the
616/// table at the *total* rate lands in a higher row and hands SILK far more than
617/// its share of a stereo packet.
618fn compute_silk_rate_for_hybrid(
619 rate_bps: i32,
620 bandwidth: Bandwidth,
621 frame20ms: bool,
622 vbr: bool,
623 fec: bool,
624 channels: usize,
625) -> i32 {
626 // total, then the SILK share at (10 ms, 20 ms) without FEC and with it.
627 // FEC costs SILK real bits, so it is given a wider share to spend.
628 #[rustfmt::skip]
629 const RATE_TABLE: &[(i32, i32, i32, i32, i32)] = &[
630 ( 0, 0, 0, 0, 0),
631 (12000, 10000, 10000, 11000, 11000),
632 (16000, 13500, 13500, 15000, 15000),
633 (20000, 16000, 16000, 18000, 18000),
634 (24000, 18000, 18000, 21000, 21000),
635 (32000, 22000, 22000, 28000, 28000),
636 (64000, 38000, 38000, 50000, 50000),
637 ];
638 let share = |row: &(i32, i32, i32, i32, i32)| match (fec, frame20ms) {
639 (false, false) => row.1,
640 (false, true) => row.2,
641 (true, false) => row.3,
642 (true, true) => row.4,
643 };
644
645 // Per channel, and scaled back up at the end.
646 let rate_bps = rate_bps / channels as i32;
647 let n = RATE_TABLE.len();
648 let mut i = 1;
649 while i < n && RATE_TABLE[i].0 <= rate_bps {
650 i += 1;
651 }
652 let mut silk_rate = if i == n {
653 let last = &RATE_TABLE[n - 1];
654 // Above the table, SILK takes half of whatever the rate adds.
655 share(last) + (rate_bps - last.0) / 2
656 } else {
657 let (lo_row, hi_row) = (&RATE_TABLE[i - 1], &RATE_TABLE[i]);
658 let (x0, x1) = (lo_row.0, hi_row.0);
659 (share(lo_row) * (x1 - rate_bps) + share(hi_row) * (rate_bps - x0)) / (x1 - x0)
660 };
661 // C tail adjustments (opus_encoder.c:789): tiny SILK boost for CBR, and
662 // +300 for SWB hybrid (the CELT part starts at band 17 either way but
663 // covers less spectrum, so SILK earns a bigger share).
664 if !vbr {
665 silk_rate += 100;
666 }
667 if bandwidth == Bandwidth::Superwideband {
668 silk_rate += 300;
669 }
670 silk_rate *= channels as i32;
671 // Small stereo adjustment, calibrated in the reference at 32 kb/s. `rate_bps`
672 // is the per-channel rate by this point, as it is in the C.
673 if channels == 2 && rate_bps >= 12000 {
674 silk_rate -= 1000;
675 }
676 silk_rate
677}
678
679/// Shows the encoder's configuration and omits its coding state.
680///
681/// A derived `Debug` here would print every filter history and analysis buffer
682/// the encoder carries, which is tens of kilobytes of numbers that mean nothing
683/// without the codec beside them. What a caller wants from `dbg!` is the
684/// settings, so that is what this prints; the `..` stands for the rest.
685impl std::fmt::Debug for OpusEncoder {
686 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
687 f.debug_struct("OpusEncoder")
688 .field("sampling_rate", &self.sampling_rate)
689 .field("channels", &self.channels)
690 .field("application", &self.application)
691 .field("bitrate_bps", &self.bitrate_bps)
692 .field("complexity", &self.complexity)
693 .field("rate_control", &self.rate_control)
694 .field("use_inband_fec", &self.use_inband_fec)
695 .field("use_dtx", &self.use_dtx)
696 .field("packet_loss_perc", &self.packet_loss_perc)
697 .field("force_bandwidth", &self.force_bandwidth)
698 .field("max_bandwidth", &self.max_bandwidth)
699 .field("signal_type", &self.signal_type)
700 .field("lsb_depth", &self.lsb_depth)
701 .finish_non_exhaustive()
702 }
703}
704
705impl OpusEncoder {
706 /// Create an encoder for `sampling_rate` Hz and `channels` channels.
707 ///
708 /// The rate must be one of 8000, 12000, 16000, 24000 or 48000, and the
709 /// channel count 1 or 2; anything else is
710 /// [`Error::InvalidArgument`]. These three
711 /// arguments are the only settings fixed for the encoder's life. See
712 /// [`Application`] for which one to pass, and the fields on this type for
713 /// everything that can be changed afterwards.
714 ///
715 /// The rate is the rate of the PCM handed to [`encode`](Self::encode), not
716 /// a property of the packets produced: Opus always codes internally at one
717 /// of its own rates and every packet's duration is counted at 48 kHz
718 /// regardless. Passing 48000 avoids a resampling step on the way in.
719 ///
720 /// For more than two channels, see
721 /// [`OpusMSEncoder`](crate::OpusMSEncoder).
722 pub fn new(sampling_rate: i32, channels: usize, application: Application) -> Result<Self> {
723 if ![8000, 12000, 16000, 24000, 48000].contains(&sampling_rate) {
724 return Err(Error::InvalidArgument("Invalid sampling rate"));
725 }
726 if ![1, 2].contains(&channels) {
727 return Err(Error::InvalidArgument("Invalid number of channels"));
728 }
729
730 let mode = celt::modes::default_mode();
731 let mut celt_enc = CeltEncoder::new(mode, channels);
732 celt_enc.set_upsample(celt_upsample(sampling_rate));
733
734 let mut silk_enc = Box::new(SilkEncoder::default());
735 if silk_init_encoder(&mut silk_enc.state[0], 0) != 0 {
736 return Err(Error::Internal("SILK encoder initialization failed"));
737 }
738
739 // Only the starting bandwidth is kept: `encode()` re-derives the coding
740 // mode from bitrate, frame size and signal on every call, so an initial
741 // mode here would never be read.
742 let bw = match application {
743 Application::Voip => match sampling_rate {
744 8000 => Bandwidth::Narrowband,
745 12000 => Bandwidth::Mediumband,
746 16000 => Bandwidth::Wideband,
747 24000 => Bandwidth::Superwideband,
748 48000 => Bandwidth::Fullband,
749 _ => Bandwidth::Narrowband,
750 },
751 Application::RestrictedLowDelay => match sampling_rate {
752 8000 => Bandwidth::Narrowband,
753 12000 => Bandwidth::Mediumband,
754 16000 => Bandwidth::Wideband,
755 24000 => Bandwidth::Superwideband,
756 _ => Bandwidth::Fullband,
757 },
758 Application::Audio => {
759 if sampling_rate <= 16000 {
760 match sampling_rate {
761 8000 => Bandwidth::Narrowband,
762 12000 => Bandwidth::Mediumband,
763 _ => Bandwidth::Wideband,
764 }
765 } else {
766 match sampling_rate {
767 24000 => Bandwidth::Superwideband,
768 _ => Bandwidth::Fullband,
769 }
770 }
771 }
772 };
773
774 let variable_hp_smth2_q15 = silk_lin2log(60) << 8;
775
776 Ok(Self {
777 celt_enc,
778 silk_enc,
779 application,
780 sampling_rate,
781 channels,
782 bandwidth: bw,
783 bitrate_bps: 64000,
784 complexity: 9,
785 rate_control: RateControl::ConstrainedVbr,
786 use_inband_fec: false,
787 use_dtx: false,
788 nb_no_activity_ms_q1: 0,
789 range_final: 0,
790 packet_loss_perc: 0,
791 lbrr_coded: false,
792 silk_initialized: false,
793 prev_enc_mode: None,
794 variable_hp_smth2_q15,
795 auto_bandwidth: 0,
796 first_frame: true,
797 force_bandwidth: None,
798 signal_type: None,
799 max_bandwidth: Bandwidth::Fullband,
800 tonality: analysis::TonalityAnalysisState::new(sampling_rate),
801 analysis_kfft: celt::kiss_fft::KissFftState::new(480),
802 lsb_depth: DEFAULT_LSB_DEPTH,
803 coded_lsb_depth: DEFAULT_LSB_DEPTH,
804 voice_ratio: -1,
805 detected_bandwidth: 0,
806 hp_mem: vec![0; channels * 2],
807
808 buf_from_s16: Vec::new(),
809 buf_filtered: Vec::new(),
810 buf_silk_input: Vec::new(),
811 buf_stereo_mid: Vec::new(),
812 buf_stereo_side: Vec::new(),
813 buf_celt_input: Vec::new(),
814 down_fir_l: None,
815 down_fir_r: None,
816 silk_prefill_tail: Vec::new(),
817 silk_prefill_pending: false,
818 buf_left: Vec::new(),
819 buf_right: Vec::new(),
820 celt_prefill_tail: Vec::new(),
821 celt_delay: vec![0.0; celt_delay_samples(sampling_rate, application) * channels],
822 celt_delay_next: Vec::new(),
823 rc: RangeCoder::new_encoder(1),
824 })
825 }
826
827 /// Final range-coder state of the last encoded packet (libopus
828 /// OPUS_GET_FINAL_RANGE). Stored in opus_demo `.bit` framing so the reference
829 /// decoder can verify encoder/decoder range-coder agreement per packet.
830 pub fn final_range(&self) -> u32 {
831 self.range_final
832 }
833
834 /// The sample rate this encoder was created with, in Hz.
835 pub fn sample_rate(&self) -> i32 {
836 self.sampling_rate
837 }
838
839 /// The channel count this encoder was created with.
840 pub fn channels(&self) -> usize {
841 self.channels
842 }
843
844 /// The [`Application`] this encoder was created with.
845 pub fn application(&self) -> Application {
846 self.application
847 }
848
849 /// Samples per channel of algorithmic delay, at this encoder's sample rate
850 /// (libopus `OPUS_GET_LOOKAHEAD`).
851 ///
852 /// The encoder's output trails its input by this much, so a decoder should
853 /// discard this many samples from the start to line the two up again. It is
854 /// not a constant: [`Application::RestrictedLowDelay`] gives up the 4 ms
855 /// the other two spend keeping SILK and CELT aligned, so it is 120 samples
856 /// at 48 kHz where `Audio` and `Voip` are 312.
857 ///
858 /// For an Ogg stream this is what
859 /// [`OpusHead::pre_skip`](crate::OpusHead::pre_skip) must carry, expressed
860 /// at 48 kHz — which [`OpusHead::for_encoder`](crate::OpusHead::for_encoder)
861 /// does for you, and is the reason to prefer it over
862 /// [`OpusHead::new`](crate::OpusHead::new).
863 pub fn lookahead(&self) -> usize {
864 celt_prefill_samples(self.sampling_rate)
865 + celt_delay_samples(self.sampling_rate, self.application)
866 }
867
868 /// Discard everything the encoder has learned, keeping its settings.
869 ///
870 /// Equivalent to building a new encoder with the same sample rate, channel
871 /// count and [`Application`], then re-applying every setting you had
872 /// changed — which is what it does. Use it to encode an unrelated second
873 /// stream through the same instance, so that nothing from the first one
874 /// (the filter histories, the bandwidth hysteresis, the speech/music
875 /// decision) carries across and colours its opening frames.
876 ///
877 /// This is libopus's `OPUS_RESET_STATE`. Note it re-initialises the coding
878 /// state rather than merely rewinding it, so it is not free; it is cheaper
879 /// and far less error-prone than trying to keep a used encoder honest by
880 /// hand, but a caller counting allocations should know it makes some.
881 pub fn reset_state(&mut self) -> Result<()> {
882 let mut fresh = Self::new(self.sampling_rate, self.channels, self.application)?;
883 fresh.bitrate_bps = self.bitrate_bps;
884 fresh.complexity = self.complexity;
885 fresh.rate_control = self.rate_control;
886 fresh.use_inband_fec = self.use_inband_fec;
887 fresh.use_dtx = self.use_dtx;
888 fresh.packet_loss_perc = self.packet_loss_perc;
889 fresh.force_bandwidth = self.force_bandwidth;
890 fresh.signal_type = self.signal_type;
891 fresh.max_bandwidth = self.max_bandwidth;
892 fresh.lsb_depth = self.lsb_depth;
893 *self = fresh;
894 Ok(())
895 }
896
897 /// opus_encoder.c:1296 voice_est ladder: forced by `signal_type` when set,
898 /// else analysis-driven when voice_ratio is known, else application defaults.
899 fn compute_voice_est(&self) -> i32 {
900 match self.signal_type {
901 Some(Signal::Voice) => return 127,
902 Some(Signal::Music) => return 0,
903 None => {}
904 }
905 if self.voice_ratio >= 0 {
906 let mut v = (self.voice_ratio * 327) >> 8;
907 // For AUDIO, never be more than 90% confident of having speech.
908 if self.application == Application::Audio {
909 v = v.min(115);
910 }
911 v
912 } else {
913 match self.application {
914 Application::Voip => 115,
915 Application::Audio => 48,
916 Application::RestrictedLowDelay => 0,
917 }
918 }
919 }
920
921 /// Encode `frame_size` samples per channel into one Opus packet, returning
922 /// how many bytes of `output` it filled.
923 ///
924 /// `input` is interleaved and must hold `frame_size * channels` samples.
925 /// `frame_size` is one of the nine durations Opus defines — 2.5, 5, 10, 20,
926 /// 40, 60, 80, 100 or 120 ms at this encoder's sample rate — and anything
927 /// else is an `InvalidArgument`. Whether the packet ends up holding one
928 /// coded frame or several is the encoder's to decide: only SILK has
929 /// configurations past 20 ms, so a longer packet in any other mode is
930 /// several frames sharing one TOC byte. A caller sees the difference only in
931 /// the packet's framing, never in its duration.
932 ///
933 /// `output.len()` is the packet's **byte budget**, not merely a capacity.
934 /// This is libopus's `max_data_bytes`, and it means a short buffer does not
935 /// produce an error — the encoder codes a smaller packet to fit it, and the
936 /// stream quietly comes out under the bitrate you asked for. Pass
937 /// [`MAX_PACKET_BYTES`](crate::MAX_PACKET_BYTES) unless you are deliberately
938 /// capping the instantaneous rate, for instance to a network MTU. The one
939 /// size that is refused outright is a buffer under two bytes, which cannot
940 /// hold any packet at all.
941 ///
942 /// Samples outside ±1 are coded rather than rejected, so a caller working
943 /// in float can drive the encoder past full scale. If your source is
944 /// integer PCM, prefer [`encode_s16`](Self::encode_s16), which is the same
945 /// encoder told the truth about its input's precision.
946 pub fn encode(&mut self, input: &[f32], frame_size: usize, output: &mut [u8]) -> Result<usize> {
947 self.encode_native(input, frame_size, output, MAX_ENCODING_DEPTH)
948 }
949
950 /// Encode `frame_size` samples per channel of 16-bit PCM into one packet,
951 /// returning how many bytes of `output` it filled.
952 ///
953 /// The same encoder as [`encode`](Self::encode) in every respect but one:
954 /// it knows the input came from 16 bits. That matters because the encoder
955 /// treats anything below the source's own noise floor as digital silence
956 /// and codes it as such, and the floor sits `2^-depth` from full scale. Told
957 /// 24 bits when the input has 16, it holds detail no 16-bit source could
958 /// carry and spends bits on the dither in the bottom bits; told 16, it
959 /// drops out where the source does. libopus draws the same distinction
960 /// between `opus_encode` and `opus_encode_float`, and this matches it,
961 /// including honouring a lower [`lsb_depth`](Self::lsb_depth) if the caller
962 /// has set one.
963 ///
964 /// Conversion is `sample / 32768`, which is exact — the scale is a power of
965 /// two — so this differs from converting by hand and calling
966 /// [`encode`](Self::encode) only in the depth, never in the samples.
967 ///
968 /// ```
969 /// # use opus_pure::{Application, OpusEncoder};
970 /// let mut encoder = OpusEncoder::new(48_000, 2, Application::Audio)?;
971 /// let pcm = vec![0i16; 960 * 2]; // 20 ms of stereo at 48 kHz
972 /// let mut packet = vec![0u8; 4000];
973 /// let n = encoder.encode_s16(&pcm, 960, &mut packet)?;
974 /// # assert!(n > 0);
975 /// # Ok::<(), opus_pure::Error>(())
976 /// ```
977 pub fn encode_s16(
978 &mut self,
979 input: &[i16],
980 frame_size: usize,
981 output: &mut [u8],
982 ) -> Result<usize> {
983 let wanted = frame_size * self.channels;
984 // Checked here as well as in `encode_native`, because the conversion
985 // below reads the whole span before the encoder ever sees it.
986 if input.len() < wanted {
987 return Err(Error::InvalidArgument(
988 "input is shorter than frame_size * channels",
989 ));
990 }
991 let mut converted = std::mem::take(&mut self.buf_from_s16);
992 converted.clear();
993 converted.extend(input[..wanted].iter().copied().map(i16_to_float));
994 let result = self.encode_native(&converted, frame_size, output, 16);
995 self.buf_from_s16 = converted;
996 result
997 }
998
999 /// Bring every setting into the range the encoder can honour, and reject
1000 /// the one value that cannot mean anything.
1001 ///
1002 /// The settings are public fields, so a caller can put any `i32` in them
1003 /// between one call and the next, and several of them go on to index a
1004 /// table or feed a shift. Clamping here keeps that in one place instead of
1005 /// at every read, and clamping the field itself rather than a private copy
1006 /// means [`Debug`] afterwards reports what the encoder is actually doing
1007 /// rather than what was asked for.
1008 ///
1009 /// A rate of zero or less is rejected rather than clamped. libopus spells
1010 /// "decide for me" and "as high as it goes" as the negative sentinels
1011 /// `OPUS_AUTO` (-1000) and `OPUS_BITRATE_MAX` (-1), and this crate has no
1012 /// sentinels — [`bitrate_bps`](Self::bitrate_bps) is always a rate, and
1013 /// "decide for me" is spelled by leaving the default alone. Quietly
1014 /// treating -1000 as half a kilobit would hand somebody porting from C a
1015 /// stream of two-byte packets and no reason why.
1016 fn normalize_settings(&mut self) -> Result<()> {
1017 if self.bitrate_bps <= 0 {
1018 return Err(Error::InvalidArgument(
1019 "bitrate_bps must be a positive rate; this crate has no \
1020 OPUS_AUTO/OPUS_BITRATE_MAX sentinel",
1021 ));
1022 }
1023 self.bitrate_bps = self.bitrate_bps.clamp(
1024 MIN_BITRATE_BPS,
1025 MAX_BITRATE_BPS_PER_CHANNEL * self.channels as i32,
1026 );
1027 self.complexity = self.complexity.clamp(0, 10);
1028 self.packet_loss_perc = self.packet_loss_perc.clamp(0, 100);
1029 self.lsb_depth = self.lsb_depth.clamp(8, MAX_ENCODING_DEPTH);
1030 Ok(())
1031 }
1032
1033 /// The body both entry points share. `api_lsb_depth` is the precision the
1034 /// entry point itself implies, which the caller's own setting can lower but
1035 /// not raise (libopus `opus_encode_native`).
1036 pub(crate) fn encode_native(
1037 &mut self,
1038 input: &[f32],
1039 frame_size: usize,
1040 output: &mut [u8],
1041 api_lsb_depth: i32,
1042 ) -> Result<usize> {
1043 self.normalize_settings()?;
1044 self.coded_lsb_depth = api_lsb_depth.min(self.lsb_depth);
1045 if output.len() < 2 {
1046 return Err(Error::buffer_too_small(2, output.len()));
1047 }
1048
1049 // Reject an impossible duration before anything below advances the
1050 // analysis, the bandwidth hysteresis or any other encoder state.
1051 let duration = PacketDuration::classify(self.sampling_rate, frame_size).ok_or(
1052 Error::InvalidArgument("Invalid frame size for sampling rate"),
1053 )?;
1054 // C takes the input on trust because it is a bare pointer. Here the
1055 // slice knows its own length, and every layer below reads
1056 // `frame_size * channels` samples from it unconditionally, so a short
1057 // one has to be an error rather than an index out of bounds.
1058 if input.len() < frame_size * self.channels {
1059 return Err(Error::InvalidArgument(
1060 "input is shorter than frame_size * channels",
1061 ));
1062 }
1063 // The rate the *packet* repeats at, which is what the bitrate, mode and
1064 // bandwidth decisions below are scaled by (`opus_encoder.c`
1065 // `frame_rate = st->Fs/frame_size`). The rate a single coded frame
1066 // repeats at is only known once the split is decided, and is what the
1067 // TOC carries.
1068 let packet_rate = self.sampling_rate / frame_size as i32;
1069
1070 // ---- Tonality analysis (opus_encoder.c:1123) ----
1071 // Runs over the whole packet, and `analysis_info` is the whole-packet
1072 // view the decisions below are made from. `analysis_at` is where the
1073 // ring stood before it was consumed: a split packet rewinds to it so
1074 // each frame can pull the slice covering the audio it actually codes
1075 // (`opus_encoder.c` analysis_read_pos_bak). `None` means the analysis
1076 // did not run, so there is nothing in the ring for a frame to read and
1077 // nothing to rewind.
1078 let mut analysis_at = None;
1079 let mut analysis_info = analysis::AnalysisInfo::default();
1080 if self.complexity >= 7 && self.sampling_rate >= 16000 {
1081 if let Some(kfft) = &self.analysis_kfft {
1082 analysis_at = Some(self.tonality.read_position());
1083 analysis_info = analysis::run_analysis(
1084 &mut self.tonality,
1085 kfft,
1086 input,
1087 frame_size,
1088 frame_size,
1089 self.channels,
1090 self.sampling_rate,
1091 self.coded_lsb_depth,
1092 );
1093 }
1094 } else if self.tonality.initialized() {
1095 self.tonality.reset();
1096 }
1097
1098 // voice_ratio / detected_bandwidth from the analysis (opus_encoder.c:1154).
1099 // This is the whole packet's silence; a split packet re-tests each frame
1100 // on its own, so a silent stretch inside a long packet still reaches DTX.
1101 let is_silence = self.is_digital_silence(&input[..frame_size * self.channels]);
1102 if !is_silence {
1103 self.voice_ratio = -1;
1104 }
1105 // The classifier's verdict is used from the first frame it reports one,
1106 // as libopus does. This port used to discount the first ten, on the
1107 // theory that libopus's analysis lookahead left it converged by frame 0
1108 // — but libopus spends about twenty frames climbing from "voice" to
1109 // "music" on musical input, so the early hybrid run that guard removed
1110 // was the reference's own behaviour rather than a defect. Trusting the
1111 // verdict brings the mode decision to within one packet of libopus at
1112 // every rate and application measured; the guard put it as much as
1113 // twenty-one packets out.
1114 self.detected_bandwidth = 0;
1115 if analysis_info.valid {
1116 // Auto path (signal_type override applies later in compute_voice_est):
1117 // pick the hysteresis-correct probability.
1118 let prob = if self.prev_enc_mode.is_none() {
1119 analysis_info.music_prob
1120 } else if self.prev_enc_mode == Some(OpusMode::CeltOnly) {
1121 analysis_info.music_prob_max
1122 } else {
1123 analysis_info.music_prob_min
1124 };
1125 self.voice_ratio = (0.5 + 100.0 * (1.0 - prob)).floor() as i32;
1126 let ab = analysis_info.bandwidth;
1127 self.detected_bandwidth = if ab <= 12 {
1128 Bandwidth::Narrowband as i32
1129 } else if ab <= 14 {
1130 Bandwidth::Mediumband as i32
1131 } else if ab <= 16 {
1132 Bandwidth::Wideband as i32
1133 } else if ab <= 18 {
1134 Bandwidth::Superwideband as i32
1135 } else {
1136 Bandwidth::Fullband as i32
1137 };
1138 }
1139
1140 // Mode selection: match C's opus_encode_native() behavior.
1141 // C reference auto-selects between SILK_ONLY and CELT_ONLY; Hybrid is
1142 // produced afterwards by bandwidth overrides (SILK-only + FB/SWB → Hybrid).
1143 let mut mode = if self.application == Application::RestrictedLowDelay {
1144 OpusMode::CeltOnly
1145 } else {
1146 let equiv = compute_equiv_rate(
1147 self.bitrate_bps,
1148 self.channels,
1149 packet_rate,
1150 !self.rate_control.is_cbr(),
1151 self.complexity,
1152 self.packet_loss_perc,
1153 );
1154 let prev_was_celt = self.prev_enc_mode == Some(OpusMode::CeltOnly);
1155 let has_prev_mode = self.prev_enc_mode.is_some();
1156 let voice_est = self.compute_voice_est();
1157 let threshold = compute_mode_threshold(
1158 self.application,
1159 self.channels,
1160 prev_was_celt,
1161 has_prev_mode,
1162 voice_est,
1163 );
1164 // libopus compares the equivalent rate against the threshold and
1165 // nothing else (opus_encoder.c). This port carried an extra
1166 // `&& self.sampling_rate >= 24000` from the crate it was forked
1167 // from, where CELT below 48 kHz was broken — 24 kHz decoded to
1168 // full-scale noise. That was fixed here when CELT learned to code
1169 // lower rates the way libopus does, but the guard outlived it and
1170 // pinned 8, 12 and 16 kHz to SILK whatever the content or bitrate.
1171 // At 16 kHz that cost a third of the requested bitrate, because
1172 // SILK saturates at wideband and simply cannot spend the rest.
1173 if equiv >= threshold {
1174 OpusMode::CeltOnly
1175 } else {
1176 OpusMode::SilkOnly
1177 }
1178 };
1179
1180 // ---- Automatic rate-dependent bandwidth selection (opus_encoder.c:1456) ----
1181 // Walk down from FB; stop at the first bandwidth whose hysteresis-adjusted
1182 // threshold the equivalent rate meets. Thresholds interpolate voice<->music
1183 // by voice_est^2. Without the tonality analysis we cannot do
1184 // detected-bandwidth reduction, so this reproduces libopus's
1185 // complexity-0 choices (measured: WB @16k, SWB @20k, FB @24k+ voip mono).
1186 {
1187 let equiv = compute_equiv_rate(
1188 self.bitrate_bps,
1189 self.channels,
1190 packet_rate,
1191 !self.rate_control.is_cbr(),
1192 self.complexity,
1193 self.packet_loss_perc,
1194 );
1195 let voice_est: i32 = self.compute_voice_est();
1196 let (vt, mt) = if self.channels == 2 {
1197 (
1198 &STEREO_VOICE_BANDWIDTH_THRESHOLDS,
1199 &STEREO_MUSIC_BANDWIDTH_THRESHOLDS,
1200 )
1201 } else {
1202 (
1203 &MONO_VOICE_BANDWIDTH_THRESHOLDS,
1204 &MONO_MUSIC_BANDWIDTH_THRESHOLDS,
1205 )
1206 };
1207 let mut th = [0i32; 8];
1208 for i in 0..8 {
1209 th[i] = mt[i] + ((voice_est * voice_est * (vt[i] - mt[i])) >> 14);
1210 }
1211 const NB: i32 = Bandwidth::Narrowband as i32; // 1101
1212 const MB: i32 = Bandwidth::Mediumband as i32; // 1102
1213 const FB: i32 = Bandwidth::Fullband as i32; // 1105
1214 let mut bw = FB;
1215 while bw > NB {
1216 let idx = (2 * (bw - MB)) as usize;
1217 let mut threshold = th[idx];
1218 let hysteresis = th[idx + 1];
1219 if !self.first_frame {
1220 if self.auto_bandwidth >= bw {
1221 threshold -= hysteresis;
1222 } else {
1223 threshold += hysteresis;
1224 }
1225 }
1226 if equiv >= threshold {
1227 break;
1228 }
1229 bw -= 1;
1230 }
1231 // Mediumband is no longer used by libopus's selector.
1232 if bw == MB {
1233 bw = Bandwidth::Wideband as i32;
1234 }
1235 self.auto_bandwidth = bw;
1236 // Hybrid at unsafe CBR rates starves SILK: cap at WB below 15 kb/s.
1237 if mode != OpusMode::CeltOnly && self.rate_control.is_cbr() && self.bitrate_bps < 15000
1238 {
1239 bw = bw.min(Bandwidth::Wideband as i32);
1240 }
1241 // NB/MB SILK-internal rates (8/12 kHz) aren't wired for >16 kHz API
1242 // input yet (no 48k->8k/12k encode resamplers); clamp to WB.
1243 if mode != OpusMode::CeltOnly && self.sampling_rate > 16000 {
1244 bw = bw.max(Bandwidth::Wideband as i32);
1245 }
1246 // Never code above the input's Nyquist (opus_encoder.c:1516).
1247 if self.sampling_rate <= 24000 {
1248 bw = bw.min(Bandwidth::Superwideband as i32);
1249 }
1250 if self.sampling_rate <= 16000 {
1251 bw = bw.min(Bandwidth::Wideband as i32);
1252 }
1253 if self.sampling_rate <= 12000 {
1254 bw = bw.min(Bandwidth::Mediumband as i32);
1255 }
1256 if self.sampling_rate <= 8000 {
1257 bw = bw.min(Bandwidth::Narrowband as i32);
1258 }
1259 // (MB remap above may have been undone by the caps; keep WB floor
1260 // only where the API rate allows it.)
1261 if bw == Bandwidth::Mediumband as i32 && self.sampling_rate > 12000 {
1262 bw = Bandwidth::Wideband as i32;
1263 }
1264 // Use the detected bandwidth to reduce the coded bandwidth
1265 // (opus_encoder.c:1526), conservatively floored by rate. (For
1266 // CELT-only this is currently undone below — no end-band support.)
1267 // For CELT-only, hold the detected-bandwidth narrowing until the
1268 // leak_boost dynalloc lands: decisions already match libopus
1269 // frame-for-frame (64k st music: 27:704/31:680/23:90 both), but our
1270 // dynalloc lacks C's leakage compensation at the spectral cut, so
1271 // the same narrowing costs 0.25 ODG more than C pays (PEAQ-gated
1272 // out). Hybrid/SILK caps (incl. hybrid SWB) stay live.
1273 // CELT-only keeps FULL bandwidth by choice: C's detected-bandwidth
1274 // narrowing costs PEAQ universally (libopus's own -2.11 at 64k st
1275 // IS its narrowed score; our FB encode scores -1.65 on the same
1276 // clip). leak_boost did NOT change this verdict (tested 2026-07-09
1277 // with the full dynalloc live: narrowing still -2.37). Hybrid/SILK
1278 // caps stay (they pick coding MODE, not spectral truncation).
1279 if self.detected_bandwidth != 0
1280 && self.force_bandwidth.is_none()
1281 && mode != OpusMode::CeltOnly
1282 {
1283 let ch = self.channels as i32;
1284 let equiv2 = equiv; // same 20-ms equivalent rate as the walk
1285 let min_det = if equiv2 <= 18000 * ch && mode == OpusMode::CeltOnly {
1286 NB
1287 } else if equiv2 <= 24000 * ch && mode == OpusMode::CeltOnly {
1288 MB
1289 } else if equiv2 <= 30000 * ch {
1290 Bandwidth::Wideband as i32
1291 } else if equiv2 <= 44000 * ch {
1292 Bandwidth::Superwideband as i32
1293 } else {
1294 FB
1295 };
1296 bw = bw.min(self.detected_bandwidth.max(min_det));
1297 }
1298 // Cap by OPUS_SET_MAX_BANDWIDTH before the force override
1299 // (opus_encoder.c: bandwidth = IMIN(bandwidth, max_bandwidth)), but
1300 // keep the WB floor for non-CELT >16 kHz input — NB/MB SILK from
1301 // 48 kHz needs the 48->8/12k encode resamplers we don't have, so a
1302 // max_bandwidth of NB/MB there would emit an uncodeable config.
1303 let mut max_bw = self.max_bandwidth as i32;
1304 if mode != OpusMode::CeltOnly && self.sampling_rate > 16000 {
1305 max_bw = max_bw.max(Bandwidth::Wideband as i32);
1306 }
1307 bw = bw.min(max_bw);
1308 // The CELT TOC has no mediumband config; C maps MB down to NB.
1309 if mode == OpusMode::CeltOnly && bw == MB {
1310 bw = NB;
1311 }
1312 self.bandwidth = match self.force_bandwidth {
1313 Some(f) => f,
1314 None => match bw {
1315 x if x == NB => Bandwidth::Narrowband,
1316 x if x == MB => Bandwidth::Mediumband,
1317 x if x == Bandwidth::Wideband as i32 => Bandwidth::Wideband,
1318 x if x == Bandwidth::Superwideband as i32 => Bandwidth::Superwideband,
1319 x if x == FB => Bandwidth::Fullband,
1320 _ => Bandwidth::Wideband,
1321 },
1322 };
1323 self.first_frame = false;
1324 }
1325
1326 // Never code a band the input cannot contain. `force_bandwidth` is a
1327 // user override that bypasses the selection above, so this clamp has to
1328 // sit after it — libopus applies the same one last
1329 // (opus_encoder.c, "prevents Opus from wasting bits on frequencies that
1330 // are above the Nyquist rate of the input signal"). Without it, asking
1331 // for e.g. mediumband at 8 kHz emits a config the rest of the encoder
1332 // cannot honour, and the result is not merely mis-tuned: it decodes to
1333 // full-scale noise.
1334 self.bandwidth = clamp_bandwidth_to_rate(self.bandwidth, self.sampling_rate);
1335
1336 // Whether this packet carries in-band FEC. libopus settles this after
1337 // the bandwidth is chosen and lets it narrow the bandwidth further, so
1338 // it has to run here rather than alongside the other SILK settings.
1339 {
1340 let equiv = compute_equiv_rate(
1341 self.bitrate_bps,
1342 self.channels,
1343 packet_rate,
1344 !self.rate_control.is_cbr(),
1345 self.complexity,
1346 self.packet_loss_perc,
1347 );
1348 let mut bw = self.bandwidth as i32;
1349 self.lbrr_coded = decide_fec(
1350 self.use_inband_fec,
1351 self.packet_loss_perc.clamp(0, 100),
1352 self.lbrr_coded,
1353 mode,
1354 &mut bw,
1355 equiv,
1356 );
1357 if bw != self.bandwidth as i32 {
1358 self.bandwidth = bandwidth_from_i32(bw);
1359 }
1360 }
1361
1362 if mode == OpusMode::SilkOnly
1363 && matches!(
1364 self.bandwidth,
1365 Bandwidth::Superwideband | Bandwidth::Fullband
1366 )
1367 {
1368 mode = OpusMode::Hybrid;
1369 }
1370 if mode == OpusMode::Hybrid
1371 && matches!(
1372 self.bandwidth,
1373 Bandwidth::Narrowband | Bandwidth::Mediumband | Bandwidth::Wideband
1374 )
1375 {
1376 mode = OpusMode::SilkOnly;
1377 }
1378
1379 // Stereo hybrid is now CONFORMANT (the CELT intensity-clamp fix), but
1380 // our FIXED-point stereo SILK executes it worse than plain CELT-FB above
1381 // ~28 kb/s: PEAQ on stereo speech (ODG) measured hybrid −2.196/−2.193 vs
1382 // CELT-FB −2.136/−2.057 at 32k/48k (CELT-FB wins), while at 24k hybrid
1383 // −2.198 beats CELT-FB −2.240. libopus's FLOAT stereo SILK hybrid beats
1384 // both everywhere — the gap is fixed-vs-float, not a bug. So route
1385 // stereo hybrid to CELT-FB except at the low rates where it wins. (Force
1386 // via OPUS_SET_BANDWIDTH if the true hybrid path is wanted.) The clean
1387 // fix is float stereo SILK — a large port, tracked in the roadmap.
1388 if self.channels == 2 && mode == OpusMode::Hybrid && self.bitrate_bps > 28000 {
1389 mode = OpusMode::CeltOnly;
1390 self.bandwidth = Bandwidth::Fullband;
1391 }
1392
1393 mode = coerce_mode_for_packet_rate(mode, packet_rate);
1394
1395 // CELT has no mediumband configuration. libopus widens to wideband
1396 // (opus_encoder.c) rather than letting the TOC fall into the narrowband
1397 // slot, which would halve the coded bandwidth for a caller who asked for
1398 // more than narrowband.
1399 if mode == OpusMode::CeltOnly && self.bandwidth == Bandwidth::Mediumband {
1400 self.bandwidth = Bandwidth::Wideband;
1401 }
1402
1403 // ---- The packet is decided; code it (opus_encoder.c:1698) ----
1404 // Everything above ran once for the whole packet, because every frame in
1405 // a packet shares one TOC byte and so must agree on mode, bandwidth and
1406 // duration. `layout` says how many frames those decisions imply. This is
1407 // libopus's split between `opus_encode_native` and
1408 // `opus_encode_frame_native`.
1409 let layout = duration.layout(self.sampling_rate, mode);
1410 if layout.nb_frames == 1 {
1411 return self.encode_frame(
1412 input,
1413 frame_size,
1414 output,
1415 mode,
1416 layout.frame_rate,
1417 &analysis_info,
1418 is_silence,
1419 );
1420 }
1421 self.encode_split_packet(input, output, mode, layout, analysis_at)
1422 }
1423
1424 /// Code one packet as `layout.nb_frames` frames sharing a TOC.
1425 ///
1426 /// The frames are coded into scratch buffers and assembled by the
1427 /// repacketizer, exactly as `opus_encode_native` does — there is no separate
1428 /// multi-frame writer. Each frame gets its own slice of the packet's byte
1429 /// budget and its own slice of the tonality analysis.
1430 fn encode_split_packet(
1431 &mut self,
1432 input: &[f32],
1433 output: &mut [u8],
1434 mode: OpusMode,
1435 layout: PacketLayout,
1436 analysis_at: Option<analysis::AnalysisReadPos>,
1437 ) -> Result<usize> {
1438 let PacketLayout {
1439 enc_frame_size,
1440 nb_frames,
1441 frame_rate,
1442 } = layout;
1443
1444 // Under CBR the packet owes the caller an exact size, so the frame
1445 // budget is carved out of that; under VBR the only ceiling is the
1446 // caller's buffer.
1447 let frame_size = enc_frame_size * nb_frames;
1448 let target_bits =
1449 (self.bitrate_bps as i64 * frame_size as i64 / self.sampling_rate as i64) as i32;
1450 let repacketize_len = if self.rate_control.is_cbr() {
1451 (((target_bits + 4) / 8) as usize).min(output.len())
1452 } else {
1453 output.len()
1454 };
1455 // Each coded frame carries a TOC byte the repacketizer strips, so the
1456 // frames may spend `nb_frames` bytes more between them than the packet
1457 // will hold. The framing itself is charged up front at its worst case.
1458 let header = max_header_bytes(nb_frames);
1459 if repacketize_len + nb_frames <= header {
1460 return Err(Error::buffer_too_small(header + 1, repacketize_len));
1461 }
1462 let max_len_sum = nb_frames + repacketize_len - header;
1463 // One frame's share of the configured bitrate. Both this and an equal
1464 // division of the packet bound each frame, so no frame can spend the
1465 // packet's whole budget however the mode decision inside it goes.
1466 let per_frame_bitrate_bytes = ((self.bitrate_bps as i64 * enc_frame_size as i64
1467 / self.sampling_rate as i64)
1468 / 8) as usize;
1469
1470 let mut rp = crate::repacketizer::Repacketizer::new();
1471
1472 // Not enough of a packet to seat every frame. libopus answers this the
1473 // same way (`opus_encoder.c:1340`, "If the space is too low to do
1474 // something useful, emit 'PLC' frames"): write the framing and no
1475 // payload, so the packet still announces its duration and the decoder
1476 // conceals it. Coding some frames and starving the rest would desync
1477 // the stream instead.
1478 if max_len_sum < 3 * nb_frames {
1479 let toc = gen_toc(mode, frame_rate, self.bandwidth, self.channels);
1480 for _ in 0..nb_frames {
1481 rp.cat(&[toc])?;
1482 }
1483 self.range_final = 0;
1484 self.prev_enc_mode = Some(mode);
1485 let pad_to = self.rate_control.is_cbr().then_some(repacketize_len);
1486 return Self::emit(rp, nb_frames, pad_to, output);
1487 }
1488
1489 let mut scratch = vec![0u8; max_len_sum];
1490 let mut tot_size = 0usize;
1491 let mut dtx_count = 0usize;
1492
1493 // Rewind the tonality ring to where it stood before `run_analysis`
1494 // consumed the whole packet's worth of it.
1495 if let Some(at) = analysis_at {
1496 self.tonality.set_read_position(at);
1497 }
1498
1499 for i in 0..nb_frames {
1500 let curr_max = per_frame_bitrate_bytes
1501 .min(max_len_sum / nb_frames)
1502 // A frame is a TOC byte plus the two a range coder needs to say
1503 // anything at all, so a bitrate share below that is raised
1504 // rather than handed over as an impossible budget.
1505 .max(3)
1506 // What is actually left, which is the one bound that cannot be
1507 // relaxed: the frames have to fit the buffer they are coded into.
1508 .min(max_len_sum - tot_size);
1509 let base = i * enc_frame_size * self.channels;
1510 let frame_input = &input[base..base + enc_frame_size * self.channels];
1511
1512 let analysis_info = match analysis_at {
1513 Some(_) => analysis::tonality_get_info(&mut self.tonality, enc_frame_size),
1514 None => analysis::AnalysisInfo::default(),
1515 };
1516 let is_silence = self.is_digital_silence(frame_input);
1517
1518 let len = self.encode_frame(
1519 frame_input,
1520 enc_frame_size,
1521 &mut scratch[tot_size..tot_size + curr_max],
1522 mode,
1523 frame_rate,
1524 &analysis_info,
1525 is_silence,
1526 )?;
1527 if len == 1 {
1528 dtx_count += 1;
1529 }
1530 rp.cat(&scratch[tot_size..tot_size + len])?;
1531 tot_size += len;
1532 }
1533
1534 // CBR still owes the caller an exact packet, unless every frame was
1535 // dropped to DTX — padding a packet that says "nothing was sent" would
1536 // put the bytes back that DTX exists to save.
1537 let pad_to =
1538 (self.rate_control.is_cbr() && dtx_count != nb_frames).then_some(repacketize_len);
1539 Self::emit(rp, nb_frames, pad_to, output)
1540 }
1541
1542 /// Assemble the held frames into `output` (`opus_repacketizer_out_range_impl`
1543 /// plus C's copy into the caller's buffer).
1544 fn emit(
1545 rp: crate::repacketizer::Repacketizer,
1546 nb_frames: usize,
1547 pad_to: Option<usize>,
1548 output: &mut [u8],
1549 ) -> Result<usize> {
1550 let packet = rp.out_range_impl(0, nb_frames, pad_to)?;
1551 if packet.len() > output.len() {
1552 return Err(Error::buffer_too_small(packet.len(), output.len()));
1553 }
1554 output[..packet.len()].copy_from_slice(&packet);
1555 Ok(packet.len())
1556 }
1557
1558 /// Whether every sample is at or below the quantiser's own noise floor
1559 /// (libopus `is_digital_silence`).
1560 fn is_digital_silence(&self, input: &[f32]) -> bool {
1561 let thresh = 1.0f32 / (1i64 << self.coded_lsb_depth) as f32;
1562 input.iter().fold(0.0f32, |m, &v| m.max(v.abs())) <= thresh
1563 }
1564
1565 /// Code one frame — one TOC's worth of audio — into `output`.
1566 ///
1567 /// libopus `opus_encode_frame_native`. Everything the mode and bandwidth
1568 /// decision settled is already in `self`; what varies frame to frame within
1569 /// one packet is the audio, its analysis and its byte budget.
1570 #[allow(clippy::too_many_arguments)]
1571 fn encode_frame(
1572 &mut self,
1573 input: &[f32],
1574 frame_size: usize,
1575 output: &mut [u8],
1576 mode: OpusMode,
1577 frame_rate: i32,
1578 analysis_info: &analysis::AnalysisInfo,
1579 is_silence: bool,
1580 ) -> Result<usize> {
1581 if output.len() < 2 {
1582 return Err(Error::buffer_too_small(2, output.len()));
1583 }
1584 let curr_bw = self.bandwidth;
1585
1586 // The frame durations each mode has a TOC configuration for
1587 // (RFC 6716 §3.1). `PacketDuration::layout` only ever produces frame
1588 // sizes that satisfy these, so reaching one of these errors means the
1589 // mode decision and the split disagree.
1590 let codable = match mode {
1591 OpusMode::CeltOnly => matches!(frame_rate, 400 | 200 | 100 | 50),
1592 OpusMode::Hybrid => matches!(frame_rate, 100 | 50),
1593 // 60 ms is 16 because the frame rate is truncated; see
1594 // `frame_rate_from_params`.
1595 OpusMode::SilkOnly => matches!(frame_rate, 100 | 50 | 25 | 16),
1596 };
1597 if !codable {
1598 return Err(Error::Internal("frame size is not codable in this mode"));
1599 }
1600
1601 // CELT can only transform frame sizes its 48 kHz mode has an `lm` for.
1602 // Reject the combination rather than letting it reach the MDCT, which
1603 // would fall back to `lm = 0` and read past the output spectrum.
1604 if mode != OpusMode::SilkOnly
1605 && !celt_can_code_frame(frame_size * celt_upsample(self.sampling_rate))
1606 {
1607 return Err(Error::Internal(
1608 "frame size is not codable by the CELT layer at this sampling rate",
1609 ));
1610 }
1611
1612 // Voice-activity flag for DTX (opus_encoder.c:1160). Silence is always
1613 // inactive; with analysis, use the VAD probability; without it, assume
1614 // active (conservative — never DTX away real audio). We skip the
1615 // peak-energy SNR fallback, which only ever ADDS activity.
1616 let activity = if is_silence {
1617 false
1618 } else if analysis_info.valid {
1619 analysis_info.activity_probability >= 0.1
1620 } else {
1621 true
1622 };
1623
1624 // ---- Mode-transition resets (opus_encoder.c:1449 + 2054) ----
1625 // The decoder resets its CELT state on ANY mode change (when there is
1626 // no redundancy) and its SILK state when leaving CELT-only; the
1627 // encoder must mirror both or the streams desync from that frame on.
1628 if let Some(prev) = self.prev_enc_mode
1629 && prev != mode
1630 {
1631 if mode != OpusMode::SilkOnly {
1632 let ch = self.channels;
1633 self.celt_enc = CeltEncoder::new(celt::modes::default_mode(), ch);
1634 // Prefill one CELT block so the fresh state has real
1635 // preemph/overlap history instead of a hard edge
1636 // (opus_encoder.c:2060). Skipped when the previous frame was
1637 // shorter than a block and no tail was captured; that only
1638 // costs a transition artifact, never decoder sync.
1639 self.celt_enc
1640 .set_upsample(celt_upsample(self.sampling_rate));
1641 let prefill = celt_prefill_samples(self.sampling_rate);
1642 if self.celt_prefill_tail.len() == prefill * ch {
1643 let mut dummy = RangeCoder::new_encoder(2);
1644 let tail = std::mem::take(&mut self.celt_prefill_tail);
1645 self.celt_enc
1646 .encode_with_budget(&tail, prefill, &mut dummy, 0, 21, 16);
1647 self.celt_prefill_tail = tail;
1648 }
1649 }
1650 if mode != OpusMode::CeltOnly && prev == OpusMode::CeltOnly {
1651 self.silk_initialized = false;
1652 self.silk_prefill_pending = true;
1653 }
1654 }
1655
1656 // SILK prefill tail: last 10 ms of API-rate mono input.
1657 if self.channels == 1 {
1658 let n10 = (self.sampling_rate / 100) as usize;
1659 if frame_size >= n10 {
1660 self.silk_prefill_tail.resize(n10, 0);
1661 for i in 0..n10 {
1662 self.silk_prefill_tail[i] =
1663 (input[frame_size - n10 + i] * 32768.0).clamp(-32768.0, 32767.0) as i16;
1664 }
1665 }
1666 }
1667
1668 // ---- Advance the CELT input timeline (opus_encoder.c:1967, 2301, 2304) ----
1669 // CELT reads `delay` samples behind the caller, so everything it touches
1670 // comes off one virtual timeline: `celt_delay` (the samples it has not
1671 // reached yet) followed by this frame's `input`. Index `i` on that
1672 // timeline is `i - delay` on the caller's.
1673 //
1674 // All three reads happen here, before the delay buffer moves, and before
1675 // any early return below — DTX included. The timeline is a position in
1676 // the input, not a coder state, so it has to advance on every frame
1677 // whatever the mode does.
1678 {
1679 let ch = self.channels;
1680 let delay = celt_delay_samples(self.sampling_rate, self.application);
1681 debug_assert_eq!(self.celt_delay.len(), delay * ch);
1682 let timeline = |celt_delay: &[f32], c: usize, i: usize| -> f32 {
1683 if i < delay {
1684 celt_delay[c * delay + i]
1685 } else {
1686 input[(i - delay) * ch + c]
1687 }
1688 };
1689
1690 // What CELT codes this frame: `frame_size` samples from the start of
1691 // the timeline, i.e. ending `delay` short of the newest input.
1692 if mode != OpusMode::SilkOnly {
1693 self.buf_celt_input.resize(frame_size * ch, 0.0);
1694 for c in 0..ch {
1695 for i in 0..frame_size {
1696 self.buf_celt_input[c * frame_size + i] = timeline(&self.celt_delay, c, i);
1697 }
1698 }
1699 }
1700
1701 // The 2.5 ms immediately before the *next* CELT frame, kept for a
1702 // prefill if the next mode transition needs one. On the timeline
1703 // that block ends exactly where the new delay buffer begins. A frame
1704 // shorter than one CELT block leaves the tail empty, which the
1705 // prefill treats as "skip".
1706 let prefill = celt_prefill_samples(self.sampling_rate);
1707 if frame_size >= prefill {
1708 self.celt_prefill_tail.resize(prefill * ch, 0.0);
1709 for c in 0..ch {
1710 for i in 0..prefill {
1711 self.celt_prefill_tail[c * prefill + i] =
1712 timeline(&self.celt_delay, c, frame_size - prefill + i);
1713 }
1714 }
1715 } else {
1716 self.celt_prefill_tail.clear();
1717 }
1718
1719 // Slide the timeline forward by one frame, into the spare buffer
1720 // and back, rather than allocating a fresh one every frame and
1721 // dropping the old one. `timeline` reads `celt_delay`, so the two
1722 // cannot be the same buffer, and swapping is what keeps both
1723 // allocations alive across calls.
1724 if delay > 0 {
1725 let mut next = std::mem::take(&mut self.celt_delay_next);
1726 next.clear();
1727 next.resize(delay * ch, 0.0);
1728 for c in 0..ch {
1729 for i in 0..delay {
1730 next[c * delay + i] = timeline(&self.celt_delay, c, frame_size + i);
1731 }
1732 }
1733 self.celt_delay_next = std::mem::replace(&mut self.celt_delay, next);
1734 }
1735 }
1736
1737 let toc = gen_toc(mode, frame_rate, self.bandwidth, self.channels);
1738 output[0] = toc;
1739
1740 // ---- DTX decision (opus_encoder.c:2137 decide_dtx_mode) ----
1741 // After enough consecutive inactive frames, emit a TOC-only 1-byte
1742 // packet: the decoder sees an empty payload and runs comfort-noise /
1743 // PLC. We decide before the (skipped) SILK/CELT encode — SILK's own DTX
1744 // likewise stops coding, so the encoder state simply doesn't advance;
1745 // the codecs resync on the next active frame.
1746 if self.use_dtx && (analysis_info.valid || is_silence) {
1747 let frame_ms_q1 = 2 * 1000 * frame_size as i32 / self.sampling_rate;
1748 let dtx = if !activity {
1749 self.nb_no_activity_ms_q1 += frame_ms_q1;
1750 const LO: i32 = silk::define::NB_SPEECH_FRAMES_BEFORE_DTX * 20 * 2; // 400
1751 const HI: i32 = (silk::define::NB_SPEECH_FRAMES_BEFORE_DTX
1752 + silk::define::MAX_CONSECUTIVE_DTX)
1753 * 20
1754 * 2; // 1200
1755 if self.nb_no_activity_ms_q1 > LO {
1756 if self.nb_no_activity_ms_q1 <= HI {
1757 true
1758 } else {
1759 self.nb_no_activity_ms_q1 = LO;
1760 false
1761 }
1762 } else {
1763 false
1764 }
1765 } else {
1766 self.nb_no_activity_ms_q1 = 0;
1767 false
1768 };
1769 if dtx {
1770 self.prev_enc_mode = Some(mode);
1771 self.range_final = 0;
1772 return Ok(1);
1773 }
1774 } else {
1775 self.nb_no_activity_ms_q1 = 0;
1776 }
1777
1778 let target_bits =
1779 (self.bitrate_bps as i64 * frame_size as i64 / self.sampling_rate as i64) as i32;
1780 let cbr_bytes = ((target_bits + 4) / 8) as usize;
1781 let max_data_bytes = output.len();
1782
1783 // CBR: the packet is exactly the target size. VBR: the packet ends
1784 // wherever the coded frame ends — SILK-only packets stop at whatever
1785 // SILK produced, and the CELT layer picks its own frame size
1786 // (compute_vbr) and shrinks the coder to it — so the only bound that
1787 // matters is the caller's buffer.
1788 let n_bytes = if self.rate_control.is_cbr() {
1789 cbr_bytes.min(max_data_bytes).max(1)
1790 } else {
1791 max_data_bytes.max(3)
1792 };
1793
1794 // `n_bytes` is the packet the caller asked for; `frame_bytes` is what a
1795 // single coded frame is allowed to occupy. They diverge only when a CBR
1796 // target exceeds the frame limit, and the surplus then leaves `encode`
1797 // as code 3 padding instead of an over-long frame that libopus would
1798 // reject as OPUS_INVALID_PACKET. Mirrors libopus's split between
1799 // `orig_max_data_bytes` and `max_data_bytes`.
1800 let frame_bytes = n_bytes.min(MAX_ONE_FRAME_PACKET);
1801
1802 self.rc.reset_for_encode((frame_bytes - 1) as u32);
1803
1804 let mut hybrid_silk_rate = 0i32;
1805 if mode == OpusMode::SilkOnly || mode == OpusMode::Hybrid {
1806 // SILK's internal rate follows the coded bandwidth, exactly as
1807 // libopus derives `maxInternalSampleRate` from it: narrowband is
1808 // coded at 8 kHz, mediumband at 12, everything else at 16. Deriving
1809 // it from the API rate instead made the TOC advertise a bandwidth
1810 // the encoder had not actually coded, and the decoder then ran SILK
1811 // at a different rate than the encoder did.
1812 let silk_fs_khz = if mode == OpusMode::Hybrid {
1813 16
1814 } else {
1815 let by_bandwidth = match self.bandwidth {
1816 Bandwidth::Narrowband => 8,
1817 Bandwidth::Mediumband => 12,
1818 _ => 16,
1819 };
1820 by_bandwidth.min(self.sampling_rate / 1000)
1821 };
1822 let silk_fs_hz = silk_fs_khz * 1000;
1823
1824 let frame_ms = (frame_size as i32 * 1000) / self.sampling_rate;
1825 // A stream that codes stereo needs its second channel built and the
1826 // mid/side smoothers primed before the first frame that uses them.
1827 let n_channels_internal = self.channels as i32;
1828 let channels_changed = n_channels_internal != self.silk_enc.n_channels_internal;
1829 if n_channels_internal > self.silk_enc.n_channels_internal {
1830 silk_init_encoder(&mut self.silk_enc.state[1], 0);
1831 self.silk_enc.stereo.reset_for_stereo();
1832 // Both resamplers are rebuilt below, so the two channels start
1833 // from the same state: were they to start at different points,
1834 // the first stereo frame would carry a phase difference that is
1835 // purely an artefact of the filters and not of the image.
1836 }
1837 self.silk_enc.n_channels_internal = n_channels_internal;
1838
1839 // libopus reconfigures SILK on every call (silk_Encode ->
1840 // silk_control_encoder), so do the same rather than gating on a
1841 // hand-maintained list of what might have changed. The frame
1842 // duration is one of the inputs: 20 -> 40 ms leaves `frame_length`
1843 // alone but doubles `n_frames_per_packet`, and skipping the call
1844 // left SILK coding one frame into a packet whose TOC announced two.
1845 // What must stay gated is the *resampler*, whose filter memory is
1846 // real audio history: rebuilding it every frame would restart the
1847 // filter mid-stream.
1848 let resampler_stale = !self.silk_initialized
1849 || self.silk_enc.state[0].s_cmn.fs_khz != silk_fs_khz
1850 || channels_changed;
1851 for ch in 0..n_channels_internal as usize {
1852 silk_control_encoder(
1853 &mut self.silk_enc.state[ch],
1854 silk_fs_khz,
1855 frame_ms,
1856 self.complexity,
1857 );
1858 self.silk_enc.state[ch].s_cmn.use_cbr =
1859 if self.rate_control.is_cbr() { 1 } else { 0 };
1860 }
1861 if resampler_stale {
1862 self.silk_initialized = true;
1863 self.down_fir_l =
1864 silk::resampler::SilkEncoderResampler::new(self.sampling_rate, silk_fs_hz);
1865 self.down_fir_r =
1866 silk::resampler::SilkEncoderResampler::new(self.sampling_rate, silk_fs_hz);
1867 }
1868
1869 // SILK prefill after CELT-only (opus_encoder.c prefill=1): run 10 ms
1870 // of the previous audio through the fresh resampler + SILK warmup
1871 // path so the first coded SILK frame has real LTP/shape history.
1872 if self.silk_prefill_pending {
1873 self.silk_prefill_pending = false;
1874 let n10 = (self.sampling_rate / 100) as usize;
1875 if self.channels == 1 && self.silk_prefill_tail.len() == n10 {
1876 let need = silk_fs_khz as usize * 10;
1877 let mut resampled = vec![0i16; need];
1878 if let Some(r) = &mut self.down_fir_l {
1879 r.process(&mut resampled, &self.silk_prefill_tail);
1880 } else {
1881 resampled.copy_from_slice(&self.silk_prefill_tail[..need]);
1882 }
1883 let (state, stereo) = (&mut self.silk_enc.state[0], &mut self.silk_enc.stereo);
1884 silk::enc_api::silk_encode_prefill(state, stereo, &resampled, 0);
1885 }
1886 }
1887
1888 for ch in 0..n_channels_internal as usize {
1889 let cmn = &mut self.silk_enc.state[ch].s_cmn;
1890 cmn.packet_loss_perc = self.packet_loss_perc.clamp(0, 100);
1891
1892 // libopus silk_setup_LBRR. The gain bump is what makes the
1893 // redundant copy cheap; it shrinks as loss rises, so LBRR stays
1894 // decodable when it is most needed. A stream that had no LBRR in
1895 // the previous packet gets the full 7: that packet was coded at
1896 // the higher rate FEC-off allows, so there is more to give back.
1897 let lbrr_in_previous_packet = cmn.lbrr_enabled != 0;
1898 cmn.lbrr_enabled = if self.lbrr_coded { 1 } else { 0 };
1899 if cmn.lbrr_enabled != 0 {
1900 cmn.lbrr_gain_increases = if !lbrr_in_previous_packet {
1901 7
1902 } else {
1903 (7 - silk_smulwb(cmn.packet_loss_perc, 13107)).max(3)
1904 };
1905 }
1906 }
1907
1908 let hp_freq_smth1 = if mode == OpusMode::CeltOnly {
1909 silk_lin2log(60) << 8
1910 } else {
1911 self.silk_enc.state[0].s_cmn.variable_hp_smth1_q15
1912 };
1913
1914 const VARIABLE_HP_SMTH_COEF2_Q16: i32 = 984;
1915 self.variable_hp_smth2_q15 = silk_smlawb(
1916 self.variable_hp_smth2_q15,
1917 hp_freq_smth1 - self.variable_hp_smth2_q15,
1918 VARIABLE_HP_SMTH_COEF2_Q16,
1919 );
1920
1921 let cutoff_hz = silk_log2lin(silk_rshift(self.variable_hp_smth2_q15, 8));
1922
1923 let required_size = frame_size * self.channels;
1924 self.buf_filtered.resize(required_size, 0);
1925 if self.application == Application::Voip {
1926 hp_cutoff(
1927 input,
1928 cutoff_hz,
1929 &mut self.buf_filtered,
1930 &mut self.hp_mem,
1931 frame_size,
1932 self.channels,
1933 self.sampling_rate,
1934 );
1935 } else {
1936 for (i, &x) in input.iter().enumerate() {
1937 self.buf_filtered[i] = (x * 32768.0).clamp(-32768.0, 32767.0) as i16;
1938 }
1939 }
1940
1941 let input_i16 = &self.buf_filtered;
1942
1943 let (silk_left, silk_right): (&[i16], &[i16]) = if self.channels == 2 {
1944 // Stereo SILK/hybrid: deinterleave and resample EACH channel to
1945 // the SILK-internal rate with its own filter state, then hand
1946 // both to silk_encode. The mid/side conversion happens in there,
1947 // not here, because how wide the image is coded depends on the
1948 // frame's bit budget and on state that advances with the coder.
1949 let frame_length = input_i16.len() / 2;
1950 self.buf_left.resize(frame_length, 0);
1951 self.buf_right.resize(frame_length, 0);
1952 for i in 0..frame_length {
1953 self.buf_left[i] = input_i16[2 * i];
1954 self.buf_right[i] = input_i16[2 * i + 1];
1955 }
1956 let ds_len =
1957 frame_length * silk_fs_khz as usize / (self.sampling_rate as usize / 1000);
1958 self.buf_stereo_mid.resize(ds_len, 0);
1959 self.buf_stereo_side.resize(ds_len, 0);
1960 if let (Some(rl), Some(rr)) = (&mut self.down_fir_l, &mut self.down_fir_r) {
1961 rl.process(&mut self.buf_stereo_mid, &self.buf_left);
1962 rr.process(&mut self.buf_stereo_side, &self.buf_right);
1963 }
1964 self.buf_left.resize(ds_len, 0);
1965 self.buf_right.resize(ds_len, 0);
1966 self.buf_left
1967 .copy_from_slice(&self.buf_stereo_mid[..ds_len]);
1968 self.buf_right
1969 .copy_from_slice(&self.buf_stereo_side[..ds_len]);
1970 (&self.buf_left[..ds_len], &self.buf_right[..ds_len])
1971 } else {
1972 // Mono. When the API rate is above SILK's internal rate this
1973 // is a direct FIR for the whole ratio, never a chain of
1974 // halvings: the old down2 + down2_3 pair aliased badly (a 1 kHz
1975 // sine came back with a 7 kHz mirror at a third of its
1976 // amplitude). When the rates match it is the pass-through, which
1977 // still runs so the delay comes out the same either way.
1978 let silk_frame_size =
1979 frame_size * silk_fs_khz as usize / (self.sampling_rate as usize / 1000);
1980 self.buf_silk_input.resize(silk_frame_size, 0);
1981 if let Some(r) = &mut self.down_fir_l {
1982 r.process(&mut self.buf_silk_input, input_i16);
1983 } else {
1984 self.buf_silk_input
1985 .copy_from_slice(&input_i16[..silk_frame_size]);
1986 }
1987 (&self.buf_silk_input[..], &[][..])
1988 };
1989
1990 let mut pn_bytes = 0;
1991
1992 // The frames-per-second math below divides by silk_input.len(), which is
1993 // at the SILK-INTERNAL rate — so the rate here must be internal too.
1994 // Using the API rate at 48 kHz told SILK to target 3x the real budget
1995 // with a hard max_bits cap -> the gain loop crushed every frame to fit
1996 // -> near-silent output (only worked at 16 kHz API where they coincide).
1997 let silk_rate_for_calc = silk_fs_hz;
1998 let silk_frame_len = silk_left.len();
1999
2000 let silk_bitrate = if mode == OpusMode::Hybrid {
2001 let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
2002 let frame20ms = frame_duration_ms >= 20;
2003 // libopus distributes the *frame's* budget, not the configured
2004 // bitrate: capped by the caller's buffer, less the TOC byte
2005 // (`opus_encoder.c`, `bits_target`). At 20 kb/s and 20 ms that
2006 // is 19600 rather than 20000, which is a whole table row's
2007 // worth of interpolation.
2008 let fs = self.sampling_rate;
2009 let bits_target = (8 * frame_bytes as i32).min(bitrate_to_bits(
2010 self.bitrate_bps,
2011 fs,
2012 frame_size as i32,
2013 )) - 8;
2014 let r = compute_silk_rate_for_hybrid(
2015 bits_to_bitrate(bits_target, fs, frame_size as i32),
2016 curr_bw,
2017 frame20ms,
2018 !self.rate_control.is_cbr(),
2019 self.lbrr_coded,
2020 self.channels,
2021 );
2022 hybrid_silk_rate = r;
2023 r
2024 } else if self.rate_control.is_cbr() {
2025 (8i64 * (n_bytes - 1) as i64 * silk_rate_for_calc as i64 / silk_frame_len as i64)
2026 as i32
2027 } else {
2028 // VBR: n_bytes is only the buffer cap; target the configured rate.
2029 self.bitrate_bps
2030 };
2031 let silk_max_bits = if mode == OpusMode::Hybrid {
2032 let total_max_bits = ((frame_bytes - 1) * 8) as i32;
2033 if self.rate_control.is_cbr() {
2034 let silk_bits = (silk_bitrate as i64 * silk_frame_len as i64
2035 / silk_rate_for_calc as i64) as i32;
2036 let other_bits = 0i32.max(total_max_bits - silk_bits);
2037 0i32.max(total_max_bits - other_bits * 3 / 4)
2038 } else {
2039 let frame_duration_ms = frame_size as i32 * 1000 / self.sampling_rate;
2040 let frame20ms = frame_duration_ms >= 20;
2041 let max_bit_rate = compute_silk_rate_for_hybrid(
2042 bits_to_bitrate(total_max_bits, self.sampling_rate, frame_size as i32),
2043 curr_bw,
2044 frame20ms,
2045 !self.rate_control.is_cbr(),
2046 self.lbrr_coded,
2047 self.channels,
2048 );
2049 max_bit_rate * frame_size as i32 / self.sampling_rate
2050 }
2051 } else {
2052 ((frame_bytes - 1) * 8) as i32
2053 };
2054 let silk_use_cbr = if mode == OpusMode::Hybrid && self.rate_control.is_cbr() {
2055 0
2056 } else if self.rate_control.is_cbr() {
2057 1
2058 } else {
2059 0
2060 };
2061 let ret = silk_encode(
2062 &mut self.silk_enc,
2063 silk_left,
2064 silk_right,
2065 &mut self.rc,
2066 &mut pn_bytes,
2067 silk_bitrate,
2068 silk_max_bits,
2069 silk_use_cbr,
2070 1,
2071 );
2072 if ret != 0 {
2073 return Err(Error::Internal("SILK encoding failed"));
2074 }
2075
2076 // What SILK just coded, handed to CELT the way `opus_encoder.c` hands
2077 // it over (`CELT_SET_SILK_INFO`, hybrid only). The high band's rate,
2078 // its temporal resolution and its transient decision all key off it.
2079 let idx = &self.silk_enc.state[0].s_cmn.indices;
2080 self.celt_enc.silk_signal_type = idx.signal_type as i32;
2081 self.celt_enc.silk_offset = crate::silk::tables::SILK_QUANTIZATION_OFFSETS_Q10
2082 [(idx.signal_type >> 1) as usize][idx.quant_offset_type as usize]
2083 as i32;
2084 }
2085
2086 // The hybrid redundancy flag is only present when >=37 bits remain
2087 // (opus_encoder.c: ec_tell+17+20 <= 8*(max_data_bytes-1)); the decoder
2088 // gates its read identically. Writing it unconditionally desynced every
2089 // frame where SILK left fewer than 37 bits (starved low-rate hybrid).
2090 if mode == OpusMode::Hybrid && self.rc.tell() + 37 <= ((frame_bytes - 1) * 8) as i32 {
2091 self.rc.encode_bit_logp(false, 12); // redundancy = 0
2092 }
2093
2094 if mode == OpusMode::Hybrid {
2095 let nb_compr_bytes = (frame_bytes - 1) as u32;
2096 self.rc.shrink(nb_compr_bytes);
2097 }
2098
2099 let silk_ret_bytes = if mode == OpusMode::SilkOnly {
2100 ((self.rc.tell() + 7) >> 3) as usize
2101 } else {
2102 0
2103 };
2104
2105 if mode == OpusMode::CeltOnly || mode == OpusMode::Hybrid {
2106 self.celt_enc.analysis = celt::AnalysisInfo {
2107 valid: analysis_info.valid,
2108 tonality: analysis_info.tonality,
2109 tonality_slope: analysis_info.tonality_slope,
2110 noisiness: analysis_info.noisiness,
2111 activity: analysis_info.activity,
2112 music_prob: analysis_info.music_prob,
2113 music_prob_min: analysis_info.music_prob_min,
2114 music_prob_max: analysis_info.music_prob_max,
2115 bandwidth: analysis_info.bandwidth,
2116 activity_probability: analysis_info.activity_probability,
2117 max_pitch_ratio: analysis_info.max_pitch_ratio,
2118 leak_boost: analysis_info.leak_boost,
2119 };
2120 self.celt_enc.complexity = self.complexity;
2121 self.celt_enc.lsb_depth = self.coded_lsb_depth;
2122 // Census 2026-08-07 fix: loss_rate was never assigned, so CELT's
2123 // prefilter loss ladder (celt.rs) and coarse-energy intra bias were
2124 // dead even with OPUS_SET_PACKET_LOSS_PERC set. Default 0 = no
2125 // change on the default path (libopus opus_encoder.c parity).
2126 self.celt_enc.loss_rate = self.packet_loss_perc;
2127 let start_band = if mode == OpusMode::Hybrid { 17 } else { 0 };
2128 let end_band = celt_endband_for_bandwidth(self.bandwidth);
2129 let total_packet_bits = ((frame_bytes - 1) * 8) as i32;
2130 // VBR: hand CELT the target in eighth-bits per frame; it picks the
2131 // frame's size (compute_vbr) and shrinks the range coder to it. The
2132 // hybrid target covers the whole packet (CELT adds back the SILK
2133 // bits via `target += tell`).
2134 // libopus turns constrained VBR *off* for the hybrid high band
2135 // (`opus_encoder.c`: `OPUS_SET_VBR_CONSTRAINT(0)` beside the
2136 // bitrate ctl) and leaves it on for CELT-only. The constrained path
2137 // caps the frame against a reservoir sized for the whole packet,
2138 // which in hybrid is mostly SILK's bits, so leaving it on starves
2139 // the high band of the little rate it was given.
2140 // Hybrid has always run unconstrained here, matching libopus.
2141 // `RateControl::Vbr` extends that to every mode; the other two
2142 // variants keep exactly the behaviour this line had before it took
2143 // the setting into account.
2144 self.celt_enc.constrained_vbr =
2145 mode != OpusMode::Hybrid && self.rate_control != RateControl::Vbr;
2146 self.celt_enc.vbr_rate = if self.rate_control.is_cbr() {
2147 0
2148 } else {
2149 let den = self.sampling_rate >> 3; // Fs >> BITRES
2150 // In hybrid, CELT codes only the high band, so its target is
2151 // what SILK did not take (`opus_encoder.c`: `OPUS_SET_BITRATE
2152 // (st->bitrate_bps - st->silk_mode.bitRate)`). Handing it the
2153 // whole packet's rate and then adding the SILK bits back via
2154 // `target += tell` counts the low band twice.
2155 let rate = self.bitrate_bps - hybrid_silk_rate;
2156 ((rate as i64 * frame_size as i64 + (den >> 1) as i64) / den as i64) as i32
2157 };
2158
2159 // Filled above from the delayed timeline, planar, for every mode
2160 // that reaches CELT.
2161 let celt_input: &[f32] = &self.buf_celt_input;
2162
2163 if self.rc.tell() <= total_packet_bits {
2164 self.celt_enc
2165 .set_upsample(celt_upsample(self.sampling_rate));
2166 self.celt_enc.encode_with_budget(
2167 celt_input,
2168 frame_size,
2169 &mut self.rc,
2170 start_band,
2171 end_band,
2172 total_packet_bits,
2173 );
2174 }
2175 }
2176
2177 self.rc.done();
2178 self.range_final = self.rc.rng;
2179
2180 // Payload actually coded. SILK reports its own length; CELT and hybrid
2181 // fill the coder under CBR, or shrank it to the size compute_vbr chose.
2182 let payload_len = if mode == OpusMode::SilkOnly {
2183 let mut len = silk_ret_bytes.min(self.rc.storage as usize);
2184 // Trailing zero bytes carry no information, and dropping them keeps
2185 // a short frame from being framed as if it filled the budget.
2186 while len > 2 && self.rc.buf[len - 1] == 0 {
2187 len -= 1;
2188 }
2189 len
2190 } else if self.rate_control.is_cbr() {
2191 frame_bytes - 1
2192 } else {
2193 (self.rc.storage as usize).min(frame_bytes - 1)
2194 };
2195
2196 // CBR owes the caller a packet of exactly `n_bytes`; VBR emits only what
2197 // was coded. Where the two differ by more than the frame limit allows,
2198 // `emit_one_frame_packet` makes up the difference with code 3 padding.
2199 let target_total = if self.rate_control.is_cbr() {
2200 n_bytes
2201 } else {
2202 payload_len + 1
2203 };
2204
2205 self.prev_enc_mode = Some(mode);
2206 Ok(emit_one_frame_packet(
2207 output,
2208 toc,
2209 &self.rc.buf[..payload_len],
2210 target_total,
2211 ))
2212 }
2213}
2214
2215#[cfg(test)]
2216mod silk_rate_tests {
2217 use super::compute_silk_rate_for_hybrid;
2218 use crate::Bandwidth;
2219
2220 /// Mono, no FEC: read the table straight off.
2221 fn mono(rate: i32) -> i32 {
2222 compute_silk_rate_for_hybrid(rate, Bandwidth::Fullband, true, true, false, 1)
2223 }
2224
2225 #[test]
2226 fn test_reference_table_exact_entries() {
2227 assert_eq!(mono(12000), 10000);
2228 assert_eq!(mono(16000), 13500);
2229 assert_eq!(mono(20000), 16000);
2230 assert_eq!(mono(24000), 18000);
2231 assert_eq!(mono(32000), 22000);
2232 assert_eq!(mono(64000), 38000);
2233 }
2234
2235 #[test]
2236 fn test_32kbps_gives_22kbps_silk() {
2237 assert_eq!(mono(32000), 22000);
2238 }
2239
2240 #[test]
2241 fn test_interpolation_between_table_entries() {
2242 assert_eq!(mono(18000), 14750);
2243 }
2244
2245 #[test]
2246 fn test_above_table_max_gives_half_extra() {
2247 assert_eq!(mono(72000), 38000 + (72000 - 64000) / 2);
2248 }
2249
2250 /// FEC costs SILK real bits, so the reference gives it a wider share at the
2251 /// same total rate rather than letting the redundant copy squeeze the frame.
2252 #[test]
2253 fn fec_widens_the_silk_share() {
2254 for rate in [12000, 16000, 20000, 24000, 32000, 64000] {
2255 let no_fec =
2256 compute_silk_rate_for_hybrid(rate, Bandwidth::Fullband, true, false, false, 1);
2257 let fec = compute_silk_rate_for_hybrid(rate, Bandwidth::Fullband, true, false, true, 1);
2258 assert!(
2259 fec > no_fec,
2260 "{rate}: FEC should widen SILK's share, got {fec} against {no_fec}"
2261 );
2262 }
2263 // The reference's own numbers at two table rows.
2264 assert_eq!(
2265 compute_silk_rate_for_hybrid(20000, Bandwidth::Fullband, true, true, true, 1),
2266 18000
2267 );
2268 assert_eq!(
2269 compute_silk_rate_for_hybrid(64000, Bandwidth::Fullband, true, true, true, 1),
2270 50000
2271 );
2272 }
2273
2274 /// The allocation is per channel: the total is divided down, the table is
2275 /// read at the single-channel rate, and the result scaled back up. Reading
2276 /// the table at the *total* rate lands in a higher row and hands SILK far
2277 /// more than its share, which is what this port used to do.
2278 #[test]
2279 fn stereo_allocates_per_channel() {
2280 // 32 kb/s stereo is 16 kb/s per channel: 13500 each, less the 1000 the
2281 // reference trims from stereo above 12 kb/s per channel.
2282 assert_eq!(
2283 compute_silk_rate_for_hybrid(32000, Bandwidth::Fullband, true, true, false, 2),
2284 13500 * 2 - 1000
2285 );
2286 // Below the trim threshold there is no trim: 20 kb/s stereo is 10 kb/s
2287 // per channel, under the 12 kb/s the reference tests against.
2288 let per_channel =
2289 compute_silk_rate_for_hybrid(10000, Bandwidth::Fullband, true, true, false, 1);
2290 assert_eq!(
2291 compute_silk_rate_for_hybrid(20000, Bandwidth::Fullband, true, true, false, 2),
2292 per_channel * 2
2293 );
2294 // And a stereo packet never gets the mono answer for the same total.
2295 assert_ne!(
2296 compute_silk_rate_for_hybrid(32000, Bandwidth::Fullband, true, true, false, 2),
2297 compute_silk_rate_for_hybrid(32000, Bandwidth::Fullband, true, true, false, 1)
2298 );
2299 }
2300
2301 /// Superwideband hybrid gives SILK a little more, because CELT starts at the
2302 /// same band either way but covers less spectrum above it.
2303 #[test]
2304 fn superwideband_adds_to_the_silk_share() {
2305 assert_eq!(
2306 compute_silk_rate_for_hybrid(20000, Bandwidth::Superwideband, true, true, false, 1),
2307 16000 + 300
2308 );
2309 // Per channel first, then scaled: the bonus is per channel too.
2310 assert_eq!(
2311 compute_silk_rate_for_hybrid(40000, Bandwidth::Superwideband, true, true, false, 2),
2312 (16000 + 300) * 2 - 1000
2313 );
2314 }
2315
2316 /// CBR gets a small boost, as in the reference.
2317 #[test]
2318 fn cbr_boosts_the_silk_share() {
2319 assert_eq!(
2320 compute_silk_rate_for_hybrid(20000, Bandwidth::Fullband, true, false, false, 1),
2321 16000 + 100
2322 );
2323 }
2324}