Refactor opusenc for strict Clippy checks

This commit is contained in:
Dylan M. Taylor
2026-10-28 06:09:21 +00:00
parent 072f2619bd
commit 7c27d88030
9 changed files with 113 additions and 137 deletions
+18 -24
View File
@@ -8,7 +8,8 @@
use crate::range::{BITRES, RangeEncoder, ilog};
use crate::rate::{Mode, QTHETA_OFFSET, get_pulses};
use crate::tables::*;
use crate::tables::EBANDS;
use crate::{CeltFrame, rate::Allocation};
pub const SPREAD_NORMAL: usize = 2;
@@ -55,7 +56,7 @@ fn exp_rotation1_inv(x: &mut [f32], len: usize, stride: usize, c: f32, s: f32) {
if len <= stride {
return;
}
if len >= 2 * stride + 1 {
if len > 2 * stride {
for i in 0..=len - 2 * stride - 1 {
let x1 = x[i];
let x2 = x[i + stride];
@@ -217,7 +218,7 @@ impl BandEnc<'_, '_> {
let q = qn as u32;
let half = q >> 1;
let ft = (half + 1) * (half + 1);
let (fl, fs) = if it <= half { (it * (it + 1) >> 1, it + 1) } else { (ft - ((q + 1 - it) * (q + 2 - it) >> 1), q + 1 - it) };
let (fl, fs) = if it <= half { ((it * (it + 1)) >> 1, it + 1) } else { (ft - (((q + 1 - it) * (q + 2 - it)) >> 1), q + 1 - it) };
self.enc.encode(fl, fl + fs, ft);
itheta = ((it * 16384) / q) as i32;
}
@@ -294,26 +295,19 @@ impl BandEnc<'_, '_> {
}
}
/// Codes all band shapes (`quant_all_bands`, encoder side, long blocks). `x` holds `c` channels
/// of `n` normalised MDCT coefficients each.
#[allow(clippy::too_many_arguments)]
pub fn quant_all_bands(
m: &Mode,
start: usize,
end: usize,
x: &[f32],
n_total: usize,
c: usize,
pulses: &[i32; NB_EBANDS],
spread: usize,
dual_stereo: bool,
intensity: usize,
total_bits: i32,
mut balance: i32,
enc: &mut RangeEncoder,
lm: usize,
coded_bands: usize,
) {
/// Shape-coding controls, independent of the selected band allocation.
pub struct BandCoding {
pub spread: usize,
pub total_bits: i32,
}
/// Codes all band shapes (`quant_all_bands`, encoder side, long blocks). `x` holds
/// `frame.channels` channels of `n_total` normalised MDCT coefficients each.
pub fn quant_all_bands(m: &Mode, frame: CeltFrame, x: &[f32], n_total: usize, allocation: &Allocation, coding: BandCoding, enc: &mut RangeEncoder) {
let CeltFrame { start, end, channels: c, lm } = frame;
let Allocation { pulses, dual_stereo, intensity, coded_bands, balance, .. } = allocation;
let (dual_stereo, intensity, coded_bands, mut balance) = (*dual_stereo, *intensity, *coded_bands, *balance);
let BandCoding { spread, total_bits } = coding;
let mm = 1usize << lm;
debug_assert!(c == 1 || dual_stereo || intensity <= start, "stereo frames are coded as dual stereo");
let mut ctx = BandEnc { m, enc, i: 0, spread, remaining_bits: 0, pvq_v: Vec::new(), iy: Vec::new(), tmp: Vec::new() };
@@ -362,7 +356,7 @@ mod tests {
x[i + stride] = c * x2 + s * x1;
x[i] = c * x1 + ms * x2;
}
if len >= 2 * stride + 1 {
if len > 2 * stride {
for i in (0..=len - 2 * stride - 1).rev() {
let x1 = x[i];
let x2 = x[i + stride];
+11 -29
View File
@@ -4,9 +4,10 @@
//! The quantised energies are updated with exactly the decoder's arithmetic so the prediction
//! state never drifts between encoder and decoder.
use crate::CeltFrame;
use crate::range::RangeEncoder;
use crate::rate::MAX_FINE_BITS;
use crate::tables::*;
use crate::rate::{Allocation, MAX_FINE_BITS};
use crate::tables::{BETA_COEF, BETA_INTRA, E_PROB_MODEL, NB_EBANDS, PRED_COEF, SMALL_ENERGY_ICDF};
const LAPLACE_MINP: u32 = 1;
const LAPLACE_NMIN: u32 = 16;
@@ -56,18 +57,8 @@ pub fn laplace_encode(enc: &mut RangeEncoder, value: i32, mut fs: u32, decay: u3
/// `quant_coarse_energy` for one prediction mode. `e` holds the target log2 energies (relative
/// to `E_MEANS`), `old_e` the quantised energies, updated in place. `budget` is the frame size in
/// bits.
#[allow(clippy::too_many_arguments)]
pub fn quant_coarse_energy(
start: usize,
end: usize,
e: &[f32; 2 * NB_EBANDS],
old_e: &mut [f32; 2 * NB_EBANDS],
intra: bool,
enc: &mut RangeEncoder,
c: usize,
lm: usize,
budget: i32,
) {
pub fn quant_coarse_energy(frame: CeltFrame, e: &[f32; 2 * NB_EBANDS], old_e: &mut [f32; 2 * NB_EBANDS], intra: bool, enc: &mut RangeEncoder, budget: i32) {
let CeltFrame { start, end, channels: c, lm } = frame;
let prob = &E_PROB_MODEL[lm][intra as usize];
let (coef, beta) = if intra { (0.0, BETA_INTRA) } else { (PRED_COEF[lm], BETA_COEF[lm]) };
let mut prev = [0f32; 2];
@@ -111,15 +102,8 @@ pub fn quant_coarse_energy(
}
/// `quant_fine_energy`: raw bits refining each band's quantised energy.
pub fn quant_fine_energy(
start: usize,
end: usize,
e: &[f32; 2 * NB_EBANDS],
old_e: &mut [f32; 2 * NB_EBANDS],
fine_quant: &[i32; NB_EBANDS],
enc: &mut RangeEncoder,
c: usize,
) {
pub fn quant_fine_energy(frame: CeltFrame, e: &[f32; 2 * NB_EBANDS], old_e: &mut [f32; 2 * NB_EBANDS], fine_quant: &[i32; NB_EBANDS], enc: &mut RangeEncoder) {
let CeltFrame { start, end, channels: c, .. } = frame;
for i in start..end {
let fq = fine_quant[i];
if fq <= 0 {
@@ -139,18 +123,16 @@ pub fn quant_fine_energy(
/// `quant_energy_finalise`: spends the bits left at the end of the frame on one more bit of
/// energy resolution per band, in priority order.
#[allow(clippy::too_many_arguments)]
pub fn quant_energy_finalise(
start: usize,
end: usize,
frame: CeltFrame,
e: &[f32; 2 * NB_EBANDS],
old_e: &mut [f32; 2 * NB_EBANDS],
fine_quant: &[i32; NB_EBANDS],
fine_priority: &[i32; NB_EBANDS],
allocation: &Allocation,
mut bits_left: i32,
enc: &mut RangeEncoder,
c: usize,
) {
let CeltFrame { start, end, channels: c, .. } = frame;
let Allocation { fine_quant, fine_priority, .. } = allocation;
for prio in 0..2 {
let mut i = start;
while i < end && bits_left >= c as i32 {
+25 -33
View File
@@ -24,8 +24,6 @@
//! ```
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
// The bit-allocation code mirrors the normative integer arithmetic; keep C-like shift expressions.
#![allow(clippy::precedence, clippy::int_plus_one)]
mod bands;
mod energy;
@@ -38,14 +36,23 @@ mod tables;
use std::sync::OnceLock;
use bands::{SPREAD_NORMAL, quant_all_bands};
use bands::{BandCoding, SPREAD_NORMAL, quant_all_bands};
use energy::{quant_coarse_energy, quant_energy_finalise, quant_fine_energy};
use mdct::Mdct;
use range::{BITRES, RangeEncoder};
use rate::{Mode as CeltMode, compute_allocation};
use rate::{AllocationInput, Mode as CeltMode, compute_allocation};
use resample::Downsampler;
use silk::SilkEncoder;
use tables::*;
use tables::{E_MEANS, EBANDS, NB_EBANDS, OVERLAP, PREEMPH, SPREAD_ICDF, TF_SELECT_TABLE, TRIM_ICDF};
/// Band range, channel count and transform size shared by CELT coding stages.
#[derive(Clone, Copy)]
struct CeltFrame {
start: usize,
end: usize,
channels: usize,
lm: usize,
}
/// Samples per channel in one 20 ms frame at 48 kHz.
const N: usize = 960;
@@ -314,7 +321,7 @@ impl OpusEncoder {
Mode::Celt => {
let (log_e, silence) = self.celt_analysis(pcm);
let len = self.frame_bytes;
packet.extend_from_slice(&self.encode_celt(RangeEncoder::new(), len, 0, NB_EBANDS, &log_e, silence));
packet.extend_from_slice(&self.encode_celt(RangeEncoder::new(), len, 0..NB_EBANDS, &log_e, silence));
}
Mode::Silk => {
let x = self.silk_input(pcm);
@@ -344,7 +351,7 @@ impl OpusEncoder {
}
let (log_e, _) = self.celt_analysis(pcm);
let end = if self.bandwidth == Bandwidth::SuperWideband { 19 } else { NB_EBANDS };
packet.extend_from_slice(&self.encode_celt(enc, len, HYBRID_START_BAND, end, &log_e, false));
packet.extend_from_slice(&self.encode_celt(enc, len, HYBRID_START_BAND..end, &log_e, false));
}
}
packet
@@ -406,10 +413,11 @@ impl OpusEncoder {
/// Codes one CELT frame (RFC 6716 §4.3, in bitstream order) of `len` bytes into `enc`
/// (which already holds the SILK frame in hybrid mode), coding bands `start..end`, and
/// finalises the frame.
#[allow(clippy::too_many_arguments)]
fn encode_celt(&mut self, mut enc: RangeEncoder, len: usize, start: usize, end: usize, log_e: &[f32; 2 * NB_EBANDS], silence: bool) -> Vec<u8> {
fn encode_celt(&mut self, mut enc: RangeEncoder, len: usize, bands: std::ops::Range<usize>, log_e: &[f32; 2 * NB_EBANDS], silence: bool) -> Vec<u8> {
let m = celt_mode();
let c = self.channels;
let frame = CeltFrame { start: bands.start, end: bands.end, channels: c, lm: LM };
let CeltFrame { start, end, .. } = frame;
if c == 1 {
for i in 0..NB_EBANDS {
self.old_band_e[i] = self.old_band_e[i].max(self.old_band_e[NB_EBANDS + i]);
@@ -438,10 +446,10 @@ impl OpusEncoder {
let mut enc_intra = enc.clone();
let mut old_intra = self.old_band_e;
enc_intra.bit_logp(true, 3);
quant_coarse_energy(start, end, log_e, &mut old_intra, true, &mut enc_intra, c, LM, total_bits_raw);
quant_coarse_energy(frame, log_e, &mut old_intra, true, &mut enc_intra, total_bits_raw);
enc.bit_logp(false, 3);
let mut old_inter = self.old_band_e;
quant_coarse_energy(start, end, log_e, &mut old_inter, false, &mut enc, c, LM, total_bits_raw);
quant_coarse_energy(frame, log_e, &mut old_inter, false, &mut enc, total_bits_raw);
if enc_intra.tell_frac() < enc.tell_frac() {
enc = enc_intra;
self.old_band_e = old_intra;
@@ -449,14 +457,14 @@ impl OpusEncoder {
self.old_band_e = old_inter;
}
} else {
quant_coarse_energy(start, end, log_e, &mut self.old_band_e, false, &mut enc, c, LM, total_bits_raw);
quant_coarse_energy(frame, log_e, &mut self.old_band_e, false, &mut enc, total_bits_raw);
}
// TF resolution: no changes.
{
let mut budget = total_bits_raw;
let mut tell = enc.tell();
let mut logp = 4;
let tf_select_rsv = LM > 0 && tell + logp + 1 <= budget;
let tf_select_rsv = LM > 0 && tell + logp < budget;
budget -= tf_select_rsv as i32;
for _ in start..end {
if tell + logp <= budget {
@@ -488,27 +496,11 @@ impl OpusEncoder {
enc.icdf(alloc_trim as usize, &TRIM_ICDF, 7);
}
let bits = (total_bits_raw << BITRES) - enc.tell_frac() - 1;
let alloc = compute_allocation(m, start, end, &offsets, &cap, alloc_trim, bits, c, LM, &mut enc);
quant_fine_energy(start, end, log_e, &mut self.old_band_e, &alloc.fine_quant, &mut enc, c);
quant_all_bands(
m,
start,
end,
&self.freq,
N,
c,
&alloc.pulses,
SPREAD_NORMAL,
alloc.dual_stereo,
alloc.intensity,
total_bits_raw << BITRES,
alloc.balance,
&mut enc,
LM,
alloc.coded_bands,
);
let alloc = compute_allocation(m, frame, AllocationInput { offsets: &offsets, cap: &cap, trim: alloc_trim, bits }, &mut enc);
quant_fine_energy(frame, log_e, &mut self.old_band_e, &alloc.fine_quant, &mut enc);
quant_all_bands(m, frame, &self.freq, N, &alloc, BandCoding { spread: SPREAD_NORMAL, total_bits: total_bits_raw << BITRES }, &mut enc);
let bits_left = total_bits_raw - enc.tell();
quant_energy_finalise(start, end, log_e, &mut self.old_band_e, &alloc.fine_quant, &alloc.fine_priority, bits_left, &mut enc, c);
quant_energy_finalise(frame, log_e, &mut self.old_band_e, &alloc, bits_left, &mut enc);
debug_assert!(enc.tell() <= total_bits_raw, "frame overflow: {} > {}", enc.tell(), total_bits_raw);
if c == 1 {
let (a, b) = self.old_band_e.split_at_mut(NB_EBANDS);
+44 -45
View File
@@ -4,8 +4,9 @@
//! spec-derived `filmcraft-opus` decoder (first-party, MIT OR Apache-2.0) step by step; the only
//! difference is that the encoder *writes* the band-skip, intensity and dual-stereo symbols.
use crate::CeltFrame;
use crate::range::{BITRES, RangeEncoder, ilog};
use crate::tables::*;
use crate::tables::{ALLOC, EBANDS, LOG2_FRAC_TABLE, MAX_LM, NB_EBANDS};
const MAX_PSEUDO: i32 = 40;
const LOG_MAX_PSEUDO: i32 = 6;
@@ -127,7 +128,7 @@ impl Mode {
let mut cap = [0i32; NB_EBANDS];
for (i, cp) in cap.iter_mut().enumerate() {
let n = (EBANDS[i + 1] - EBANDS[i]) << lm;
*cp = (self.caps[NB_EBANDS * (2 * lm + c - 1) + i] as i32 + 64) * c as i32 * n >> 2;
*cp = ((self.caps[NB_EBANDS * (2 * lm + c - 1) + i] as i32 + 64) * c as i32 * n) >> 2;
}
cap
}
@@ -200,7 +201,7 @@ fn compute_caps(m: &Mode) -> Vec<u8> {
let mut n0 = EBANDS[j + 1] - EBANDS[j];
let max_bits = if n0 << i == 1 {
c * (1 + MAX_FINE_BITS) << BITRES
(c * (1 + MAX_FINE_BITS)) << BITRES
} else {
let mut lm0 = 0;
if n0 > 2 {
@@ -240,7 +241,7 @@ fn compute_caps(m: &Mode) -> Vec<u8> {
let num = mb + ndof * offset;
let den = (ndof - 1) << BITRES;
let qb = ((num + (den >> 1)) / den).min(MAX_FINE_BITS);
mb += c * qb << BITRES;
mb += (c * qb) << BITRES;
mb
};
let w = c * ((EBANDS[j + 1] - EBANDS[j]) << i);
@@ -263,21 +264,19 @@ pub struct Allocation {
pub fine_priority: [i32; NB_EBANDS],
}
/// Per-band limits, boosts and available budget for the allocation search.
pub struct AllocationInput<'a> {
pub offsets: &'a [i32; NB_EBANDS],
pub cap: &'a [i32; NB_EBANDS],
pub trim: i32,
pub bits: i32,
}
/// `clt_compute_allocation`, encoder side. Stereo frames are always coded as dual (L/R) stereo
/// with no intensity bands, and no band is skipped voluntarily.
#[allow(clippy::too_many_arguments)]
pub fn compute_allocation(
m: &Mode,
start: usize,
end: usize,
offsets: &[i32; NB_EBANDS],
cap: &[i32; NB_EBANDS],
alloc_trim: i32,
total: i32,
c: usize,
lm: usize,
enc: &mut RangeEncoder,
) -> Allocation {
pub fn compute_allocation(m: &Mode, frame: CeltFrame, input: AllocationInput<'_>, enc: &mut RangeEncoder) -> Allocation {
let CeltFrame { start, end, channels: c, lm } = frame;
let AllocationInput { offsets, cap, trim: alloc_trim, bits: total } = input;
let ci = c as i32;
let lmi = lm as i32;
let mut total = total.max(0);
@@ -302,8 +301,8 @@ pub fn compute_allocation(
let mut trim_offset = [0i32; NB_EBANDS];
for j in start..end {
let w = EBANDS[j + 1] - EBANDS[j];
thresh[j] = (ci << BITRES).max((3 * w << lmi << BITRES) >> 4);
trim_offset[j] = ci * w * (alloc_trim - 5 - lmi) * (end as i32 - j as i32 - 1) * (1 << (lmi + BITRES as i32)) >> 6;
thresh[j] = (ci << BITRES).max(((3 * w) << lmi << BITRES) >> 4);
trim_offset[j] = (ci * w * (alloc_trim - 5 - lmi) * (end as i32 - j as i32 - 1) * (1 << (lmi + BITRES as i32))) >> 6;
if w << lmi == 1 {
trim_offset[j] -= ci << BITRES;
}
@@ -317,7 +316,7 @@ pub fn compute_allocation(
let mid = (lo + hi) >> 1;
for j in (start..end).rev() {
let n = EBANDS[j + 1] - EBANDS[j];
let mut bitsj = ci * n * (ALLOC[mid as usize][j] as i32) << lmi >> 2;
let mut bitsj = (ci * n * (ALLOC[mid as usize][j] as i32)) << lmi >> 2;
if bitsj > 0 {
bitsj = (bitsj + trim_offset[j]).max(0);
}
@@ -342,8 +341,8 @@ pub fn compute_allocation(
lo -= 1;
for j in start..end {
let n = EBANDS[j + 1] - EBANDS[j];
let mut bits1j = ci * n * (ALLOC[lo as usize][j] as i32) << lmi >> 2;
let mut bits2j = if hi >= nb_alloc { cap[j] } else { ci * n * (ALLOC[hi as usize][j] as i32) << lmi >> 2 };
let mut bits1j = (ci * n * (ALLOC[lo as usize][j] as i32)) << lmi >> 2;
let mut bits2j = if hi >= nb_alloc { cap[j] } else { (ci * n * (ALLOC[hi as usize][j] as i32)) << lmi >> 2 };
if bits1j > 0 {
bits1j = (bits1j + trim_offset[j]).max(0);
}
@@ -361,27 +360,27 @@ pub fn compute_allocation(
bits1[j] = bits1j;
bits2[j] = bits2j;
}
interp_bits2pulses(m, start, end, skip_start, &bits1, &bits2, &thresh, cap, total, skip_rsv, intensity_rsv, dual_stereo_rsv, c, lm, enc)
let interpolation =
AllocationInterpolation { skip_start, bits1: &bits1, bits2: &bits2, thresh: &thresh, cap, total, skip_rsv, intensity_rsv, dual_stereo_rsv };
interp_bits2pulses(m, frame, interpolation, enc)
}
#[allow(clippy::too_many_arguments)]
fn interp_bits2pulses(
m: &Mode,
start: usize,
end: usize,
/// Bracketing allocation vectors and signalling reserves for the interpolation stage.
struct AllocationInterpolation<'a> {
skip_start: usize,
bits1: &[i32; NB_EBANDS],
bits2: &[i32; NB_EBANDS],
thresh: &[i32; NB_EBANDS],
cap: &[i32; NB_EBANDS],
mut total: i32,
bits1: &'a [i32; NB_EBANDS],
bits2: &'a [i32; NB_EBANDS],
thresh: &'a [i32; NB_EBANDS],
cap: &'a [i32; NB_EBANDS],
total: i32,
skip_rsv: i32,
mut intensity_rsv: i32,
mut dual_stereo_rsv: i32,
c: usize,
lm: usize,
enc: &mut RangeEncoder,
) -> Allocation {
intensity_rsv: i32,
dual_stereo_rsv: i32,
}
fn interp_bits2pulses(m: &Mode, frame: CeltFrame, interpolation: AllocationInterpolation<'_>, enc: &mut RangeEncoder) -> Allocation {
let CeltFrame { start, end, channels: c, lm } = frame;
let AllocationInterpolation { skip_start, bits1, bits2, thresh, cap, mut total, skip_rsv, mut intensity_rsv, mut dual_stereo_rsv } = interpolation;
let ci = c as i32;
let alloc_floor = ci << BITRES;
let stereo = (c > 1) as i32;
@@ -393,7 +392,7 @@ fn interp_bits2pulses(
let mut psum = 0;
let mut done = false;
for j in (start..end).rev() {
let tmp = bits1[j] + (mid * bits2[j] >> ALLOC_STEPS);
let tmp = bits1[j] + ((mid * bits2[j]) >> ALLOC_STEPS);
if tmp >= thresh[j] || done {
done = true;
psum += tmp.min(cap[j]);
@@ -411,7 +410,7 @@ fn interp_bits2pulses(
let mut psum = 0;
let mut done = false;
for j in (start..end).rev() {
let mut tmp = bits1[j] + (lo * bits2[j] >> ALLOC_STEPS);
let mut tmp = bits1[j] + ((lo * bits2[j]) >> ALLOC_STEPS);
if tmp < thresh[j] && !done {
tmp = if tmp >= alloc_floor { alloc_floor } else { 0 };
} else {
@@ -500,9 +499,9 @@ fn interp_bits2pulses(
if n == 2 {
offset += (den << BITRES) >> 2;
}
if bits[j] + offset < den * 2 << BITRES {
if bits[j] + offset < (den * 2) << BITRES {
offset += nclogn >> 2;
} else if bits[j] + offset < den * 3 << BITRES {
} else if bits[j] + offset < (den * 3) << BITRES {
offset += nclogn >> 3;
}
let mut eb = (bits[j] + offset + (den << (BITRES - 1))).max(0);
@@ -513,7 +512,7 @@ fn interp_bits2pulses(
eb = eb.min(MAX_FINE_BITS);
ebits[j] = eb;
fine_priority[j] = (eb * (den << BITRES) >= bits[j] + offset) as i32;
bits[j] -= ci * eb << BITRES;
bits[j] -= (ci * eb) << BITRES;
} else {
excess = (bit - (ci << BITRES)).max(0);
bits[j] = bit - excess;
@@ -523,7 +522,7 @@ fn interp_bits2pulses(
if excess > 0 {
let extra_fine = (excess >> (stereo + BITRES as i32)).min(MAX_FINE_BITS - ebits[j]);
ebits[j] += extra_fine;
let extra_bits = extra_fine * ci << BITRES;
let extra_bits = (extra_fine * ci) << BITRES;
fine_priority[j] = (extra_bits >= excess - balance) as i32;
excess -= extra_bits;
}
+6 -2
View File
@@ -16,8 +16,12 @@ mod pulses;
#[allow(dead_code)]
pub(crate) mod tables;
use lpc::*;
use tables::*;
use lpc::{MAX_LPC_ORDER, div32_varq, inverse32_varq, nlsf2a, rshift_round, sat16, smlawb, smulwb, smulww};
use tables::{
DELTA_GAIN, GAIN_MSB, LTP_FILTER, LTP_PERIODICITY, LTP_SCALE, LTP_TAPS_0, LTP_TAPS_1, LTP_TAPS_2, MID_ONLY, NLSF_EXT, NLSF_INTERP, NLSF_SEL_NBMB,
NLSF_SEL_WB, NLSF_STAGE1, NLSF_STAGE2, PITCH_CONTOUR, PITCH_HIGH, PITCH_LOW, STEREO_PRED_JOINT, STEREO_WEIGHTS_Q13, TYPE_ACTIVE, TYPE_INACTIVE, UNIFORM3,
UNIFORM4, UNIFORM5, UNIFORM8,
};
use crate::range::RangeEncoder;
+1 -1
View File
@@ -1,7 +1,7 @@
//! Encoder-side signal analysis for SILK (own design): windowed autocorrelation LPC, LPC → NLSF
//! conversion, open-loop pitch search and LTP codebook search.
use super::tables::*;
use super::tables::{CB_NB_20, CB_WB_20, LTP_FILTER, LTP_PERIODICITY, LTP_TAPS_0, LTP_TAPS_1, LTP_TAPS_2};
/// Short-term prediction coefficients `a` (prediction `x[n] ≈ Σ a[j] x[n-1-j]`) from the
/// windowed segment `x`, with a Gaussian lag window and white-noise correction.
+4 -1
View File
@@ -5,7 +5,10 @@
//! spec-derived `filmcraft-opus` decoder (MIT OR Apache-2.0): the encoder must reconstruct the
//! quantised NLSFs and LPC coefficients bit-exactly as the decoder does.
use super::tables::*;
use super::tables::{
COS_Q12, LSF_ORDER_NBMB, LSF_ORDER_WB, NLSF_CB_NBMB, NLSF_CB_WB, NLSF_MIN_SPACING_NBMB, NLSF_MIN_SPACING_WB, NLSF_PRED_NBMB, NLSF_PRED_WB, NLSF_PSEL_NBMB,
NLSF_PSEL_WB,
};
pub const MAX_LPC_ORDER: usize = 16;
+3 -1
View File
@@ -3,7 +3,9 @@
//! dequantisation exactly. The search strategy is our own.
use super::lpc::{MAX_LPC_ORDER, nlsf_decode, smlawb, sqrt_approx};
use super::tables::*;
use super::tables::{
NLSF_CB_NBMB, NLSF_CB_WB, NLSF_EXT, NLSF_PRED_NBMB, NLSF_PRED_WB, NLSF_PSEL_NBMB, NLSF_PSEL_WB, NLSF_SEL_NBMB, NLSF_SEL_WB, NLSF_STAGE1, NLSF_STAGE2,
};
/// Number of stage-1 candidates refined with stage 2.
const SURVIVORS: usize = 8;
+1 -1
View File
@@ -2,7 +2,7 @@
//! with LSB escapes, the recursive shell code, LSBs and signs, written in exactly the order the
//! decoder reads them.
use super::tables::*;
use super::tables::{EXC_LSB, EXC_SIGN, PULSE_COUNT, RATE_LEVEL, SHELL_2, SHELL_4, SHELL_8, SHELL_16};
use crate::range::RangeEncoder;
/// Largest pulse magnitude the quantiser produces (keeps every 16-sample block codable).