// celt_postfilter.mbt
//
// 后滤波(RFC 6716 §4.3.7.1):基音周期 comb 滤波,输出
//
//     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)))
//
// RFC 正文式子有排版重复(两侧写成同一下标),这里按参考实现
// celt_celt.c 的 comb_filter / comb_filter_const 浮点路径逐项对齐:
//
//   - 抽头 = G 不参与逐项相乘,而是分成 g0·gains[ts]、g1·gains[ts] 两组,
//     gains 表就是 RFC 给的三组 tapset 系数(float 构建 QCONST16 恒等);
//   - 过渡段(前 overlap 个样本)用 MDCT 窗平方做逐点插值:f = w[i]²,
//     (1−f) 加权旧参数(T0/ts0)、f 加权新参数(T1/ts1),且 y 逐点
//     回读——必须在位滤波,先读后写,后面的项读到的已是插值后的值;
//   - 周期钳到 ≥ COMBFILTER_MINPERIOD(调用方与函数内双重钳制,同 C);
//     旧新参数全等时过渡段整体跳过(窗只用于参数切换);
//   - 过渡段之后若新增益为 0,后段原样保留;否则跑常数段
//     (comb_filter_const,固定 T1/ts1 的直接递推)。
//
// 调用形态(celt_decode_frame):帧首 120 样本用(旧→新)过渡,
// LM≠0 时其余样本再以(新→新)跑一遍(参数全等自动走常数段)。
// 解码器随后把旧参数轮换为新参数。
//
// 对 buf 的要求:`base` 之前需保留 ≥ 1022 个历史样本(解码端的
// decode_mem 提供),函数只写 `buf[base, base+n)`,且 n ≥ overlap
// (过渡段激活时,同参考实现的调用约定)。

///|
/// 最小基音周期(celt_celt.h 的 COMBFILTER_MINPERIOD)。
pub const CEL_COMB_MINPERIOD : Int = 15

///|
/// tapset 抽头系数表(RFC §4.3.7.1),行 = tapset 0/1/2,
/// 列 = (g0 分量的 3 个系数)。索引 `3*ts + j`。
let cel_tap_gains : Array[Double] = [
  0.306640625, 0.2170410156, 0.1296386719, 0.4638671875, 0.2680664062, 0.0, 0.7998046875,
  0.1000976562, 0.0,
]

///|
/// 后滤波 comb 滤波,就地作用于 `buf[base, base+n)`。
///
/// `t0/g0/ts0` 为旧参数、`t1/g1/ts1` 为新参数(G 已折算进 g),
/// `win` 为预取的 MDCT 窗(长度即 overlap)。实现顺序与参考实现
/// 一致:全零捷径 → 钳制 → 过渡段(滑动状态读 f 分支的四个历史
/// 样本)→ 新增益零捷径 → 常数段。
pub fn celt_comb_filter(
  buf : Array[Double],
  base : Int,
  t0 : Int,
  t1 : Int,
  n : Int,
  g0 : Double,
  g1 : Double,
  ts0 : Int,
  ts1 : Int,
  win : Array[Double],
) -> Unit {
  if g0 == 0.0 && g1 == 0.0 {
    return
  }
  let tp0 = if t0 < CEL_COMB_MINPERIOD { CEL_COMB_MINPERIOD } else { t0 }
  let tp1 = if t1 < CEL_COMB_MINPERIOD { CEL_COMB_MINPERIOD } else { t1 }
  let g00 = g0 * cel_tap_gains[3 * ts0]
  let g01 = g0 * cel_tap_gains[3 * ts0 + 1]
  let g02 = g0 * cel_tap_gains[3 * ts0 + 2]
  let g10 = g1 * cel_tap_gains[3 * ts1]
  let g11 = g1 * cel_tap_gains[3 * ts1 + 1]
  let g12 = g1 * cel_tap_gains[3 * ts1 + 2]
  let mut overlap = win.length()
  if g0 == g1 && tp0 == tp1 && ts0 == ts1 {
    overlap = 0
  }
  // f 分支的四个滑动样本:等价于逐点直读(t≥15 保证读取位点在当前
  // 写入位点之前,原值/插值后值一致),保持与参考实现同一读取顺序
  let mut x1 = buf[base - tp1 + 1]
  let mut x2 = buf[base - tp1]
  let mut x3 = buf[base - tp1 - 1]
  let mut x4 = buf[base - tp1 - 2]
  let mut i = 0
  while i < overlap {
    let x0 = buf[base + i - tp1 + 2]
    let w = win[i]
    let f = w * w
    let omf = 1.0 - f
    let mut acc = buf[base + i]
    acc = acc + omf * g00 * buf[base + i - tp0]
    acc = acc + omf * g01 * (buf[base + i - tp0 + 1] + buf[base + i - tp0 - 1])
    acc = acc + omf * g02 * (buf[base + i - tp0 + 2] + buf[base + i - tp0 - 2])
    acc = acc + f * g10 * x2
    acc = acc + f * g11 * (x1 + x3)
    acc = acc + f * g12 * (x0 + x4)
    buf[base + i] = acc
    x4 = x3
    x3 = x2
    x2 = x1
    x1 = x0
    i = i + 1
  }
  if g1 == 0.0 {
    return
  }
  while i < n {
    let mut acc = buf[base + i]
    acc = acc + g10 * buf[base + i - tp1]
    acc = acc + g11 * (buf[base + i - tp1 + 1] + buf[base + i - tp1 - 1])
    acc = acc + g12 * (buf[base + i - tp1 + 2] + buf[base + i - tp1 - 2])
    buf[base + i] = acc
    i = i + 1
  }
}