Skip to main content

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}