Files
Cyrene_v2/internal/capability/transcode/amrnb/dsp_enc_cbsearch2.go
T
AskaEth 4a2d276881
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
feat(capability): 转码能力包(vendor 纯 Go AMR-NB 解码器 + 黄金向量逐样本对照 + 8 哨兵 + 注册面)
2026-10-05 13:02:28 +08:00

107 lines
2.7 KiB
Go

package amrnb
// Parameterized codebook-search correlation, ported from opencore-amrnb
// cor_h_x2.cpp. corHX2 is the generalized form of corHX used by the multi-pulse
// searches (MR102: 4 tracks, MR122: 5 tracks): dn[i] = normalized 2·Σ x[j]·h[j-i]
// with a configurable track count and step. Bit-exact with the reference.
const cLOG2_OF_32 = 5
// corHX2 computes the normalized target↔impulse correlation dn[] over nbTrack
// tracks with the given step, scaled by sf. Mirrors cor_h_x2.
func corHX2(h, x, dn []int16, sf, nbTrack, step int16) {
// y32[i] = 2·sum_{j=i}^{L-1} x[j]·h[j-i] = 2·sum_{j'=0}^{L-1-i} x[i+j']·h[j'].
// Zero-padding x past L turns this into one L-tap FIR over the padded input
// (firRaw); s<<1 == dst[i]<<1 holds mod 2^32 since <<1 distributes over the
// wrapping sum.
var xpad [2 * cL_CODE]int16
copy(xpad[:cL_CODE], x[:cL_CODE])
var dst [cL_CODE]int32
firRaw(dst[:], xpad[:], h[:cL_CODE])
var y32 [cL_CODE]int32
for i := 0; i < cL_CODE; i++ {
y32[i] = dst[i] << 1
}
tot := int32(cLOG2_OF_32)
for k := int16(0); k < nbTrack; k++ {
var max int32
for i := k; i < cL_CODE; i += step {
if a := L_abs(y32[i]); a > max {
max = a
}
}
tot += max >> 1
}
j := norm_l(tot) - sf
for i := 0; i < cL_CODE; i++ {
dn[i] = round_(L_shl(y32[i], j))
}
}
// setSign12k2 combines the residual cn and the correlation dn to determine each
// position's pulse sign, the per-track maximum positions (posMax), and a cyclic
// pulse-track ordering (ipos, length 2*nbTrack) starting from the strongest
// track — the prep for the multi-pulse search_10and8i40. dn is updated in place
// (negated where the combined sign is negative). Mirrors set_sign12k2.
func setSign12k2(dn, cn, sign, posMax []int16, nbTrack int16, ipos []int16, step int16) {
const L = cL_CODE
var en [cL_CODE]int16
s := int32(256)
t := int32(256)
for i := 0; i < L; i++ {
s = L_mac(s, cn[i], cn[i])
t += (int32(dn[i]) * int32(dn[i])) << 1
}
s = invSqrt(s)
kCn := int16(L_shl(s, 5) >> 16)
t = invSqrt(t)
kDn := int16(t >> 11)
for i := L - 1; i >= 0; i-- {
lTemp := (int32(kCn) * int32(cn[i])) << 1
val := dn[i]
ss := L_mac(lTemp, kDn, val)
cor := round_(L_shl(ss, 10))
if cor >= 0 {
sign[i] = 32767
} else {
sign[i] = -32767
cor = negate(cor)
dn[i] = negate(val)
}
en[i] = cor
}
maxOfAll := int16(-1)
var pos int16
for i := int16(0); i < nbTrack; i++ {
max := int16(-1)
for j := i; j < L; j += step {
if en[j] > max {
max = en[j]
pos = j
}
}
posMax[i] = pos
if max > maxOfAll {
maxOfAll = max
ipos[0] = i
}
}
pos = ipos[0]
ipos[nbTrack] = pos
for i := int16(1); i < nbTrack; i++ {
pos++
if pos >= nbTrack {
pos = 0
}
ipos[i] = pos
ipos[i+nbTrack] = pos
}
}