feat(capability): 转码能力包(vendor 纯 Go AMR-NB 解码器 + 黄金向量逐样本对照 + 8 哨兵 + 注册面)
This commit is contained in:
1 parent
89715d1813
commit
4a2d276881
100 files changed
+11319
No files matched your search
@@ -0,0 +1,244 @@
|
||||
package amrnb
|
||||
|
||||
// Encoder LP analysis chain, ported from opencore-amrnb pre_proc.cpp
|
||||
// (Pre_Process), autocorr.cpp (Autocorr), lag_wind.cpp (Lag_window) and
|
||||
// levinson.cpp (Levinson), plus the 32-bit operators they need (Mpy_32, Div_32,
|
||||
// L_abs). Together these turn 8 kHz PCM into the order-10 LP coefficients A(z):
|
||||
// input high-pass + scaling, windowed autocorrelation, lag-window bandwidth
|
||||
// expansion, then the Levinson-Durbin recursion. Bit-exact with the reference.
|
||||
|
||||
// L_abs returns the saturated 32-bit absolute value (|MIN_32| -> MAX_32).
|
||||
// Mirrors L_abs.
|
||||
func L_abs(x int32) int32 {
|
||||
if x == minInt32 {
|
||||
return maxInt32
|
||||
}
|
||||
if x < 0 {
|
||||
return -x
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
// mpy_32 multiplies two 32-bit values given in (hi,lo) double-precision form.
|
||||
// Mirrors the generic Mpy_32.
|
||||
func mpy_32(hi1, lo1, hi2, lo2 int16) int32 {
|
||||
L := L_mult(hi1, hi2)
|
||||
L = L_add(L, ((int32(hi1)*int32(lo2))>>15)<<1)
|
||||
L = L_add(L, ((int32(lo1)*int32(hi2))>>15)<<1)
|
||||
return L
|
||||
}
|
||||
|
||||
// div_32 divides a 32-bit numerator by a 32-bit denominator (given as hi,lo).
|
||||
// Mirrors Div_32.
|
||||
func div_32(num int32, denomHi, denomLo int16) int32 {
|
||||
approx := div_s(0x3fff, denomHi)
|
||||
result := mpy32_16(denomHi, denomLo, approx)
|
||||
result = 0x7fffffff - result
|
||||
hi, lo := L_Extract(result)
|
||||
result = mpy32_16(hi, lo, approx)
|
||||
hi, lo = L_Extract(result)
|
||||
nHi, nLo := L_Extract(num)
|
||||
result = mpy_32(nHi, nLo, hi, lo)
|
||||
return L_shl(result, 2)
|
||||
}
|
||||
|
||||
// preProcessState holds the encoder input high-pass biquad memory.
|
||||
type preProcessState struct {
|
||||
x0, x1 int16
|
||||
y1hi, y1lo, y2hi, y2lo int16
|
||||
}
|
||||
|
||||
// process applies the input high-pass filter (with 0.5 scaling) in place over
|
||||
// lg samples. Mirrors Pre_Process.
|
||||
func (st *preProcessState) process(signal []int16, lg int) {
|
||||
xn2 := st.x1
|
||||
xn1 := st.x0
|
||||
for i := 0; i < lg; i++ {
|
||||
L := int32(st.y1hi) * 7807
|
||||
L += (int32(st.y1lo) * 7807) >> 15
|
||||
L += int32(st.y2hi) * -3733
|
||||
st.y2hi = st.y1hi
|
||||
L += (int32(st.y2lo) * -3733) >> 15
|
||||
st.y2lo = st.y1lo
|
||||
L += int32(xn2) * 1899
|
||||
xn2 = xn1
|
||||
L += int32(xn1) * -3798
|
||||
xn1 = signal[i]
|
||||
L += int32(xn1) * 1899
|
||||
|
||||
signal[i] = int16((L + 0x800) >> 12)
|
||||
st.y1hi = int16(L >> 12)
|
||||
st.y1lo = int16((L << 3) - (int32(st.y1hi) << 15))
|
||||
}
|
||||
st.x1 = xn2
|
||||
st.x0 = xn1
|
||||
}
|
||||
|
||||
// autocorr windows x with wind and computes the order-m autocorrelation into
|
||||
// (rh,rl) double precision, returning the normalization shift applied. Mirrors
|
||||
// Autocorr.
|
||||
func autocorr(x []int16, m int, rh, rl, wind []int16) int16 {
|
||||
var y [cL_WINDOW]int16
|
||||
|
||||
var sum int32
|
||||
overflow := false
|
||||
b := 0
|
||||
for ; b < cL_WINDOW; b++ {
|
||||
temp := int16((int32(x[b])*int32(wind[b]) + 0x4000) >> 15)
|
||||
y[b] = temp
|
||||
sum += (int32(temp) * int32(temp)) << 1
|
||||
if sum < 0 {
|
||||
overflow = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
overflShft := int16(0)
|
||||
if overflow {
|
||||
for k := b + 1; k < cL_WINDOW; k++ {
|
||||
y[k] = int16((int32(x[k])*int32(wind[k]) + 0x4000) >> 15)
|
||||
}
|
||||
for {
|
||||
overflShft += 4
|
||||
sum = 0
|
||||
for k := 0; k < cL_WINDOW; k++ {
|
||||
t := y[k] >> 2
|
||||
y[k] = t
|
||||
sum += (int32(t) * int32(t)) << 1
|
||||
}
|
||||
if sum > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sum++ // avoid all-zeros
|
||||
norm := norm_l(sum)
|
||||
sum <<= uint(norm)
|
||||
rh[0] = int16(sum >> 16)
|
||||
rl[0] = int16((sum >> 1) - (int32(rh[0]) << 15))
|
||||
|
||||
for i := 1; i <= m; i++ {
|
||||
// sum_{n=i}^{W-1} y[n]·y[n-i] = sum_k y[i+k]·y[k] (wrapping int32) via firDot
|
||||
s := firDot(y[i:cL_WINDOW], y[:cL_WINDOW-i])
|
||||
s <<= uint(norm + 1)
|
||||
rh[i] = int16(s >> 16)
|
||||
rl[i] = int16((s >> 1) - (int32(rh[i]) << 15))
|
||||
}
|
||||
|
||||
return norm - overflShft
|
||||
}
|
||||
|
||||
// lagWindow applies the lag-window bandwidth expansion to the autocorrelation
|
||||
// in place. Mirrors Lag_window.
|
||||
func lagWindow(m int, rh, rl []int16) {
|
||||
for i := 1; i <= m; i++ {
|
||||
x := mpy_32(rh[i], rl[i], lag_h[i-1], lag_l[i-1])
|
||||
rh[i] = int16(x >> 16)
|
||||
rl[i] = int16((x >> 1) - (int32(rh[i]) << 15))
|
||||
}
|
||||
}
|
||||
|
||||
// levinsonState carries the last stable A(z) for the unstable-filter fallback.
|
||||
type levinsonState struct {
|
||||
oldA [cMP1]int16
|
||||
}
|
||||
|
||||
// levinson runs the Levinson-Durbin recursion on the (rh,rl) autocorrelation,
|
||||
// producing order-10 LP coefficients A[0:M+1] and the first 4 reflection
|
||||
// coefficients rc[0:4]. Mirrors Levinson.
|
||||
func (st *levinsonState) levinson(rh, rl, a, rc []int16) {
|
||||
var ah, al, anh, anl [cMP1]int16
|
||||
|
||||
t1 := (int32(rh[1]) << 16) + (int32(rl[1]) << 1)
|
||||
t2 := L_abs(t1)
|
||||
t0 := div_32(t2, rh[0], rl[0]) // R[1]/R[0]
|
||||
if t1 > 0 {
|
||||
t0 = L_negate(t0)
|
||||
}
|
||||
kh, kl := L_Extract(t0)
|
||||
rc[0] = round_(t0)
|
||||
|
||||
t0 >>= 4
|
||||
ah[1] = int16(t0 >> 16)
|
||||
al[1] = int16((t0 >> 1) - (int32(ah[1]) << 15))
|
||||
|
||||
t0 = mpy_32(kh, kl, kh, kl) // K*K
|
||||
t0 = L_abs(t0)
|
||||
t0 = 0x7fffffff - t0 // 1 - K*K
|
||||
hi, lo := L_Extract(t0)
|
||||
t0 = mpy_32(rh[0], rl[0], hi, lo) // Alpha
|
||||
alpExp := norm_l(t0)
|
||||
t0 = t0 << uint(alpExp)
|
||||
alpH := int16(t0 >> 16)
|
||||
alpL := int16((t0 >> 1) - (int32(alpH) << 15))
|
||||
|
||||
for i := 2; i <= cM; i++ {
|
||||
t0 = 0
|
||||
for j := 1; j < i; j++ {
|
||||
t0 += (int32(rh[j]) * int32(al[i-j])) >> 15
|
||||
t0 += (int32(rl[j]) * int32(ah[i-j])) >> 15
|
||||
t0 += int32(rh[j]) * int32(ah[i-j])
|
||||
}
|
||||
t0 <<= 5
|
||||
t1 = (int32(rh[i]) << 16) + (int32(rl[i]) << 1)
|
||||
t0 += t1
|
||||
|
||||
t1 = L_abs(t0)
|
||||
t2 = div_32(t1, alpH, alpL)
|
||||
if t0 > 0 {
|
||||
t2 = L_negate(t2)
|
||||
}
|
||||
t2 = L_shl(t2, alpExp)
|
||||
kh = int16(t2 >> 16)
|
||||
kl = int16((t2 >> 1) - (int32(kh) << 15))
|
||||
|
||||
if i < 5 {
|
||||
rc[i-1] = int16((t2 + 0x8000) >> 16)
|
||||
}
|
||||
if abs_s(kh) > 32750 { // unstable filter -> reuse last A(z)
|
||||
copy(a[:cMP1], st.oldA[:])
|
||||
for k := 0; k < 4; k++ {
|
||||
rc[k] = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for j := 1; j < i; j++ {
|
||||
t0 = (int32(kh) * int32(al[i-j])) >> 15
|
||||
t0 += (int32(kl) * int32(ah[i-j])) >> 15
|
||||
t0 += int32(kh) * int32(ah[i-j])
|
||||
t0 += (int32(ah[j]) << 15) + int32(al[j])
|
||||
anh[j] = int16(t0 >> 15)
|
||||
anl[j] = int16(t0 - (int32(anh[j]) << 15))
|
||||
}
|
||||
anh[i] = int16(t2 >> 20)
|
||||
anl[i] = int16((t2 >> 5) - (int32(anh[i]) << 15))
|
||||
|
||||
t0 = mpy_32(kh, kl, kh, kl) // K*K
|
||||
t0 = L_abs(t0)
|
||||
t0 = 0x7fffffff - t0 // 1 - K*K
|
||||
hi = int16(t0 >> 16)
|
||||
lo = int16((t0 >> 1) - (int32(hi) << 15))
|
||||
|
||||
t0 = (int32(alpH) * int32(lo)) >> 15
|
||||
t0 += (int32(alpL) * int32(hi)) >> 15
|
||||
t0 += int32(alpH) * int32(hi)
|
||||
t0 <<= 1
|
||||
jn := norm_l(t0)
|
||||
t0 = t0 << uint(jn)
|
||||
alpH = int16(t0 >> 16)
|
||||
alpL = int16((t0 >> 1) - (int32(alpH) << 15))
|
||||
alpExp += jn
|
||||
|
||||
copy(ah[1:1+i], anh[1:1+i])
|
||||
copy(al[1:1+i], anl[1:1+i])
|
||||
}
|
||||
|
||||
a[0] = 4096
|
||||
for i := 1; i <= cM; i++ {
|
||||
t0 = (int32(ah[i]) << 15) + int32(al[i])
|
||||
a[i] = int16((t0 + 0x2000) >> 14)
|
||||
st.oldA[i] = a[i]
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user