Skip to content

Releases: OxideAV/oxideav-opus

v0.0.12

15 Jun 05:01
d071a8d

Choose a tag to compare

Other

  • §4.3.7.1 pitch post-filter response (celt_post_filter)
  • §4.3.4.2 PVQ shape read path (index read + unit-L2 normalization)
  • fix clippy assertions-on-constants in celt_deemphasis test
  • §4.3.7.2 de-emphasis filter (round 48)
  • §4.3.7 inverse-MDCT overlap window (round 47)
  • §4.1.2 public two-step range-coder symbol API (ec_decode + ec_dec_update)
  • §4.3.2.1 per-LM inter-mode (alpha, beta) prediction coefficients (round 45)
  • §4.3.4.3 spreading rotation (round 44)
  • §4.3.4.2 PVQ index-to-vector decode (round 43)
  • clean-room round 42 — §4.3.2.2 fine-energy quantization
  • §4.3.4.2 PVQ codebook-size function V(N, K) (round 41)
  • §4.3.3 1/64-step interpolated allocation search (round 40)
  • §4.3.3 static allocation table (Table 57) (round 39)
  • §4.5.3 normative + recommended-non-normative transition table (round 38)
  • drop release-plz.toml — use release-plz defaults across the workspace
  • RFC 6716 Appendix B self-delimiting framing (round 37)
  • §4.3.3 per-band allocation-trim offsets (round 36)
  • §4.3.3 per-band minimum-allocation vector (round 35)
  • §4.3.3 reservation block (round 34)
  • §4.3.3 band-boost decoder (round 33)
  • §4.3.3 allocation-trim Table-58 PDF + signalling gate (round 32)
  • §4.3.3 CACHE_CAPS50 per-band maximum-allocation parameter surface (round 31)
  • §4.3.3 LOG2_FRAC_TABLE intensity-stereo reservation parameter surface (round 30)
  • §4.3.2.1 CELT coarse-energy Laplace-model parameter surface (round 29)
  • §4.5.1.4 redundant-CELT-frame decode parameters + cross-lap placement (round 28)
  • §4.5.2 SILK + CELT state-reset policy across mode transitions (round 27)
  • §4.5.1 CELT redundancy / mode-transition side information (round 26)

Added

  • Clean-room round 50 (2026-06-15): §4.3.7.1 pitch post-filter
    response
    (celt_post_filter). The pitch comb filter the CELT decoder
    applies to the inverse-MDCT / overlap-add output (§4.3.7) just before
    the round-48 §4.3.7.2 de-emphasis; the post-filter parameters landed
    in celt_header at round 20, this round owns their application. RFC
    6716 §4.3.7.1 (p. 121) states the five-tap symmetric comb response
    y(n) = x(n) + G*(g0*y(n-T) + g1*(y(n-T+1)+y(n-T-1)) + g2*(y(n-T+2)+y(n-T-2))) — recursive over past output samples (state
    = the trailing T + 2 outputs, carried across frames, reset only on a
    §4.5.2 CELT state reset). The ASCII equation prints each pair term with
    a repeated index; the symmetric y(n-T±1) / y(n-T±2) reading is the
    only one consistent with the "g0, g1, g2" symmetric-tap-set prose, and
    the module documents the slip. New surface: POST_FILTER_TAPS (the
    three §4.3.7.1 (g0, g1, g2) tapsets) + tapset_coefficients +
    post_filter_gain (G = 3*(gain_index+1)/32) + the formula constants;
    PostFilterCoeffs { period, a0, a1, a2 } (gain folded into each tap)
    via new / from_header; PostFilter carrying the output history
    (new / reset / step / process_in_place / process /
    process_gain_transition — the §4.3.7.1 squared-MDCT-window gain
    crossfade pushing the mixed value into the shared feedback history per
    "interpolated one at a time"); the standalone crossfade_transition;
    and PostFilterError::{TapsetOutOfRange, PeriodOutOfRange, GainIndexOutOfRange, OutputBufferTooSmall, TransitionLengthMismatch, Window} with From<MdctWindowError>. Twenty-six new unit tests (1064
    lib tests, up from 1038; 20 integration unchanged): the tapset decimals

    • g2 = 0 for tapsets 1/2, the gain formula + monotonicity, the
      gain-fold, period bounds, header round-trip, fresh-history
      pass-through, a hand-expanded impulse response placing each tap at its
      exact lag, impulse-response symmetry about T, history carry across
      split blocks, the buffer paths, reset, the gain-transition endpoints
    • old==new identity + length checks, the standalone crossfade
      convexity, and every error Display. Provenance: §4.3.7.1 comb
      response, tapsets, gain map, and squared-window transition rule in the
      staged docs/audio/opus/rfc6716-opus.txt; the squared window reuses
      the round-47 celt_mdct_window; no external library source consulted.
  • Clean-room round 49 (2026-06-15): §4.3.4.2 PVQ shape read path
    (celt_pvq_decode). Composes the three steps RFC 6716 §4.3.4.2
    (p. 116–117) states in sequence: the up-front
    i = ec_dec_uint(V(N, K)) codeword-index read
    (RangeDecoder::dec_uint), the round-43 five-step index-to-vector
    walk, and the final normalization — "The decoded vector X is then
    normalized such that its L2-norm equals one." New surface:
    pvq_unit_normalize(&[i32], &mut [f64]) (the unit-L2 scaling, with
    the K = 0 no-direction case left all-zeros); decode_pvq_shape(rd, n, k) -> Vec<f64> and decode_pvq_shape_into(rd, n, k, &mut [f64])
    (the full read path returning the unit-norm f64 shape the §4.3.4.3
    spreading rotation operates on and §4.3.6 denormalization later
    scales by the band energy); and PvqShapeError::{CodebookSize, RangeDecoder, PulseVector, OutputBufferTooSmall} with From<PvqVError>
    / From<PvqDecodeError>. Fourteen new unit tests (1038 lib tests, up
    from 1024; 20 integration unchanged): the unit-L2 norm over every
    codeword of (N, K) ∈ 1..=6 × 1..=6, direction preservation,
    single-pulse ±1, the zero-vector carve-out, the buffer paths;
    decode_pvq_shapedecode_pvq_vector + pvq_unit_normalize
    consistency from fixed buffers, the _into parity, the K = 0
    no-bit-consumption edge, N = 1 signed-unit, codebook-size error
    propagation, and the error conversions/Display.

  • Clean-room round 48 (2026-06-14): §4.3.7.2 de-emphasis filter
    (celt_deemphasis). The final stage of the CELT decode pipeline,
    applied after the inverse MDCT + overlap-add (§4.3.7) and the
    §4.3.7.1 pitch post-filter. RFC 6716 §4.3.7.2 (p. 122) states it as
    the inverse of the encoder's pre-emphasis filter,
    1/A(z) = 1/(1 - alpha_p*z^-1) with alpha_p = 0.8500061035;
    inverting the one-pole transfer function gives the time-domain
    recurrence y(n) = x(n) + alpha_p*y(n-1). The single state element
    carries across frame boundaries (the recurrence is continuous over
    the whole stream, reset only on a §4.5.2 CELT state reset). New
    surface: DEEMPHASIS_ALPHA_P = 0.8500061035 constant;
    DeemphasisFilter with new() / with_memory(mem) / memory() /
    reset() / step(x) (one-sample recurrence) /
    process_in_place(&mut [f64]) / process(input, output); and
    DeemphasisError::OutputBufferTooSmall. Fifteen new unit tests
    (1024 lib tests, up from 1009; 20 integration unchanged): the
    alpha_p constant + stability bound, fresh-filter zero memory,
    first-sample pass-through, hand-computed recurrence, constant-input
    convergence to the DC gain 1/(1 - alpha_p), the
    pre-emphasis-round-trip inverse property, memory carry across split
    blocks, with_memory seeding, reset, the process_in_place
    step parity, output-buffer write + over-long acceptance +
    short-buffer rejection (state unchanged on error), empty-input
    no-op, and the error Display. Provenance: §4.3.7.2 transfer
    function + alpha_p constant in the staged
    docs/audio/opus/rfc6716-opus.txt; the recurrence is the textbook
    inverse of the stated one-pole filter; no reference source
    consulted.

  • Clean-room round 47 (2026-06-14): §4.3.7 inverse-MDCT overlap
    window (celt_mdct_window). RFC 6716 §4.3.7 (p. 121) states the
    basic full-overlap 240-sample Vorbis-derived window directly:
    W(n) = sin( (pi/2) * sin( (pi/2) * (n + 1/2) / L )^2 ) (the 2
    superscript squares the inner sine — the only nesting that
    satisfies the §4.3.7 power-complementarity / Princen-Bradley
    requirement W(n)^2 + W(L-1-n)^2 = 1, which the module proves
    algebraically and pins in tests). New surface: window_tap(n, len)
    (the amplitude tap for window length L = len), basic_window()
    (the 240-tap full-overlap window), mdct_window(overlap) (the
    §4.3.7 "low-overlap" ramp for an arbitrary even overlap, built by
    evaluating the same shape with L = overlap — the "zero-pad +
    insert ones in the middle" construction expressed as a per-overlap
    rising ramp), celt_overlap_window() (the fixed CELT 120-sample
    overlap at 48 kHz — the 2.5 ms look-ahead "fixed by the decoder",
    RFC 6716 §1), constants BASIC_WINDOW_LEN = 240 /
    CELT_OVERLAP_48K = 120, and MdctWindowError::{PositionOutOfRange, ZeroLength, OddOverlap}. Eighteen new unit tests (1009 lib tests,
    up from 991; 20 integration unchanged): the formula spot-check,
    unit-interval bound, monotone-increasing ramp, power complementarity
    on both the basic window and arbitrary overlaps, the half-power
    centre pair, endpoint shape, mdct_windowwindow_tap parity,
    the celt_overlap_windowmdct_window(120) parity, and every
    error path. The inverse MDCT itself and the weighted overlap-add
    that consumes this ramp run at the §4.3.7 consumer site.
    Provenance: §4.3.7 window equation + low-overlap narrative + §1
    fixed-overlap statement, all in the staged
    docs/audio/opus/rfc6716-opus.txt; no reference source consulted.

  • Clean-room round 46 (2026-06-13): public two-step range-coder
    symbol API RangeDecoder::ec_decode(ft) -> fs and
    RangeDecoder::ec_dec_update(fl, fh, ft) per RFC 6716 §4.1.2,
    promoting the previously-private decode / dec_update helpers to a
    validated public surface. ec_decode computes the §4.1.2 symbol
    proxy fs = ft - min(val/(rng/ft) + 1, ft) and rejects ft == 0
    (division by zero) by latching the sticky error flag; ec_dec_update
    narrows the range to the chosen symbol's [fl, fh) sub-interval of
    [0, ft) and rejects malformed tuples (ft == 0, fh > ft,
    fl >= fh) with the same error-latch-and-no-op guard, so a corrupt
    search result cannot underflow val or zero rng. This is the
    generic symbol path required when the frequency model is computed at
    run time rather than baked into a...

Read more

v0.0.11

30 May 02:33
8031a87

Choose a tag to compare

Other

  • §4.3.4.5 CELT TF-resolution adjustment lookup (round 25)

Added

  • Clean-room round 25 (2026-05-30): §4.3.4.5 CELT TF-resolution
    adjustment lookup — a new celt_tf_adjust module owning RFC 6716
    Tables 60–63 (the four (frame_size, choice) -> i8 adjustment
    tables keyed by (transient, tf_select)). Exposes
    celt_tf_adjustment(frame_size, transient, tf_select, tf_change) -> i8 (the routed lookup, return value ∈ [-3, 3]),
    celt_tf_select_can_affect(frame_size, transient, &[bool]) -> bool
    (the §4.3.1 "tf_select is only decoded if it can have an impact on
    the result knowing the value of all per-band tf_change flags"
    redundancy gate that the §4.3.4.5 band loop calls AFTER decoding
    every per-band tf_change[b]), TfDirection::{Unchanged, IncreaseTime(N), IncreaseFrequency(N)} carrying the §4.3.4.5
    Hadamard-transform branch and level count, TfAdjustment (= i8)
    storage type, and named constants TF_ADJUSTMENT_MAX = 3,
    TF_ADJUSTMENT_ABS_MAX = 3, plus the four tables themselves
    (TF_ADJ_NONTRANSIENT_SELECT0, TF_ADJ_NONTRANSIENT_SELECT1,
    TF_ADJ_TRANSIENT_SELECT0, TF_ADJ_TRANSIENT_SELECT1) for direct
    inspection.

    This is the lookup the §4.3.4.5 band loop downstream consumes once
    it's wired up (gated on §4.3.2.1 coarse energy and §4.3.3 bit
    allocation, both still deferred); it sits between Table 55's
    per-band MDCT-bin count and the §4.3.4.2 PVQ shape decoder.

    Twenty-seven new module tests (428 lib tests total, up from 401 at
    round-24 close; 20 integration tests unchanged, grand total 448).
    Coverage: every table's 4 × 2 shape; every cell ∈ [-3, 3]; all
    32 cells across Tables 60 / 61 / 62 / 63 hand-pinned to RFC 6716
    §4.3.4.5; the "non-transient choice = 0 is always 0" invariant;
    the "non-transient choice = 1 is always ≤ 0" invariant; the
    "positive adjustments only on transient frames" §4.3.4.5
    asymmetry pinned at both the table and TfDirection layer; the
    Table 62 choice = 0 monotone 0, 1, 2, 3 scale across frame
    sizes; the universal 2.5 ms [0, -1] row across all four tables;
    TF_ADJUSTMENT_MAX and TF_ADJUSTMENT_ABS_MAX matching the
    observed max over every cell; celt_tf_adjustment entry-point
    routing each (transient, tf_select) corner; celt_tf_select_can_affect
    returning false on empty band sets and on the redundant 2.5 ms
    rows; returning false on 10 ms non-transient with all-choice 0
    bands and true as soon as any band picks choice = 1;
    returning true on 20 ms transient for any non-empty band set;
    TfDirection::from_adjustment classification + levels() value
    matching adj.unsigned_abs() over [-3, 3];
    IncreaseFrequency never reachable on non-transient frames;
    IncreaseTime always reached for non-transient choice = 1.

v0.0.10

29 May 08:16
0cfc789

Choose a tag to compare

Other

  • §4.3 Table 55 CELT MDCT-band layout (round 24)
  • §4.2.7.4 SILK gain dequant tail (silk_log2lin) — round 23
  • §3.4 R1..R7 malformed-input rejection audit (round 22)
  • §3.1 / §4.2 framing dispatch (round 21)
  • land §4.3 Table 56 CELT pre-band header symbols
  • Round 19: §4.2.9 SILK resampler delay budget + sample-rate accounting
  • round 18: §4.2.3 SILK header bits + §4.2.4 per-frame LBRR flags
  • §4.2.8 stereo unmixing — silk_stereo_MS_to_LR (round 17)
  • fix the round-16 test count phrasing
  • §4.2.7.9.1 LTP synthesis filter (round 16)
  • round 15 — RFC 6716 §4.2.7.9.2 LPC synthesis filter
  • §4.2.7.7 LCG seed + §4.2.7.8 excitation reconstruction
  • §4.2.7.6 LTP parameters (pitch lags + LTP filter + LTP scaling)
  • §4.2.7.5.8 LPC prediction-gain stability limiting
  • §4.2.7.5.7 LPC range-limiting bandwidth expansion
  • round 10: RFC 6716 §4.2.7.5.6 SILK NLSF→LPC core conversion
  • clean-room round 9 — SILK §4.2.7.5.5 NLSF interpolation
  • round 8: RFC 6716 §4.2.7.5.4 SILK NLSF stabilization
  • round 7: RFC 6716 §4.2.7.5.3 SILK NLSF reconstruction
  • round 6: RFC 6716 §4.2.7.5.2 SILK LSF Stage-2
  • round 5 fix: compare iCDF slices by value, not pointer identity
  • round 5: RFC 6716 §4.2.7.4 SILK subframe gains
  • round 4: RFC 6716 §4.2.7.1–§4.2.7.5.1 SILK frame header
  • round 3: RFC 6716 §4.1 range decoder
  • round 2: RFC 6716 §3.2 frame-packing parser
  • round 1: RFC 6716 §3.1 packet TOC byte parser
  • orphan rebuild: clean-room scaffold post 2026-05-20 audit

Added

  • Clean-room round 24 (2026-05-29): §4.3 CELT MDCT-band layout —
    a new celt_band_layout module owning RFC 6716 Table 55 (the
    21-band partition with per-band MDCT bin counts at 2.5 / 5 / 10 /
    20 ms and the 0..=20000 Hz band-edge frequencies) and the §4.3
    "first 17 bands (up to 8 kHz) are not coded in Hybrid mode" rule.
    Exposes CeltFrameSize (the four CELT frame-size variants whose
    repr(u8) discriminants double as Table 55 column index 0..=3,
    plus from_frame_tenths_ms / to_frame_tenths_ms),
    celt_band_bins_per_channel(band, fs) -> Option<u16>,
    celt_band_start_hz(b) / celt_band_stop_hz(b) band edges,
    celt_band_at_hz(hz) -> Option<usize> reverse lookup,
    celt_first_coded_band(is_hybrid) / celt_end_coded_band()
    iterator bounds, celt_total_bins_per_channel(fs, is_hybrid)
    column-sum helper, and named constants CELT_NUM_BANDS = 21,
    HYBRID_FIRST_CODED_BAND = 17, CELT_MAX_BINS_PER_BAND = 176.
    The "Custom" mode of §6.2 is explicitly out of scope.

    This is the layout the deferred §4.3.2 coarse-energy decoder,
    §4.3.3 bit allocator, §4.3.4 PVQ shape decoder, §4.3.6
    denormalisation, and §4.3.7 inverse MDCT all need before any band
    loop can iterate.

    Twenty new module tests (401 lib tests total, up from 381 at
    round-23 close; 20 integration tests unchanged) cover: full-band
    start / stop pin (band 0 starts at 0 Hz, band 20 stops at 20 kHz);
    adjacent bands tile without gaps (stop(b) == start(b + 1) for
    every b ∈ 0..=19); positive band widths everywhere; the
    power-of-two column-scaling invariant (column(c) == 1 << c * column(0) per band); every cell ∈ [1, 176] per the §4.3 prose;
    hand-pinned Table 55 cells at bands 0 / 8 / 12 / 15 / 17 / 20;
    band-edge spot pins at start, the §4.3 Hybrid boundary
    (stop(16) = 8000 = start(17)), and tail (stop(20) = 20000);
    out-of-range band index returns None;
    CeltFrameSize::from_frame_tenths_ms round-trip with explicit
    SILK-only rejection (400 / 600 ms); discriminant-vs-column-index
    agreement; the Hybrid-vs-CELT-only first-coded-band split with the
    8 kHz boundary pin; celt_total_bins_per_channel column-sum
    agreement against an independent iterator sum for each mode; strict
    hybrid_total < celt_only_total invariant; pinned CELT-only column
    sums (100 / 200 / 400 / 800) and Hybrid column sums (60 / 120 /
    240 / 480); celt_band_at_hz round-trip against the band-edge
    triple (start, midpoint, stop - 1 all land on the same band);
    >= 20 kHz rejection of celt_band_at_hz;
    celt_band_at_hz(8000) == 17 lining up with
    HYBRID_FIRST_CODED_BAND; multiple-of-200-Hz band-width
    invariant with three pinned widths (200 Hz for band 0, 400 Hz for
    band 8, 4400 Hz for band 20); CELT_MAX_BINS_PER_BAND == max(every cell).

  • Clean-room round 23 (2026-05-29): §4.2.7.4 SILK gain
    dequantization tail — a new silk_log2lin module exposing
    silk_log2lin (the spec's piecewise-linear approximation of
    2^(inLog_Q7/128)) and silk_gains_dequant (the composed
    log_gain ∈ 0..=63 → gain_Q16 pipeline
    silk_log2lin((0x1D1C71*log_gain >> 16) + 2090)), plus the named
    constants SILK_LOG_GAIN_MULTIPLIER, SILK_LOG_GAIN_BIAS,
    SILK_GAIN_Q16_MIN = 81_920, SILK_GAIN_Q16_MAX = 1_686_110_208.
    Also adds a SubframeGains::dequant_q16 convenience that maps an
    entire decoded frame's log_gain[] into the fixed-size [u32; SILK_MAX_SUBFRAMES] array consumed by the §4.2.7.9.1 LTP and
    §4.2.7.9.2 LPC synthesis filters (with trailing unused slots left
    at zero for two-subframe frames).

    This closes the §4.2.7.4 tail-end conversion that was previously
    noted as deferred since round 5; the §4.2.7.9 synthesis filters
    already accept a gain_q16 input but were missing the official
    RFC-spec mapping from the decoded log_gain integer to the linear
    Q16 gain.

    Nineteen new module tests (381 lib tests total, up from 362 at
    round-22 close, plus the 20 integration tests unchanged) cover:

    • The §4.2.7.4 documented endpoints — log_gain = 0 returns
      81920 (= 1.25 in linear scale) and log_gain = 63 returns
      1_686_110_208 (≈ 25 728 in linear).
    • Strict monotonicity: silk_gains_dequant(g+1) > silk_gains_dequant(g)
      for every g ∈ 0..=62.
    • Spec-range invariant across the full 0..=63 sweep.
    • Pure-power-of-two collapse: silk_log2lin(128*i) == 1<<i for
      i ∈ 0..=30.
    • silk_log2lin(0) == 1 and silk_log2lin(1) == 1 (the
      approximation can't resolve sub-128 Q7 below i = 7).
    • Pinned silk_log2lin(7*128 | 64) = 181 — exact match of the
      §4.2.7.4 approximation against the true 2^7.5 ≈ 181.019…
      halfway between 2^7 and 2^8, exercising both the bowed
      correction and the linear term.
    • Independent i64 oracle of the §4.2.7.4 formula matched bit-for-bit
      by the production i32 implementation across (a) every reachable
      inLog_Q7 from the log_gain dequant pipeline and (b) the full
      i ∈ 0..=30 × f ∈ 0..=127 Q7 domain.
    • Endpoint algebra pinned independently of silk_gains_dequant:
      log_gain = 0 → in_log_q7 = 2090; log_gain = 63 → in_log_q7 = 3923 (= 30*128 + 83), silk_log2lin(2090) = 81_920,
      silk_log2lin(3923) = 1_686_110_208.
    • SubframeGains::dequant_q16 leaves trailing slots at zero for a
      two-subframe frame and matches per-subframe silk_gains_dequant
      calls across the four-subframe frame.
  • Clean-room round 22 (2026-05-27): §3.4 R1..R7 malformed-input
    rejection audit — a dedicated integration-level test file
    (tests/malformed_input.rs, 20 tests) that pins every concrete
    failure mode RFC 6716 §3.4 enumerates for a malformed packet, plus
    property-style sweeps proving the §4.2.3 / §4.2.4 SILK header
    decoder is panic-free on any truncation of a previously-valid
    bitstream (§4.1.4 zero-extension contract). Covers R1 (empty
    packet), R2 (frame > 1275 B for codes 0 and 1, plus the §3.2.1
    boundary at 1275 B), R3 (code-1 odd body length), R4 (code-2
    length-byte truncations + length > remaining + DTX boundary), R5
    (M = 0 + M > 48 rejection), R6 (CBR R % M != 0), R7 (VBR
    declared length overrun), §3.2.5 padding-chain pathologies, TOC
    total-function self-consistency, §4.2.3 / §4.2.4 truncation
    panic-freeness across (num_silk_frames, stereo) × prefix-length
    1..=32, §4.2.4 LBRR-bitmap-never-zero invariant for 40 / 60 ms,
    mono channel never emits side state, parsed-frame slice
    lifetimes, and a code × body-len short-packet panic sweep. Test
    totals: 362 lib + 20 integration = 382 (was 362 lib + 0
    integration after round 21).

  • Clean-room round 21 (2026-05-27): §3.1 / §4.2 framing dispatch —
    a new framing module exposing OpusFrameRouting, OperatingMode,
    and SilkBandwidth. OpusFrameRouting::from_toc turns the parsed
    OpusTocByte into the per-Opus-frame dispatch decision a §4 decoder
    needs before it touches the range coder:

    • operating_mode — SilkOnly / Hybrid / CeltOnly from §3.1 Table 2.
    • silk_layer / celt_layer — which layers are present.
    • silk_bandwidth — internal SILK bandwidth (NB / MB / WB), pinned
      to WB for every Hybrid frame regardless of the TOC's SWB / FB per
      RFC 6716 §4.2 first paragraph ("the LP layer itself still only runs
      in WB").
    • silk_frames_per_channel — §4.2.2 LP-layer organisation (1 for
      10 / 20 ms Opus frames, 2 for 40 ms, 3 for 60 ms; None for
      CELT-only).
    • total_silk_frames — channel-count × per-channel SILK frames.
    • has_per_frame_lbrr_bits — §4.2.4 duration gate (true for SILK-
      bearing frames longer than 20 ms).

    Thirteen new unit tests cover the SILK-only Table 2 row-by-row
    expectations (12 cells), the Hybrid WB-pin, the CELT-only frames
    sweep across mono/stereo, the §4.2.4 per-frame LBRR gate against
    every Table 2 cell, the total_silk_frames formula across all 32
    configs × {mono, stereo}, a 60 ms stereo SILK-only worked example,
    the c-bit independence of the routing, the channel-mapping
    pass-through, and the silk_layer ⇔ silk_bandwidth.is_some() ⇔ silk_frames_per_channel.is_some() invariants across the entire
    Table 2 grid.

  • Clean-room round 20 (2026-05-26): first CELT-layer fragment —
    the RFC 6716 §4.3 / Table 56 pre-band header symbols behind a new
    celt_header module (CeltHeaderPrefix / CeltPostFilter).

    • silencedec_icdf against the 2-entry {32767, 1}/32768
      iCDF [1, 0] at ftb=15. When the flag fires t...
Read more