// celt_quant_band.mbt
//
// 带级量化解码入口(RFC 6716 §4.3.4 Shape Decoding 的 band 层)。
//
// 对应参考实现 celt_bands.c 的 quant_band() 解码侧,四段结构:
//
// 1. n==1 特例:预算够就读 1 个 raw bit 作符号,输出 ±1(不乘 gain);
// 2. 前段:按 TF 布局变换 fill 位图;有折叠源时先对它施加前向 TF
// 变换(编码端对 X 做同样的变换,解码端到 lowband 上);
// 3. 中段:celt_partition_rec 递归分割解码,叶上完成谱应用
// (归一化/旋转/噪声与折叠填充,见 celt_partition.mbt);
// 4. 后段:celt_tf_inverse 把已解码向量还原到频序;cm 按同一布局
// 反向变换并按最终 B 掩蔽;可选写 lowband_out(×√N0,供后续
// 等长带折叠)。
//
// 带级 fill 的 TF 位图变换与 cm 的反向变换和 TF 链共用 celt_tf_layout
// 推导出的结构参数,避免两处各写一遍推导。
///|
/// fill 位图的 4 bit 交织表(celt_bands.c 的 bit_interleave_table)。
let cel_bit_interleave : Array[Int] = [
0, 1, 1, 1, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
]
///|
/// cm 的 4 bit 反交织表(celt_bands.c 的 bit_deinterleave_table)。
let cel_bit_deinterleave : Array[Int] = [
0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F, 0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3,
0xFC, 0xFF,
]
///|
/// fill 的正向 TF 位图变换(C 前段循环的 fill 部分:recombine 段按
/// 4 bit 交织表重排,时间段逐级 `fill |= fill< Int {
let mut f = fill
for _ in 0..> 4] << 2)
}
let mut bb = lay.b_start
for _ in 0..>B`,recombine 段按 4 bit
/// 反交织表重排,最后按 `B<<=recombine` 后的位宽掩蔽。
fn celt_cm_transform(cm : Int, lay : CelTfLayout) -> Int {
let mut c = cm
let mut bb = lay.b_end
for _ in 0..> 1
c = c | (c >> bb)
}
for _ in 0.. (Int, Int64, Int) {
// ---- n==1:quant_band_n1 的符号位 ----
if n == 1 {
let mut rem = remaining
let mut sign = 0
if rem >= 1 << CEL_BITRES {
sign = dec.dec_bits(1)
rem -= 1 << CEL_BITRES
}
x[0] = if sign != 0 { -1.0 } else { 1.0 }
if lowband_out.length() > 0 {
lowband_out[0] = x[0]
}
return (1, seed, rem)
}
let lay = celt_tf_layout(n, blocks, tf_change)
let fill_tf = celt_fill_transform(fill, lay)
if lowband.length() > 0 {
celt_tf_forward(lowband, n, blocks, tf_change)
}
let splits : Array[CeltThetaSplit] = []
let leaves : Array[CeltPartitionLeaf] = []
let ctx = CeltBandCtx::{
active: true,
x,
lowband,
has_lowband: lowband.length() > 0,
spread,
seed: [seed],
}
let (rem2, cm_raw) = celt_partition_rec(
dec,
band,
lm,
n,
b,
lay.b_end,
fill_tf,
remaining,
splits,
leaves,
ctx,
0,
0,
gain,
)
celt_tf_inverse(x, n, blocks, tf_change)
let cm = celt_cm_transform(cm_raw, lay)
if lowband_out.length() > 0 {
let s = @math.pow(n.to_double(), 0.5)
for j in 0..