oxideav_opus/lib.rs
1//! # oxideav-opus
2//!
3//! **Status:** orphan-rebuild scaffold (post 2026-05-20 audit).
4//!
5//! The prior implementation was retired under the workspace clean-room
6//! policy. The crate is being re-implemented from scratch against
7//! RFC 6716 + RFC 8251 + RFC 7587 + RFC 7845 using only material under
8//! `docs/` and black-box validator binaries (`opusdec` / `opusenc`).
9//!
10//! ## Current surface
11//!
12//! * Round 1 lands the [`OpusTocByte`] parser per RFC 6716 §3.1
13//! (Table 2, Table 3, Table 4 — the 32-config × stereo-flag ×
14//! frame-count-code triple that prefixes every well-formed Opus
15//! packet).
16//! * Round 2 lands the [`OpusPacket`] §3.2 frame-packing parser for
17//! all four `c` codes (code 0 single frame; code 1 two equal-size;
18//! code 2 two unequal with §3.2.1 length encoding; code 3 signalled
19//! frame count with optional VBR per-frame lengths and Opus
20//! padding). The returned slices borrow from the input packet, so
21//! the SILK / CELT decoders can be hooked up against them in a
22//! subsequent round without copying.
23//! * Round 3 lands the [`RangeDecoder`] RFC 6716 §4.1 range coder —
24//! the shared entropy primitive consumed by both the SILK and CELT
25//! layers. The sibling `oxideav-celt` crate owns an independent
26//! clean-room copy of the same primitive; both crates carry their
27//! own copy until a shared low-level primitives crate exists.
28//! * Round 4 lands the [`SilkFrameHeader`] decoder for RFC 6716
29//! §4.2.7.1 (stereo prediction weights), §4.2.7.2 (mid-only flag),
30//! §4.2.7.3 (frame type / quantization-offset type), and §4.2.7.5.1
31//! (normalized LSF stage-1 codebook index `I1`). These are the four
32//! structural decisions that gate every subsequent SILK stage
33//! (gains, LSF stage-2, LTP, excitation). Implemented as
34//! inverse-CDF reads against the range decoder, with the PDFs
35//! transcribed from Tables 6, 8, 9, and 14.
36//! * Round 5 lands the [`SubframeGains`] decoder for RFC 6716
37//! §4.2.7.4 — per-subframe quantization gains for the two- or
38//! four-subframe SILK frame. The first subframe is **independently**
39//! coded (Table 11 signal-type-conditioned MSB PDF + Table 12
40//! uniform LSB PDF + the `max(gain_index, previous_log_gain - 16)`
41//! clamp from §4.2.7.4) when the §4.2.7.4 enumeration triggers;
42//! otherwise it's coded as a 41-symbol delta (Table 13) against
43//! the previous coded subframe gain via the `clamp(0,
44//! max(2*delta - 16, prev + delta - 4), 63)` rule. All subsequent
45//! subframes in the frame use the delta path. Output is integer
46//! `log_gain` in `0..=63`; the §4.2.7.4 tail-end `gain_Q16`
47//! conversion (`silk_log2lin`) is part of the excitation stage
48//! and not wired up yet.
49//!
50//! * Round 6 lands the [`LsfStage2`] decoder for RFC 6716 §4.2.7.5.2 —
51//! the per-coefficient stage-2 residual indices `I2[k] ∈ [-10, 10]`
52//! plus the backwards-prediction-undone `res_Q10[k]`. Tables 15
53//! (NB/MB) and 16 (WB) are the eight signal-shape codebooks; Tables
54//! 17 (NB/MB) and 18 (WB) map `(I1, k)` → codebook letter; Table 19
55//! is the 7-cell extension PDF for the `|I2| == 4` saturation case;
56//! Table 20 holds the four prediction-weight lists (A/B for NB/MB,
57//! C/D for WB); Tables 21 (NB/MB) and 22 (WB) map `(I1, k)` →
58//! weight-list. Output stops at `res_Q10[]`.
59//!
60//! * Round 7 lands the [`NlsfReconstructed`] decoder for RFC 6716
61//! §4.2.7.5.3 — the stage-1 codebook lookup (Tables 23 NB/MB and
62//! 24 WB carrying `cb1_Q8[]` for each `I1 ∈ 0..32`), the
63//! low-complexity Inverse Harmonic Mean Weighting (IHMW) derivation
64//! of `w_Q9[k]` from `cb1_Q8[]` via
65//! `w2_Q18[k] = (1024/(cb1_Q8[k]-cb1_Q8[k-1]) + 1024/(cb1_Q8[k+1]-cb1_Q8[k])) << 16`
66//! reduced through the spec's square-root approximation, and the
67//! final reconstructed
68//! `NLSF_Q15[k] = clamp(0, (cb1_Q8[k]<<7) + (res_Q10[k]<<14)/w_Q9[k], 32767)`.
69//! The §4.2.7.5.5 interpolation step that consumes the stabilized
70//! `NLSF_Q15[]` is deferred to a later round.
71//!
72//! * Round 8 lands the [`NlsfStabilized`] decoder for RFC 6716
73//! §4.2.7.5.4 — the normalized-LSF stabilization that enforces the
74//! Table 25 minimum spacing between consecutive `NLSF_Q15[]` entries.
75//! Up to 20 distortion-minimizing re-centring passes run first
76//! (finding the smallest-spacing pair, then the `min_center` /
77//! `max_center` / `center_freq` re-centring, with special handling
78//! for the implicit `NLSF_Q15[-1] = 0` and `NLSF_Q15[d_LPC] = 32768`
79//! edges), falling back after the 20th pass to a guaranteed sort +
80//! forward-`max` + backward-`min` sweep. The fallback's forward sweep
81//! uses 16-bit saturating addition per the RFC 8251 §7 erratum.
82//!
83//! * Round 9 lands the [`LsfInterpolated`] decoder for RFC 6716
84//! §4.2.7.5.5 — the normalized-LSF interpolation that produces the
85//! first-half coefficients of a 20 ms SILK frame. A Q2 factor
86//! `w_Q2 ∈ 0..=4` is decoded from the Table 26 PDF and
87//! `n1_Q15[k] = n0_Q15[k] + (w_Q2*(n2_Q15[k] - n0_Q15[k]) >> 2)` blends
88//! the prior coded frame's NLSF vector (`n0`) with the current
89//! stabilized one (`n2`). After a decoder reset or an uncoded regular
90//! side-channel SILK frame the factor is still decoded (to keep the
91//! range coder in sync) but discarded and `4` is used instead; for a
92//! 10 ms SILK frame no factor is present at all.
93//!
94//! * Round 10 lands the [`LpcQ17`] core converter for RFC 6716
95//! §4.2.7.5.6 — the NLSF → LPC reconstruction (`silk_NLSF2A`). The
96//! Table 28 Q12 cosine table with linear interpolation produces the
97//! re-ordered Q17 cosine vector `c_Q17[]` per Table 27, the
98//! `silk_NLSF2A_find_poly` P/Q recurrence runs in i64 to absorb the
99//! "up to 48 bits of intermediate precision" the spec calls out, and
100//! the last-row sum/difference assembly produces the 32-bit
101//! `a32_Q17[]`.
102//!
103//! * Round 11 lands the §4.2.7.5.7 range-limiting bandwidth expansion
104//! ([`LpcQ17::range_limited`]) — up to 10 rounds of `silk_bwexpander_32`
105//! chirping (`maxabs_Q12 = min((maxabs_Q17 + 16) >> 5, 163838)`, chirp
106//! factor `sc_Q16[0] = 65470 - ((maxabs_Q12 - 32767) << 14) /
107//! ((maxabs_Q12 * (k+1)) >> 2)`) that shrink the raw `a32_Q17[]` until
108//! it fits a signed 16-bit Q12 value, followed by the documented
109//! post-loop Q12 saturation `clamp(-32768, (a + 16) >> 5, 32767) << 5`.
110//! The result is held in the Q17 domain for the §4.2.7.5.8
111//! prediction-gain limiting that follows.
112//!
113//! * Round 12 lands the §4.2.7.5.8 prediction-gain limiting
114//! ([`LpcQ17::prediction_gain_limited`] → [`LpcQ12`]) — the
115//! `silk_LPC_inverse_pred_gain_QA()` stability test (DC-response check
116//! plus the fixed-point Levinson recurrence on the Q24-widened Q12
117//! coefficients, with the `abs(a32_Q24[k][k]) > 16773022` and
118//! `inv_gain_Q30[k] < 107374` instability bounds) driving up to 16
119//! rounds of bandwidth expansion with `sc_Q16[0] = 65536 - (2<<i)`.
120//! The result is the final stable Q12 filter `a_Q12[k]` consumed by the
121//! §4.2.7.9.2 LPC synthesis.
122//!
123//! * Round 13 lands the §4.2.7.6 Long-Term Prediction parameters
124//! ([`LtpParameters`]) — the primary pitch lag (§4.2.7.6.1; absolute via
125//! Table 29 high part + Table 30 bandwidth-conditioned low part, or
126//! relative via the Table 31 delta with a zero-delta fallback to
127//! absolute), the pitch-contour VQ index (Table 32 PDF; Tables 33–36
128//! codebooks) that refines the primary lag into per-subframe pitch lags
129//! clamped to `[lag_min, lag_max]`, the §4.2.7.6.2 periodicity index
130//! (Table 37) and per-subframe 5-tap Q7 LTP filter taps (Table 38 PDFs;
131//! Tables 39–41 codebooks), and the §4.2.7.6.3 optional Q14 LTP scaling
132//! factor (Table 42 → `{15565, 12288, 8192}`; default `15565` when not
133//! coded). Non-voiced frames consume no LTP bits.
134//!
135//! * Round 14 lands the §4.2.7.7 LCG seed ([`decode_lcg_seed`]) and the
136//! §4.2.7.8 SILK excitation decoder ([`Excitation`] / [`ExcitationConfig`]).
137//! The excitation is decoded in six substeps: §4.2.7.8.1 rate level
138//! (Table 45 PDFs, one symbol per SILK frame), §4.2.7.8.2 per-shell-block
139//! pulse count (Table 46 PDFs at one of 11 rate levels; the "extra LSB"
140//! value 17 chains into rate level 9, then 10), §4.2.7.8.3 recursive
141//! pulse-location partition (16 → 8 → 4 → 2 → 1; Tables 47–50 select
142//! the split PDF by partition size + remaining pulse count),
143//! §4.2.7.8.4 per-coefficient LSB decoding (Table 51), §4.2.7.8.5
144//! sign decoding (Table 52, picked by signal type × quantization
145//! offset type × pulse count bin with 6+ saturating), and §4.2.7.8.6
146//! reconstruction with the LCG `seed' = 196314165*seed + 907633515
147//! mod 2^32` plus the Table 53 Q23 quantization offset. The result is
148//! the final Q23 excitation `e_Q23[]` consumed by the §4.2.7.9 LTP
149//! and LPC synthesis filters.
150//!
151//! * Round 15 lands the §4.2.7.9.2 SILK LPC synthesis filter
152//! ([`lpc_synthesis_subframe`] / [`lpc_synthesis_frame`] /
153//! [`LpcSynthState`]). The short-term predictor combines the §4.2.7.4
154//! Q16 gain, the §4.2.7.9.1 residual `res[i]`, and the §4.2.7.5.8 Q12
155//! stabilised filter `a_Q12[k]` into the unclamped `lpc[i]` and its
156//! clamped output `out[i] = clamp(-1.0, lpc[i], 1.0)`; the per-subframe
157//! `d_LPC` unclamped history is carried across subframes via the
158//! stateful [`LpcSynthState`] (cleared to zero on a decoder reset).
159//!
160//! * Round 16 lands the §4.2.7.9.1 SILK LTP synthesis filter
161//! ([`ltp_synthesis_subframe`] / [`ltp_synth_commit_subframe`] /
162//! [`LtpSynthState`]). Unvoiced subframes produce `res[i] = e_Q23[i] /
163//! 2^23` (a normalised excitation copy). Voiced subframes go through the
164//! §4.2.7.6 5-tap Q7 LTP convolution `res[i] = e_Q23[i]/2^23 + Σ
165//! res[i - pitch_lag + 2 - k] * b_Q7[k]/128`, with the prior-subframe
166//! `out[]` history rewhitened via `4*LTP_scale_Q14/gain_Q16 *
167//! clamp(out[i] - Σ out[i-k-1] * a_Q12[k]/4096, -1, 1)` (region A) and
168//! the prior-subframe unclamped `lpc[]` rewhitened via `65536/gain_Q16 *
169//! (lpc[i] - Σ lpc[i-k-1] * a_Q12[k]/4096)` (region B). `out_end` and
170//! the effective `LTP_scale_Q14` (= 16384 fresh-LPC override) follow the
171//! §4.2.7.9.1 third/fourth-subframe LSF-interpolation-split branch. The
172//! stateful [`LtpSynthState`] carries 306 samples of out[] and 256
173//! samples of lpc[] history (the spec-stated WB worst cases) across
174//! subframes and across SILK frame boundaries, cleared to zero on a
175//! decoder reset per §4.5.2.
176//!
177//! * Round 17 lands the §4.2.8 SILK stereo unmixing
178//! ([`stereo_ms_to_lr`] / [`StereoUnmixState`] / [`StereoWeightsQ13`] /
179//! [`StereoFrame`]) — the `silk_stereo_MS_to_LR` conversion that turns
180//! the decoded mid/side `out[]` signals into left/right. The side
181//! channel is predicted from a low-passed mid term
182//! (`p0 = (mid[i-2] + 2*mid[i-1] + mid[i]) / 4`) and the unfiltered
183//! one-sample-delayed mid (`mid[i-1]`) via the §4.2.7.1 Q13 weights:
184//! `left[i] = clamp(-1, (1+w1)*mid[i-1] + side[i-1] + w0*p0, 1)` and
185//! `right[i] = clamp(-1, (1-w1)*mid[i-1] - side[i-1] - w0*p0, 1)`. The
186//! first `n1` samples (64 NB / 96 MB / 128 WB) interpolate the weights
187//! from the previous frame's `(prev_w0_Q13, prev_w1_Q13)` to the
188//! current frame's; the remainder use the current weights. An uncoded
189//! side channel (§4.2.7.2) is treated as all-zero. The two trailing
190//! mid samples, one trailing side sample, and previous-frame weights
191//! carry across the frame boundary via [`StereoUnmixState`], cleared
192//! to zero on a decoder reset per §4.2.8.
193//!
194//! * Round 19 lands the §4.2.9 SILK resampler delay budget and the
195//! internal-vs-output sample-rate accounting ([`silk_resampler_delay_ms`] /
196//! [`silk_resampler_delay_samples_at`] / [`silk_internal_rate_hz`] /
197//! [`silk_frame_samples_internal`] / [`silk_frame_samples_at_output`] /
198//! [`is_supported_output_rate`] / [`SUPPORTED_OUTPUT_RATES_HZ`]).
199//! The §4.2.9 resampler itself is non-normative ("a decoder can use
200//! any method it wants"); what IS normative is the Table 54 maximum
201//! delay allocation (NB = 0.538 ms, MB = 0.692 ms, WB = 0.706 ms) so
202//! the encoder can apply a matching pre-delay to keep SILK and CELT
203//! aligned across a §4.5 mode switch. This module owns Table 54 plus
204//! the implied SILK internal rates (NB = 8000 Hz, MB = 12000 Hz,
205//! WB = 16000 Hz) and the §4.2.9 supported output rates (8 / 12 / 16 /
206//! 24 / 48 kHz). SWB and FB never reach the §4.2.9 SILK stage and are
207//! rejected with `None`.
208//!
209//! * Round 18 lands the §4.2.3 SILK packet-level header bits and the
210//! §4.2.4 per-frame LBRR flags ([`SilkHeaderBits`] / [`silk_frame_count`]).
211//! For each channel (mono: 1; stereo: 2), the decoder reads N uniform
212//! `dec_bit_logp(1)` VAD bits (N = SILK-frame count from §4.2.2: 1 for
213//! 10/20 ms Opus frames, 2 for 40 ms, 3 for 60 ms) followed by a single
214//! global LBRR flag. For Opus frames longer than 20 ms, each channel
215//! whose global LBRR flag is set then contributes one Table 4 symbol
216//! (`{0, 53, 53, 150}/256` for 40 ms / `{0, 41, 20, 29, 41, 15, 28,
217//! 82}/256` for 60 ms) carrying a per-SILK-frame LBRR bitmap, packed
218//! LSB-to-MSB. For 10/20 ms Opus frames the global LBRR flag itself
219//! implies a single LBRR frame. Output is a [`SilkHeaderBits`]
220//! carrying the per-channel VAD bitmap, global LBRR flag, and the
221//! fully expanded per-channel × per-SILK-frame [`PerFrameLbrr`]
222//! bitmap consumed by the downstream §4.2.5 LBRR / §4.2.6 regular
223//! SILK frame loop.
224//!
225//! * Round 20 lands the first CELT-layer fragment ([`CeltHeaderPrefix`] /
226//! [`CeltPostFilter`]) — the §4.3, Table 56 pre-band header symbols
227//! that every CELT-bearing Opus frame opens with: `silence`
228//! (`{32767, 1}/32768`), the §4.3.7.1 pitch post-filter parameter
229//! group (logp=1 enable bit, then `octave` uniform[0,6), `period =
230//! (16<<octave) + fine_pitch - 1` from `4+octave` raw bits bounded
231//! to `15..=1022`, `gain` 3 raw bits ⇒ `G = 3*(gain_index+1)/32`,
232//! `tapset` `{2,1,1}/4`), the §4.3.1 `transient` (`{7,1}/8`), and
233//! the §4.3.2.1 `intra` (`{7,1}/8`) flag. When `silence` is set,
234//! the rest of the prefix is force-defaulted per the §4.3
235//! shortcut. This is the only Table-56 segment that fits between
236//! the SILK pipeline already wired up and the §4.3.2.1 coarse
237//! energy (#936, blocked on the Laplace decoder + `e_prob_model`
238//! table) / §4.3.3 bit allocation (#943, blocked on `cache_caps50`
239//! + `LOG2_FRAC_TABLE`) sub-pieces.
240//!
241//! * Round 21 lands the §3.1 / §4.2 framing dispatch ([`OpusFrameRouting`]
242//! / [`OperatingMode`] / [`SilkBandwidth`]) — the single
243//! pure-function lookup that turns an [`OpusTocByte`] into the
244//! per-Opus-frame routing decision a §4 decoder needs *before* it
245//! touches the range coder: which layer(s) are present (SILK-only /
246//! Hybrid / CELT-only), the SILK internal bandwidth (pinned to WB
247//! for Hybrid per §4.2 even when the TOC bandwidth is SWB / FB), the
248//! §4.2.2 SILK-frame count per channel (1 for 10/20 ms, 2 for 40 ms,
249//! 3 for 60 ms), the §4.2.4 per-frame LBRR-flag presence gate
250//! (duration > 20 ms), and the channel-count multiplier for stereo.
251//! Codifies the dispatch decision so downstream decoders consume one
252//! `OpusFrameRouting` instead of open-coding the
253//! `(mode, bandwidth, frame_size)` switch each time.
254//!
255//! * Round 23 lands the §4.2.7.4 SILK gain dequantization tail
256//! ([`silk_log2lin`] / [`silk_gains_dequant`] /
257//! [`SubframeGains::dequant_q16`](crate::silk_gains::SubframeGains::dequant_q16))
258//! — the piecewise-linear approximation of `2^(inLog_Q7/128)` and the
259//! composed `log_gain ∈ 0..=63 → gain_Q16 ∈ [81920, 1_686_110_208]`
260//! mapping that the §4.2.7.9.1 LTP and §4.2.7.9.2 LPC synthesis
261//! filters consume. The two §4.2.7.4 endpoints (`log_gain = 0`
262//! ⇒ `81920` = 1.25× linear; `log_gain = 63` ⇒ `1_686_110_208` ≈
263//! 25 728× linear) are pinned to the RFC text. The §4.2.7.5 NLSF
264//! stages had been deferred since round 5; this round closes that gap.
265//!
266//! * Round 24 lands the §4.3 CELT MDCT-band layout
267//! ([`celt_band_layout`]: [`CeltFrameSize`] + Table 55
268//! `bins_per_channel` lookups via [`celt_band_bins_per_channel`] +
269//! [`celt_band_start_hz`] / [`celt_band_stop_hz`] band-edge
270//! accessors + [`celt_band_at_hz`] reverse lookup + the §4.3
271//! "first 17 bands not coded in Hybrid mode" rule baked into
272//! [`celt_first_coded_band`] / [`HYBRID_FIRST_CODED_BAND`] + the
273//! [`celt_total_bins_per_channel`] column-sum helper). The standard
274//! non-Custom CELT layer's [`CELT_NUM_BANDS`] = 21 bands and the
275//! per-band MDCT bin counts at the four CELT frame sizes (2.5 / 5
276//! / 10 / 20 ms) are the lookup every §4.3.2 coarse-energy decoder,
277//! §4.3.3 bit allocator, §4.3.4 PVQ shape decoder, §4.3.6
278//! denormaliser, and §4.3.7 inverse-MDCT pass needs before any
279//! band-loop iteration can start.
280//!
281//! * Round 25 lands the §4.3.4.5 CELT TF-resolution adjustment lookup
282//! ([`celt_tf_adjust`]: Tables 60–63 [`TF_ADJ_NONTRANSIENT_SELECT0`]
283//! / [`TF_ADJ_NONTRANSIENT_SELECT1`] / [`TF_ADJ_TRANSIENT_SELECT0`]
284//! / [`TF_ADJ_TRANSIENT_SELECT1`] +
285//! [`celt_tf_adjustment`](crate::celt_tf_adjust::celt_tf_adjustment)
286//! `(frame_size, transient, tf_select, tf_change) -> i8` entry +
287//! the §4.3.1
288//! [`celt_tf_select_can_affect`](crate::celt_tf_adjust::celt_tf_select_can_affect)
289//! "tf_select is only decoded if it can have an impact on the
290//! result knowing the value of all per-band tf_change flags" gate +
291//! [`TfDirection`] classification (`Unchanged` / `IncreaseTime(N)` /
292//! `IncreaseFrequency(N)`) carrying the §4.3.4.5 Hadamard-transform
293//! level count). The §4.3.4.5 band loop downstream — gated on
294//! §4.3.2.1 coarse energy + §4.3.3 bit allocation, both still
295//! deferred — turns each per-band `tf_change[b]` bit into one of
296//! these adjustments before the §4.3.4.2 PVQ shape decoder runs.
297//!
298//! * Round 26 lands the §4.5.1 CELT redundancy / mode-transition side
299//! information ([`decode_redundancy`] / [`RedundancyDecision`] /
300//! [`RedundancyPosition`]) — the three-step procedure that decides
301//! whether an Opus frame embeds an extra 5 ms redundant CELT frame
302//! for a clean mode transition. §4.5.1.1 implicit signalling for
303//! SILK-only Opus frames (the 17-bit remaining-budget gate),
304//! §4.5.1.1 explicit signalling for Hybrid Opus frames (the 37-bit
305//! gate + Table 64 `{4095, 1}/4096` flag), §4.5.1.2 redundancy
306//! position (Table 65 `{1, 1}/2` uniform symbol: 0 = end-of-frame
307//! / first-frame-in-transition, 1 = start-of-frame / second-frame-
308//! in-transition), and §4.5.1.3 redundancy size (SILK-only =
309//! remaining whole bytes; Hybrid = `2 + dec_uint(256)` with the
310//! "claimed > remaining" branch routed to [`RedundancyDecision::Invalid`]
311//! per the §4.5.1.3 "stop decoding and discard" recommendation).
312//! CELT-only Opus frames bypass the §4.5.1 path entirely. This
313//! round does NOT decode the redundant CELT frame itself — that
314//! requires the §4.3.2.1 / §4.3.3 blockers (#936 / #943) — only
315//! the boundary metadata that tells the caller WHERE the redundant
316//! CELT bytes start and HOW MANY of them there are.
317//!
318//! * Round 28 lands the §4.5.1.4 redundant-CELT-frame decode
319//! parameters and the §4.5.1.4 cross-lap placement
320//! ([`redundant_frame_params`] / [`RedundantFrameParams`] /
321//! [`CrossLapPlacement`] / [`apply_mb_to_wb_override`] /
322//! [`REDUNDANT_FRAME_TENTHS_MS`] / [`REDUNDANT_CROSS_LAP_TENTHS_MS`])
323//! — the pure-function lookup that turns an [`OpusFrameRouting`]
324//! plus a [`RedundancyDecision`] into the four normative
325//! §4.5.1.4 facts a §4.3 CELT decoder needs to actually decode
326//! the redundant frame: "no TOC byte" (just feed the redundant
327//! bytes into the CELT decoder), 5 ms fixed duration
328//! ([`REDUNDANT_FRAME_TENTHS_MS`] = 50 tenths-ms), channel count
329//! inherited from the carrier Opus frame, and audio bandwidth
330//! inherited from the carrier with the §4.5.1.4 "MB SILK frames
331//! → WB" exception ([`apply_mb_to_wb_override`]). Also lands the
332//! §4.5.1.4 cross-lap placement decision
333//! ([`CrossLapPlacement::FirstHalfAsIs`] for [`RedundancyPosition::Beginning`]
334//! — CELT→SILK/Hybrid transitions, where the redundant CELT
335//! frame's first 2.5 ms replace the SILK/Hybrid leading 2.5 ms
336//! and the second 2.5 ms cross-lap; [`CrossLapPlacement::SecondHalfAsIs`]
337//! for [`RedundancyPosition::End`] — SILK/Hybrid→CELT
338//! transitions, where only the redundant frame's second 2.5 ms
339//! is used and that half cross-laps with the SILK/Hybrid
340//! trailing edge). The §4.3.7 power-complementary MDCT window
341//! that actually performs the cross-lap mix is gated on the
342//! undelivered §4.3.2 / §4.3.3 / §4.3.4 chain; this round owns
343//! only the placement metadata (which 2.5 ms region cross-laps,
344//! where in the carrier's sample buffer it sits).
345//!
346//! * Round 29 lands the §4.3.2.1 CELT coarse-energy Laplace-model
347//! parameter surface ([`celt_e_prob_model`]: [`E_PROB_MODEL`] —
348//! the 336-byte `[LM ∈ 0..4][mode ∈ {inter, intra}][band × 2]` Q8
349//! `{prob, decay}` table feeding `ec_laplace_decode` +
350//! [`EnergyPredictionMode::{Inter, Intra}`] selector driven by the
351//! §4.3.2.1 CELT header `intra` flag + [`e_prob_pair`] / [`e_prob_row`]
352//! accessors returning [`EProbPair`] / `&[u8; 42]` + the
353//! [`INTRA_PRED_ALPHA_Q15`] / [`INTRA_PRED_BETA_Q15`] / [`Q15_ONE`]
354//! intra-mode prediction-coefficient constants (`alpha = 0`,
355//! `beta = 4915 / 32768` per RFC 6716 §4.3.2.1 p. 108)). This is the
356//! parameter-surface fragment needed before the §4.3.2.1
357//! Laplace decoder + 2-D `(time, frequency)` predictor can run;
358//! the decoder itself and the per-LM inter-mode `(alpha, beta)`
359//! pair were deferred (the latter landed in round 45 —
360//! [`INTER_PRED_ALPHA_Q15`] / [`INTER_PRED_BETA_Q15`] /
361//! [`energy_pred_coef`] returning [`EnergyPredCoef`], the Q15
362//! numerators fixed by the RFC 6716 Appendix A normative
363//! reference code).
364//!
365//! * Round 30 lands the §4.3.3 *intensity-stereo reservation*
366//! parameter surface ([`celt_log2_frac_table`]:
367//! [`LOG2_FRAC_TABLE`] — the 24-byte Q3 (1/8-bit) conservative
368//! `log2` table feeding the §4.3.3 `intensity_rsv =
369//! LOG2_FRAC_TABLE[end − start]` reservation + [`log2_frac`] typed
370//! accessor + [`log2_frac_row`] full-row borrow + the
371//! [`Q3_BITS_PER_WHOLE_BIT`] = 8 unit-denominator constant). This
372//! is a parameter-surface piece of the §4.3.3 bit-allocation
373//! procedure; the boost / trim / anti-collapse / skip / dual-stereo
374//! reservations, the Table 57 static allocation search, the
375//! `cache_caps50` per-band maximum, and the rest of the §4.3.3
376//! allocation loop are all out of scope for this round.
377//!
378//! * Round 31 lands the §4.3.3 *per-band maximum-allocation* parameter
379//! surface ([`celt_cache_caps50`]: [`CACHE_CAPS50`] — the 168-byte
380//! `[LM ∈ 0..4][stereo ∈ {mono, stereo}][band ∈ 0..21]` Q0
381//! bits/sample table feeding the §4.3.3 per-band bit cap +
382//! [`CacheCapsStereo::{Mono, Stereo}`] selector + [`cache_caps_value`]
383//! / [`cache_caps_row`] accessors + [`init_caps`] /
384//! [`cap_for_band_bits`] convert-to-bits rule
385//! `cap[band] = ((cache_caps50[i] + 64) * channels * N) / 4` per
386//! RFC 6716 §4.3.3 p. 113 + [`INIT_CAPS_BIAS`] / [`INIT_CAPS_DIVISOR`]
387//! / [`INIT_CAPS_MAX_CHANNELS`] convert-rule constants). Closes the
388//! second of the two table dependencies round 24 noted for the
389//! §4.3.3 allocator (round 30 landed [`LOG2_FRAC_TABLE`]; this round
390//! lands [`CACHE_CAPS50`]). The §4.3.3 bit allocation orchestration
391//! that consumes `cap[]` (boost / trim / anti-collapse / skip /
392//! dual-stereo reservations, the Table 57 static allocation search)
393//! is still out of scope.
394//!
395//! * Round 32 lands the §4.3.3 *allocation trim* parameter surface
396//! ([`celt_alloc_trim`]: [`ALLOC_TRIM_PDF`] — the Table-58 PDF
397//! `{2, 2, 5, 10, 22, 46, 22, 10, 5, 2, 2}/128` and its derived
398//! [`ALLOC_TRIM_ICDF`] for [`RangeDecoder::dec_icdf`] consumption +
399//! [`ALLOC_TRIM_DEFAULT`] = 5 / [`ALLOC_TRIM_MIN`] = 0 /
400//! [`ALLOC_TRIM_MAX`] = 10 trim-integer range + the §4.3.3
401//! signalling gate `(ec_tell_frac + 48) ≤ (frame_bytes * 8 −
402//! total_boost)` in [`alloc_trim_is_signalled`] + the
403//! [`decode_alloc_trim`] wrapper that fuses the gate, the
404//! gate-fail-returns-default rule, and the [`RangeDecoder::dec_icdf`]
405//! read into one typed call). The §4.3.3 use of the trim — the
406//! per-band `trim_offsets[]` derivation that shifts the Table 57
407//! static allocation search — is still out of scope and runs at the
408//! call site of [`decode_alloc_trim`].
409//!
410//! * Round 33 lands the §4.3.3 *band-boost* decoder
411//! ([`celt_band_boost`]: [`decode_band_boosts`] driver +
412//! [`band_boost_quanta`] §4.3.3 `min(8*N, max(48, N))` helper +
413//! [`BandBoost`] / [`BandBoostOutcome`] per-band and full-driver
414//! outcomes carrying the §4.3.3 `total_boost` accumulator consumed
415//! by [`decode_alloc_trim`] downstream + [`DYNALLOC_LOGP_INIT`] = 6
416//! / [`DYNALLOC_LOGP_MIN`] = 2 / [`DYNALLOC_LOOP_LOGP_AFTER_FIRST`]
417//! = 1 cost constants + [`BAND_BOOST_QUANTA_FLOOR_EIGHTH_BITS`] = 48
418//! / [`BAND_BOOST_QUANTA_CEIL_MULT`] = 8 quanta-rule constants +
419//! [`BandBoostError`] caller-side bookkeeping bugs). Bridges round
420//! 31's [`crate::celt_cache_caps50::cap_for_band_bits`] per-band
421//! upper bound and round 32's [`decode_alloc_trim`] gate's
422//! `total_boost` input. The §4.3.3 *use* of the per-band boost
423//! values — the §4.3.3 Table 57 static-allocation search +
424//! anti-collapse / skip / dual-stereo reservations — is the
425//! responsibility of the §4.3.3 allocator and runs at the call
426//! site of [`decode_band_boosts`].
427//!
428//! * Round 34 lands the §4.3.3 *reservation block*
429//! ([`celt_reservations`]: [`reserve_block`] /
430//! [`ReservationOutcome`] / [`ReservationError`] +
431//! [`ONE_BIT_EIGHTH_BITS`] = 8 /
432//! [`CONSERVATIVE_DEDUCTION_EIGHTH_BITS`] = 1 /
433//! [`ANTI_COLLAPSE_LM_MIN_EXCLUSIVE`] = 1 /
434//! [`ANTI_COLLAPSE_HEADROOM_MULT_EIGHTH_BITS`] = 8 /
435//! [`ANTI_COLLAPSE_HEADROOM_LM_OFFSET`] = 2 reservation-cost +
436//! gating constants). The §4.3.3 procedure (RFC 6716 §4.3.3, p. 114)
437//! skims four fixed-cost reservations off the top of the working
438//! `total` budget before the Table 57 static-allocation search:
439//! `anti_collapse_rsv` (8 1/8 bits iff transient && LM > 1 &&
440//! total ≥ (LM + 2) * 8), `skip_rsv` (8 1/8 bits iff total > 8 after
441//! anti-collapse), `intensity_rsv = LOG2_FRAC_TABLE[end − start]`
442//! (stereo only; reset to 0 if > total), and `dual_stereo_rsv`
443//! (8 1/8 bits iff total > 8 after intensity). The initial `total`
444//! is `frame_size_bytes * 64 − ec_tell_frac − 1` (the §4.3.3
445//! conservative `-1` deduction). Bridges round 33's `total_boost`
446//! accumulator (validated as `≤ frame_eighth − ec_tell_frac`) and
447//! round 30's [`crate::celt_log2_frac_table::log2_frac`] lookup with
448//! the §4.3.3 Table 57 static-allocation search at the consumer
449//! site. The §4.3.3 *use* of the reservations — the actual
450//! `dec_bit_logp(1)` reads of the anti-collapse / skip /
451//! dual-stereo flags and the `ec_dec_uint(end − start)` read of the
452//! intensity-stereo band — runs at the §4.3.3 allocator's consumer
453//! site once the Table 57 search produces the per-band shape
454//! allocation.
455//!
456//! * Round 35 lands the §4.3.3 *per-band minimum-allocation vector*
457//! ([`celt_band_thresh`]: [`band_min_thresh`] /
458//! [`compute_band_min_thresh`] / [`band_min_thresh_vec`] /
459//! [`standard_band_window`] / [`BandThreshError`] +
460//! [`BAND_THRESH_BINS_MULTIPLIER`] = 24 /
461//! [`BAND_THRESH_BINS_DIVISOR`] = 16 /
462//! [`BAND_THRESH_PER_CHANNEL_EIGHTH_BITS`] = 8 /
463//! [`BAND_THRESH_MONO_CHANNELS`] = 1 /
464//! [`BAND_THRESH_STEREO_CHANNELS`] = 2 formula constants). The
465//! §4.3.3 narrative (RFC 6716 §4.3.3, p. 115) computes a hard
466//! per-band lower bound on the shape allocation: bands whose
467//! allocation would drop below `thresh[band]` are dropped rather
468//! than coded sparsely. For each coded band `b`, with
469//! `N = celt_band_bins_per_channel(b, frame_size)` and
470//! `channels ∈ {1, 2}`, the per-band minimum is
471//! `thresh[b] = max((24 * N) / 16, 8 * channels)` in 1/8 bits — one
472//! whole bit per channel or 48 128th-bits per MDCT bin, whichever is
473//! greater. The §4.3.3 narrative is explicit that the band-size
474//! dependent term `(24 * N) / 16` is *not* scaled by the channel
475//! count (at the very low rates where this floor binds, the
476//! §4.3.3 allocator concentrates the budget on the mid channel).
477//! Bridges round 24's Table 55 band layout with the §4.3.3 Table 57
478//! static-allocation search at the consumer site (where the
479//! per-band minimum competes with the round-31 `cap[]` per-band
480//! maximum, the round-33 boosts, and the upcoming
481//! `trim_offsets[]`).
482//!
483//! * Round 36 lands the §4.3.3 *per-band allocation-trim offsets*
484//! ([`celt_trim_offsets`]: [`band_trim_offset`] /
485//! [`band_trim_offset_for_band`] / [`band_n_shortest`] /
486//! [`shortest_frame_size`] / [`TrimOffsetError`] +
487//! [`TRIM_OFFSETS_BIAS`] = 5 /
488//! [`TRIM_OFFSETS_NUMERATOR_SCALE`] = 8 /
489//! [`TRIM_OFFSETS_DIVISOR`] = 64 /
490//! [`TRIM_OFFSETS_WIDTH_ONE_BINS_PER_CHANNEL`] = 1 /
491//! [`TRIM_OFFSETS_WIDTH_ONE_PER_CHANNEL_EIGHTH_BITS`] = 8 /
492//! [`TRIM_OFFSETS_MONO_CHANNELS`] = 1 /
493//! [`TRIM_OFFSETS_STEREO_CHANNELS`] = 2 formula constants). The
494//! §4.3.3 narrative (RFC 6716 §4.3.3, p. 115) derives a per-band
495//! *trim-offset* vector from the round-32 `alloc_trim` index; the
496//! §4.3.3 Table 57 static-allocation search will add these offsets
497//! to the per-band budget when ranking quality columns. For each
498//! coded band `b`, with `channels ∈ {1, 2}`, `LM ∈ {0, 1, 2, 3}`,
499//! `n_shortest = celt_band_bins_per_channel(b, Ms2_5)`,
500//! `n_per_channel = celt_band_bins_per_channel(b, frame_size)`,
501//! and `remaining_bands` the band-position-dependent factor:
502//! `base = (alloc_trim - 5 - LM) * channels * n_shortest *
503//! remaining_bands * (1 << LM) * 8 / 64`, then
504//! `trim_offsets[b] = base - (8 * channels)` when
505//! `n_per_channel == 1` (width-1 bands receive greater benefit
506//! from the coarse-energy coding; the §4.3.3 narrative backs the
507//! trim off by one whole bit per channel). All arithmetic is
508//! signed; the output is in 1/8 bits. Bridges round 32's
509//! [`decode_alloc_trim`] gate, round 24's Table 55 layout, and
510//! round 35's [`band_min_thresh`] floor with the upcoming §4.3.3
511//! Table 57 static-allocation search.
512//!
513//! * Round 38 lands the §4.5.3 *Summary of Transitions* (Figure 18
514//! plus Figure 19) ([`celt_transitions`]: [`NormativeTransition`]
515//! with one variant per row of Figure 18 +
516//! [`RecommendedNonNormativeTransition`] with one variant per row
517//! of Figure 19 + [`BoundaryOp`] lifting the §4.5.3 figure-key
518//! markers `;` / `|` / `!` / `&` / `+` / `c` / `P` / `>` to a
519//! typed list +
520//! [`classify_normative_transition`](crate::celt_transitions::classify_normative_transition)
521//! `(prev_mode, prev_silk_bw, next_mode, next_silk_bw,
522//! redundancy_present) -> Option<NormativeTransition>` for the
523//! Figure-18 lookup +
524//! [`recommended_non_normative`](crate::celt_transitions::recommended_non_normative)
525//! `(prev_mode, prev_silk_bw, next_mode, next_silk_bw) ->
526//! Option<RecommendedNonNormativeTransition>` for the Figure-19
527//! lookup + the
528//! [`NormativeTransition::seam_operations`](crate::celt_transitions::NormativeTransition::seam_operations)
529//! and
530//! [`RecommendedNonNormativeTransition::seam_operations`](crate::celt_transitions::RecommendedNonNormativeTransition::seam_operations)
531//! accessors returning the ordered marker list at each
532//! transition seam, transcribed from the §4.5.3 figures). Closes
533//! the §4.5 chain after the round-26 §4.5.1 redundancy side
534//! information, the round-28 §4.5.1.4 cross-lap placement, and
535//! the round-27 §4.5.2 state-reset policy. The §4.5.3
536//! classifier's SILK-bandwidth split between Figure-18 rows 2
537//! (NB/MB SILK to Hybrid with R) and row 3 (WB SILK to Hybrid, no
538//! R), the symmetric Hybrid to SILK split (rows 5 and 6), and the
539//! §4.5 "audio-bandwidth change is the glitch source" reading
540//! that rules out same-bandwidth SILK to SILK from row 1 are all
541//! baked in.
542//!
543//! * Round 39 lands the §4.3.3 *static allocation table*
544//! ([`celt_static_alloc`]:
545//! [`STATIC_ALLOC`](crate::celt_static_alloc::STATIC_ALLOC) —
546//! the 21×11 Q5 grid `alloc[band][q]` in 1/32-bit per MDCT bin
547//! units transcribed from RFC 6716 §4.3.3 Table 57 (p. 112) +
548//! [`STATIC_ALLOC_Q_COUNT`](crate::celt_static_alloc::STATIC_ALLOC_Q_COUNT)
549//! = 11 / [`STATIC_ALLOC_Q_MIN`](crate::celt_static_alloc::STATIC_ALLOC_Q_MIN)
550//! = 0 / [`STATIC_ALLOC_Q_MAX`](crate::celt_static_alloc::STATIC_ALLOC_Q_MAX)
551//! = 10 / [`STATIC_ALLOC_TOTAL_CELLS`](crate::celt_static_alloc::STATIC_ALLOC_TOTAL_CELLS)
552//! = 231 / [`STATIC_ALLOC_RIGHT_SHIFT`](crate::celt_static_alloc::STATIC_ALLOC_RIGHT_SHIFT)
553//! = 2 / [`STATIC_ALLOC_INTERP_STEPS`](crate::celt_static_alloc::STATIC_ALLOC_INTERP_STEPS)
554//! = 64 layout / conversion constants +
555//! [`static_alloc_cell`](crate::celt_static_alloc::static_alloc_cell)
556//! `(band, q) -> u8` raw-cell lookup +
557//! [`static_alloc_row`](crate::celt_static_alloc::static_alloc_row)
558//! `(band) -> &[u8; 11]` row borrow for the §4.3.3 search's
559//! per-band quality inner loop +
560//! [`static_alloc_eighth_bits`](crate::celt_static_alloc::static_alloc_eighth_bits)
561//! `(band, q, channels, n_bins, lm) -> u32` applying the §4.3.3
562//! `channels * N * alloc[band][q] << LM >> 2` unit conversion
563//! from Q5 to Q3 (1/8-bit) per-band units +
564//! [`StaticAllocError`](crate::celt_static_alloc::StaticAllocError)).
565//! Pins the §4.3.3 invariants the allocator relies on: column 0
566//! is uniformly zero (the no-allocation floor), each row is
567//! monotone non-decreasing in `q`, and the saturation column
568//! (col 10) is `200` for bands 0..=7 and declines to `104` at
569//! band 20. Bridges the round-31 cap surface, the round-33
570//! boosts, the round-34 reservations, the round-35 minimum
571//! threshold, and the round-36 trim offsets with the §4.3.3
572//! 1/64-step interpolated search the next round will land.
573//!
574//! * Round 40 lands the §4.3.3 *1/64-step interpolated static-allocation
575//! search* ([`celt_alloc_search`]:
576//! [`Q_FP_MAX`](crate::celt_alloc_search::Q_FP_MAX) = 640
577//! fixed-point-quality bound +
578//! [`STATIC_ALLOC_INTERP_RIGHT_SHIFT`](crate::celt_alloc_search::STATIC_ALLOC_INTERP_RIGHT_SHIFT)
579//! = 8 combined shift constant +
580//! [`QFpComponents`](crate::celt_alloc_search::QFpComponents)
581//! `(q_lo, frac)` decomposition +
582//! [`q_fp_to_components`](crate::celt_alloc_search::q_fp_to_components)
583//! `/ q_fp_from_components` invertible accessors +
584//! [`per_band_eighth_bits_at_q_fp`](crate::celt_alloc_search::per_band_eighth_bits_at_q_fp)
585//! `(band, q_fp, channels, n_bins, lm) -> u64` per-band Q3 lookup
586//! under the §4.3.3 1/64-step linear interpolation
587//! `cell_q11 = alloc[b][q_lo] * (64 - frac) + alloc[b][q_lo + 1] *
588//! frac` followed by the `(channels * N * cell_q11) << LM >> 8`
589//! unit conversion that folds the round-39 `>> 2` (Q5 → Q3) with
590//! the 1/64-step `>> 6` (Q11 → Q5) in one step +
591//! [`total_eighth_bits_at_q_fp`](crate::celt_alloc_search::total_eighth_bits_at_q_fp)
592//! `(q_fp, channels, frame_size, is_hybrid) -> u64` summing across
593//! coded bands respecting the §4.3 first-coded-band rule (`0` for
594//! CELT-only / `17` for Hybrid) +
595//! [`search_q_fp`](crate::celt_alloc_search::search_q_fp)
596//! `(budget, channels, frame_size, is_hybrid) -> AllocSearchOutcome`
597//! the §4.3.3 "highest allocation that does not exceed the number
598//! of bits remaining" linear scan returning
599//! [`AllocSearchOutcome`](crate::celt_alloc_search::AllocSearchOutcome)
600//! `{ q_fp, total_eighth_bits }` +
601//! [`AllocSearchError`](crate::celt_alloc_search::AllocSearchError)).
602//! Closes the §4.3.3 1/64-step interpolation gap round 39 noted as
603//! the next step. The orchestrated §4.3.3 allocator that consumes
604//! the search output (folding in the round-33 boosts, the round-35
605//! per-band minimum threshold, the round-31 per-band cap, and the
606//! round-36 trim offsets, then running the skip / dual-stereo /
607//! intensity-stereo flag reads) runs at the consumer site once the
608//! round-34 reservation block + this round's search are composed.
609//!
610//! * Round 41 lands the §4.3.4.2 *PVQ codebook-size function*
611//! ([`celt_pvq_v`]: [`pvq_codebook_size`]`(n, k) -> Result<u32,
612//! PvqVError>` evaluating the RFC 6716 §4.3.4.2 bivariate
613//! recurrence `V(N, K) = V(N - 1, K) + V(N, K - 1) + V(N - 1,
614//! K - 1)` with base cases `V(N, 0) = 1` / `V(0, K) = 0 (K != 0)`
615//! over two rolling rows + [`PVQ_V_N_MAX`] = 352 / [`PVQ_V_K_MAX`]
616//! = 4096 caller-side bookkeeping bounds + [`PVQ_V_MAX`] =
617//! `2**32 − 1` overflow guard inherited from RFC 6716 §4.1.5's
618//! `ec_dec_uint(ft)` upper bound + [`PvqVError::{NOutOfRange,
619//! KOutOfRange, OverflowsDecUintRange}`] error reporting). The
620//! §4.3.4.2 PVQ index decode (`ec_dec_uint(V(N, K))` followed by
621//! the §4.3.4.2 conversion of the index to a sign-magnitude
622//! lattice point) and the §4.3.4.1 *Bits-to-Pulses* search both
623//! consume this primitive; both run at the consumer site.
624//!
625//! The rest of the CELT layer is not yet wired up; the [`Decoder`]
626//! / [`Encoder`] entry points still return [`Error::NotImplemented`].
627
628#![warn(missing_debug_implementations)]
629
630use oxideav_core::RuntimeContext;
631
632/// Crate-local error type.
633#[derive(Debug, Clone, Copy, PartialEq, Eq)]
634pub enum Error {
635 /// The caller passed a zero-length packet. RFC 6716 §3.1 requires
636 /// every well-formed Opus packet to contain at least one byte (R1).
637 EmptyPacket,
638 /// The packet violates one of the §3.2 frame-packing
639 /// requirements (R2..R7). Examples: a code-1 packet with an odd
640 /// payload length; a code-2 packet whose declared first-frame
641 /// length runs off the end of the buffer; a code-3 packet with
642 /// `M = 0` or whose CBR per-frame size is not an integer divisor
643 /// of the remaining payload.
644 MalformedPacket,
645 /// The clean-room rebuild has not yet wired up a working
646 /// SILK / CELT pipeline; the higher-level decode / encode paths
647 /// return this until that work lands.
648 NotImplemented,
649}
650
651impl core::fmt::Display for Error {
652 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
653 match self {
654 Error::EmptyPacket => write!(
655 f,
656 "oxideav-opus: packet is empty; RFC 6716 §3.1 R1 requires at least one byte"
657 ),
658 Error::MalformedPacket => write!(
659 f,
660 "oxideav-opus: packet violates an RFC 6716 §3.2 frame-packing requirement"
661 ),
662 Error::NotImplemented => write!(
663 f,
664 "oxideav-opus: orphan-rebuild scaffold — SILK/CELT pipeline not wired up yet"
665 ),
666 }
667 }
668}
669
670impl std::error::Error for Error {}
671
672pub mod celt_alloc_search;
673pub mod celt_alloc_trim;
674pub mod celt_band_boost;
675pub mod celt_band_layout;
676pub mod celt_band_thresh;
677pub mod celt_cache_caps50;
678pub mod celt_deemphasis;
679pub mod celt_e_prob_model;
680pub mod celt_fine_energy;
681pub mod celt_header;
682pub mod celt_log2_frac_table;
683pub mod celt_mdct_window;
684pub mod celt_post_filter;
685pub mod celt_pvq_decode;
686pub mod celt_pvq_v;
687pub mod celt_redundancy;
688pub mod celt_reservations;
689pub mod celt_spreading;
690pub mod celt_static_alloc;
691pub mod celt_tf_adjust;
692pub mod celt_transitions;
693pub mod celt_trim_offsets;
694pub mod frames;
695pub mod framing;
696pub mod framing_self_delim;
697pub mod mode_transition_reset;
698pub mod range_decoder;
699pub mod redundancy_decode_params;
700pub mod silk_excitation;
701pub mod silk_frame;
702pub mod silk_gains;
703pub mod silk_header;
704pub mod silk_lcg_seed;
705pub mod silk_log2lin;
706pub mod silk_lpc_synth;
707pub mod silk_lsf_interp;
708pub mod silk_lsf_recon;
709pub mod silk_lsf_stabilize;
710pub mod silk_lsf_stage2;
711pub mod silk_lsf_to_lpc;
712pub mod silk_ltp;
713pub mod silk_ltp_synth;
714pub mod silk_resampler;
715pub mod silk_stereo;
716pub mod toc;
717
718pub use celt_alloc_search::{
719 per_band_eighth_bits_at_q_fp, q_fp_from_components, q_fp_to_components, search_q_fp,
720 total_eighth_bits_at_q_fp, AllocSearchError, AllocSearchOutcome, QFpComponents, Q_FP_MAX,
721 STATIC_ALLOC_INTERP_RIGHT_SHIFT,
722};
723pub use celt_alloc_trim::{
724 alloc_trim_icdf, alloc_trim_is_signalled, alloc_trim_pdf, decode_alloc_trim, frame_eighth_bits,
725 AllocTrimError, ALLOC_TRIM_DEFAULT, ALLOC_TRIM_FTB, ALLOC_TRIM_ICDF, ALLOC_TRIM_MAX,
726 ALLOC_TRIM_MIN, ALLOC_TRIM_PDF, ALLOC_TRIM_PDF_DENOMINATOR, ALLOC_TRIM_PDF_LEN,
727 ALLOC_TRIM_SIGNAL_COST_EIGHTH_BITS, EIGHTH_BITS_PER_BYTE,
728};
729pub use celt_band_boost::{
730 band_boost_quanta, decode_band_boosts, BandBoost, BandBoostError, BandBoostOutcome,
731 BAND_BOOST_QUANTA_CEIL_MULT, BAND_BOOST_QUANTA_FLOOR_EIGHTH_BITS, DYNALLOC_LOGP_INIT,
732 DYNALLOC_LOGP_MIN, DYNALLOC_LOOP_LOGP_AFTER_FIRST,
733};
734pub use celt_band_layout::{
735 celt_band_at_hz, celt_band_bins_per_channel, celt_band_start_hz, celt_band_stop_hz,
736 celt_end_coded_band, celt_first_coded_band, celt_total_bins_per_channel, CeltFrameSize,
737 CELT_MAX_BINS_PER_BAND, CELT_NUM_BANDS, HYBRID_FIRST_CODED_BAND,
738};
739pub use celt_band_thresh::{
740 band_min_thresh, band_min_thresh_vec, compute_band_min_thresh, standard_band_window,
741 BandThreshError, BAND_THRESH_BINS_DIVISOR, BAND_THRESH_BINS_MULTIPLIER,
742 BAND_THRESH_MONO_CHANNELS, BAND_THRESH_PER_CHANNEL_EIGHTH_BITS, BAND_THRESH_STEREO_CHANNELS,
743};
744pub use celt_cache_caps50::{
745 cache_caps_offset, cache_caps_row, cache_caps_value, cap_for_band_bits, init_caps,
746 CacheCaps50Error, CacheCapsStereo, CACHE_CAPS50, CACHE_CAPS50_LM_COUNT,
747 CACHE_CAPS50_STEREO_COUNT, CACHE_CAPS50_STEREO_MONO, CACHE_CAPS50_STEREO_STEREO,
748 CACHE_CAPS50_TOTAL_BYTES, INIT_CAPS_BIAS, INIT_CAPS_DIVISOR, INIT_CAPS_MAX_CHANNELS,
749};
750pub use celt_deemphasis::{DeemphasisError, DeemphasisFilter, DEEMPHASIS_ALPHA_P};
751pub use celt_e_prob_model::{
752 e_prob_pair, e_prob_row, energy_pred_coef, EProbModelError, EProbPair, EnergyPredCoef,
753 EnergyPredictionMode, E_PROB_MODEL, E_PROB_MODEL_BYTES_PER_BAND, E_PROB_MODEL_BYTES_PER_ROW,
754 E_PROB_MODEL_LM_COUNT, E_PROB_MODEL_MODE_COUNT, E_PROB_MODEL_MODE_INTER,
755 E_PROB_MODEL_MODE_INTRA, E_PROB_MODEL_TOTAL_BYTES, INTER_PRED_ALPHA_Q15, INTER_PRED_BETA_Q15,
756 INTRA_PRED_ALPHA_Q15, INTRA_PRED_BETA_Q15, Q15_ONE,
757};
758pub use celt_header::{CeltHeaderPrefix, CeltPostFilter};
759pub use celt_log2_frac_table::{
760 log2_frac, log2_frac_row, Log2FracError, LOG2_FRAC_TABLE, LOG2_FRAC_TABLE_LEN,
761 Q3_BITS_PER_WHOLE_BIT,
762};
763pub use celt_mdct_window::{
764 basic_window, celt_overlap_window, mdct_window, window_tap, MdctWindowError, BASIC_WINDOW_LEN,
765 CELT_OVERLAP_48K,
766};
767pub use celt_pvq_decode::{
768 decode_pvq_shape, decode_pvq_shape_into, decode_pvq_vector, decode_pvq_vector_into,
769 pvq_l1_norm, pvq_l2_norm_squared, pvq_unit_normalize, PvqDecodeError, PvqShapeError,
770 PVQ_DECODE_K_MAX, PVQ_DECODE_N_MAX,
771};
772pub use celt_pvq_v::{pvq_codebook_size, PvqVError, PVQ_V_K_MAX, PVQ_V_MAX, PVQ_V_N_MAX};
773pub use celt_redundancy::{
774 decode_redundancy, remaining_bits, whole_bytes_remaining, RedundancyDecision,
775 RedundancyPosition, HYBRID_REDUNDANCY_MIN_REMAINING_BITS,
776 HYBRID_REDUNDANCY_SIZE_BASELINE_BYTES, HYBRID_REDUNDANCY_SIZE_DEC_UINT_FT,
777 REDUNDANCY_FLAG_ICDF, REDUNDANCY_FLAG_ICDF_FTB, REDUNDANCY_MIN_SIZE_BYTES,
778 REDUNDANCY_POSITION_ICDF, REDUNDANCY_POSITION_ICDF_FTB,
779 SILK_ONLY_REDUNDANCY_MIN_REMAINING_BITS,
780};
781pub use celt_reservations::{
782 reserve_block, ReservationError, ReservationOutcome, ANTI_COLLAPSE_HEADROOM_LM_OFFSET,
783 ANTI_COLLAPSE_HEADROOM_MULT_EIGHTH_BITS, ANTI_COLLAPSE_LM_MIN_EXCLUSIVE,
784 CONSERVATIVE_DEDUCTION_EIGHTH_BITS, ONE_BIT_EIGHTH_BITS,
785};
786pub use celt_spreading::{
787 apply_spreading, decode_spread, rotate_in_place, rotate_strided, rotation_angle, rotation_gain,
788 spread_f_r, spread_theta, spreading_stride, SpreadingError, SPREAD_FTB, SPREAD_F_R,
789 SPREAD_ICDF, SPREAD_MAX, SPREAD_PDF, SPREAD_PDF_DENOMINATOR, SPREAD_PRE_ROTATION_MIN_BLOCK_LEN,
790 SPREAD_VALUE_COUNT,
791};
792pub use celt_static_alloc::{
793 static_alloc_cell, static_alloc_eighth_bits, static_alloc_row, StaticAllocError, STATIC_ALLOC,
794 STATIC_ALLOC_INTERP_STEPS, STATIC_ALLOC_Q_COUNT, STATIC_ALLOC_Q_MAX, STATIC_ALLOC_Q_MIN,
795 STATIC_ALLOC_RIGHT_SHIFT, STATIC_ALLOC_TOTAL_CELLS,
796};
797pub use celt_tf_adjust::{
798 celt_tf_adjustment, celt_tf_select_can_affect, TfAdjustment, TfDirection,
799 TF_ADJUSTMENT_ABS_MAX, TF_ADJUSTMENT_MAX, TF_ADJ_NONTRANSIENT_SELECT0,
800 TF_ADJ_NONTRANSIENT_SELECT1, TF_ADJ_TRANSIENT_SELECT0, TF_ADJ_TRANSIENT_SELECT1,
801};
802pub use celt_transitions::{
803 classify_normative_transition, recommended_non_normative, BoundaryOp, NormativeTransition,
804 RecommendedNonNormativeTransition,
805};
806pub use celt_trim_offsets::{
807 band_n_shortest, band_trim_offset, band_trim_offset_for_band, shortest_frame_size,
808 TrimOffsetError, TRIM_OFFSETS_BIAS, TRIM_OFFSETS_DIVISOR, TRIM_OFFSETS_MONO_CHANNELS,
809 TRIM_OFFSETS_NUMERATOR_SCALE, TRIM_OFFSETS_STEREO_CHANNELS,
810 TRIM_OFFSETS_WIDTH_ONE_BINS_PER_CHANNEL, TRIM_OFFSETS_WIDTH_ONE_PER_CHANNEL_EIGHTH_BITS,
811};
812pub use frames::{OpusPacket, MAX_FRAMES_PER_PACKET, MAX_FRAME_BYTES};
813pub use framing::{OperatingMode, OpusFrameRouting, SilkBandwidth};
814pub use framing_self_delim::{parse_self_delimited, SelfDelimitedParse};
815pub use mode_transition_reset::{decide_state_resets, CeltResetPlacement, StateReset};
816pub use range_decoder::RangeDecoder;
817pub use redundancy_decode_params::{
818 apply_mb_to_wb_override, redundant_frame_params, CrossLapPlacement, RedundantFrameParams,
819 REDUNDANT_CROSS_LAP_TENTHS_MS, REDUNDANT_FRAME_TENTHS_MS,
820};
821pub use silk_excitation::{
822 quantization_offset_q23, shell_block_count, Excitation, ExcitationConfig, SilkFrameSize,
823 MAX_EXCITATION_SAMPLES, MAX_SHELL_BLOCKS, SHELL_BLOCK_SAMPLES,
824};
825pub use silk_frame::{
826 FrameKind, QuantizationOffsetType, SignalType, SilkFrameHeader, SilkFrameHeaderConfig,
827 StereoPredictionWeights,
828};
829pub use silk_gains::{SubframeGain, SubframeGains, SubframeGainsConfig, SILK_MAX_SUBFRAMES};
830pub use silk_header::{
831 per_frame_lbrr_pdf, silk_frame_count, PerFrameLbrr, SilkChannelHeader, SilkHeaderBits,
832 SILK_MAX_FRAMES_PER_CHANNEL,
833};
834pub use silk_lcg_seed::decode_lcg_seed;
835pub use silk_log2lin::{
836 silk_gains_dequant, silk_log2lin, SILK_GAIN_Q16_MAX, SILK_GAIN_Q16_MIN, SILK_LOG_GAIN_BIAS,
837 SILK_LOG_GAIN_MULTIPLIER,
838};
839pub use silk_lpc_synth::{
840 lpc_synthesis_frame, lpc_synthesis_subframe, subframe_samples, LpcSynthState,
841 LPC_SYNTH_MAX_ORDER, LPC_SYNTH_MAX_SUBFRAME_SAMPLES,
842};
843pub use silk_lsf_interp::{LsfInterpContext, LsfInterpolated};
844pub use silk_lsf_recon::{cb1_q8, NlsfReconstructed};
845pub use silk_lsf_stabilize::NlsfStabilized;
846pub use silk_lsf_stage2::{
847 LsfStage2, D_LPC_MAX, D_LPC_NB_MB, D_LPC_WB, QSTEP_NB_MB_Q16, QSTEP_WB_Q16,
848};
849pub use silk_lsf_to_lpc::{nlsf_to_c_q17, ordering, LpcQ12, LpcQ17};
850pub use silk_ltp::{
851 LagCoding, LtpConfig, LtpParameters, LTP_FILTER_TAPS, LTP_MAX_SUBFRAMES,
852 LTP_SCALING_DEFAULT_Q14,
853};
854pub use silk_ltp_synth::{
855 ltp_synth_commit_subframe, ltp_synthesis_subframe, LtpSynthState, LtpSynthSubframe,
856 LTP_LPC_HISTORY_MAX, LTP_MAX_PITCH_LAG, LTP_OUT_HISTORY_MAX, LTP_SCALE_FRESH_Q14,
857};
858pub use silk_resampler::{
859 is_supported_output_rate, silk_frame_samples_at_output, silk_frame_samples_internal,
860 silk_internal_rate_hz, silk_resampler_delay_ms, silk_resampler_delay_samples_at,
861 REFERENCE_RATE_HZ, SILK_RESAMPLER_DELAY_MS_MB, SILK_RESAMPLER_DELAY_MS_NB,
862 SILK_RESAMPLER_DELAY_MS_WB, SUPPORTED_OUTPUT_RATES_HZ,
863};
864pub use silk_stereo::{
865 interp_phase_samples, stereo_ms_to_lr, StereoFrame, StereoUnmixState, StereoWeightsQ13,
866};
867pub use toc::{Bandwidth, ChannelMapping, FrameCountCode, Mode, OpusTocByte};
868
869/// No-op codec registration — the orphan-rebuild scaffold registers
870/// nothing into the runtime context until decode / encode paths are
871/// wired up.
872pub fn register(_ctx: &mut RuntimeContext) {}
873
874oxideav_core::register!("opus", register);