feat(capability): 转码能力包(vendor 纯 Go AMR-NB 解码器 + 黄金向量逐样本对照 + 8 哨兵 + 注册面)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

This commit is contained in:
AskaEth committed 2026-10-05 13:02:28 +08:00
1 parent 89715d1813
commit 4a2d276881
100 files changed
+11319

No files matched your search

@@ -0,0 +1,67 @@
package amrnb
// Output post-processing building blocks, ported from opencore-amrnb
// weight_a.cpp (Weight_Ai), preemph.cpp (preemphasis) and post_pro.cpp
// (Post_Process). weightAi applies gamma bandwidth expansion to an LP filter;
// preemphasis is the 1st-order y[n]=x[n]-g·x[n-1]; postProcess is the decoder's
// output high-pass biquad with the ×2 output scaling. Bit-exact with the
// reference.
// weightAi computes the bandwidth-expanded coefficients a_exp[i] = a[i]·fac[i-1]
// (with a_exp[0]=a[0]). Mirrors Weight_Ai.
func weightAi(a []int16, fac []int16, aExp []int16) {
aExp[0] = a[0]
for i := 1; i <= cM; i++ {
aExp[i] = int16((int32(a[i])*int32(fac[i-1]) + 0x4000) >> 15)
}
}
// preemphasis applies y[n] = x[n] - g·x[n-1] in place over L samples, carrying
// one sample of memory. Mirrors preemphasis (preemph.cpp).
func preemphasis(memPre *int16, signal []int16, g int16, L int) {
temp := signal[L-1]
for i := L - 1; i >= 1; i-- {
signal[i] = sub(signal[i], mult(g, signal[i-1]))
}
signal[0] = sub(signal[0], mult(g, *memPre))
*memPre = temp
}
// post-process output high-pass biquad coefficients (post_pro.cpp).
var postB = [3]int16{7699, -15398, 7699}
var postA = [3]int16{8192, 15836, -7667}
// postProcessState holds the biquad's double-precision input/output memory.
type postProcessState struct {
x0, x1 int16
y1hi, y1lo, y2hi, y2lo int16
}
// process applies the output high-pass filter (with ×2 gain) in place over lg
// samples. The feedback memory is kept as (hi,lo) double precision. Mirrors
// Post_Process.
func (st *postProcessState) process(signal []int16, lg int) {
a1, a2 := int32(postA[1]), int32(postA[2])
b0, b1, b2 := int32(postB[0]), int32(postB[1]), int32(postB[2])
for i := 0; i < lg; i++ {
x2 := st.x1
st.x1 = st.x0
st.x0 = signal[i]
L := int32(st.y1hi) * a1
L += (int32(st.y1lo) * a1) >> 15
L += int32(st.y2hi) * a2
L += (int32(st.y2lo) * a2) >> 15
L += int32(st.x0) * b0
L += int32(st.x1) * b1
L += int32(x2) * b2
L = L_shl(L, 3)
signal[i] = round_(L_shl(L, 1))
st.y2hi = st.y1hi
st.y2lo = st.y1lo
st.y1hi = int16(L >> 16)
st.y1lo = int16((L >> 1) - (int32(st.y1hi) << 15))
}
}