Files
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

207 lines
6.4 KiB
Go

package amrnb
// Multi-pulse algebraic codebook search, ported from opencore-amrnb s10_8pf.cpp
// (search_10and8i40). This parameterized depth-first search places 8 (MR102) or
// 10 (MR122) pulses, two tracks at a time, using a precomputed interleaved
// scratch (temp1) to cache the partial ps/alp values of the second pulse of each
// pair across the first pulse's positions. The pulse-track ordering (ipos) is
// rotated across the outer loop. The single most intricate function in the
// codec; the exact incremental criterion arithmetic is preserved (bit-exact).
func search10and8i40(nbPulse, step, nbTracks int16, dn, rr, ipos, posMax, codvec []int16) {
const L = cL_CODE
gsmefr := nbPulse == 10
var index [10]int16
var temp1 [2 * cL_CODE]int16
i0 := posMax[ipos[0]]
index[0] = i0
psk := int16(-1)
alpk := int16(1)
for i := int16(0); i < nbPulse; i++ {
codvec[i] = i
}
var i1, i2, i3, i4, i5, i6, i7 int16
for outer := int16(1); outer < nbTracks; outer++ {
i1 = posMax[ipos[1]]
index[1] = i1
ps0 := int16(int32(dn[i0]) + int32(dn[i1]))
alp0 := int32(rr[int(i0)*L+int(i0)]) << 12
alp0 += int32(rr[int(i1)*L+int(i1)]) << 12
alp0 += int32(rr[int(i0)*L+int(i1)]) << 13
alp0 += 0x8000
// ---- pulses 2 & 3 ----
ti := 0
for i3v := ipos[3]; i3v < L; i3v += step {
rrRow := rr[int(i3v)*L : int(i3v)*L+L]
s := int32(rrRow[int(i3v)]) >> 1
s += int32(rrRow[int(i0)])
s += int32(rrRow[int(i1)])
temp1[ti] = ps0 + dn[i3v]
temp1[ti+1] = int16((s + 2) >> 2)
ti += 2
}
sq := int16(-1)
alp := int16(1)
ps := int16(0)
ia := ipos[2]
ib := ipos[3]
sbase := alp0 >> 12
for j := ipos[2]; j < L; j += step {
rrRow := rr[int(j)*L : int(j)*L+L]
alp1 := (sbase + int32(rrRow[int(j)])) >> 1
alp1 += int32(rrRow[int(i0)])
alp1 += int32(rrRow[int(i1)])
ps1 := dn[j]
ti = 0
for i3v := ipos[3]; i3v < L; i3v += step {
ps2 := ps1 + temp1[ti]
sq2 := int16((int32(ps2) * int32(ps2)) >> 15)
alp2 := (alp1 + int32(rrRow[int(i3v)])) >> 2
alp2 = (alp2 + int32(temp1[ti+1])) >> 1
ti += 2
if int32(sq2)*int32(alp) > int32(sq)*alp2 {
sq, ps, alp, ia, ib = sq2, ps2, int16(alp2), j, i3v
}
}
}
i2, i3 = ia, ib
index[2], index[3] = ia, ib
// ---- pulses 4 & 5 ----
alp0 = (int32(alp) << 15) + 0x8000
ti = 0
for i5v := ipos[5]; i5v < L; i5v += step {
rrRow := rr[int(i5v)*L : int(i5v)*L+L]
s := int32(rrRow[int(i5v)]) >> 1
s += int32(rrRow[int(i0)]) + int32(rrRow[int(i1)]) + int32(rrRow[int(i2)]) + int32(rrRow[int(i3)])
temp1[ti] = ps + dn[i5v]
temp1[ti+1] = int16((s + 2) >> 2)
ti += 2
}
sq, alp, ps, ia, ib = -1, 1, 0, ipos[4], ipos[5]
for j := ipos[4]; j < L; j += step {
rrRow := rr[int(j)*L : int(j)*L+L]
alp1 := alp0 + (int32(rrRow[int(j)]) << 11)
alp1 += int32(rrRow[int(i0)]) << 12
alp1 += int32(rrRow[int(i1)]) << 12
alp1 += int32(rrRow[int(i2)]) << 12
alp1 += int32(rrRow[int(i3)]) << 12
ps1 := dn[j]
ti = 0
for i5v := ipos[5]; i5v < L; i5v += step {
ps2 := ps1 + temp1[ti]
alp2 := alp1 + (int32(rrRow[int(i5v)]) << 12)
alp16 := int16((alp2 + (int32(temp1[ti+1]) << 14)) >> 16)
ti += 2
sq2 := int16((int32(ps2) * int32(ps2)) >> 15)
if int32(sq2)*int32(alp) > int32(sq)*int32(alp16) {
sq, ps, alp, ia, ib = sq2, ps2, alp16, j, i5v
}
}
}
i4, i5 = ia, ib
index[4], index[5] = ia, ib
// ---- pulses 6 & 7 ----
alp0 = (int32(alp) << 15) + 0x8000
ti = 0
for i7v := ipos[7]; i7v < L; i7v += step {
rrRow := rr[int(i7v)*L : int(i7v)*L+L]
s := int32(rrRow[int(i7v)]) >> 1
s += int32(rrRow[int(i0)]) + int32(rrRow[int(i1)]) + int32(rrRow[int(i2)]) +
int32(rrRow[int(i3)]) + int32(rrRow[int(i4)]) + int32(rrRow[int(i5)])
temp1[ti] = ps + dn[i7v]
temp1[ti+1] = int16((s + 4) >> 3)
ti += 2
}
sq, alp, ps, ia, ib = -1, 1, 0, ipos[6], ipos[7]
for j := ipos[6]; j < L; j += step {
rrRow := rr[int(j)*L : int(j)*L+L]
alp1 := alp0 + (int32(rrRow[int(j)]) << 10)
alp1 += int32(rrRow[int(i0)]) << 11
alp1 += int32(rrRow[int(i1)]) << 11
alp1 += int32(rrRow[int(i2)]) << 11
alp1 += int32(rrRow[int(i3)]) << 11
alp1 += int32(rrRow[int(i4)]) << 11
alp1 += int32(rrRow[int(i5)]) << 11
ps1 := dn[j]
ti = 0
for i7v := ipos[7]; i7v < L; i7v += step {
ps2 := ps1 + temp1[ti]
alp2 := alp1 + (int32(rrRow[int(i7v)]) << 11)
alp16 := int16((alp2 + (int32(temp1[ti+1]) << 14)) >> 16)
ti += 2
sq2 := int16((int32(ps2) * int32(ps2)) >> 15)
if int32(sq2)*int32(alp) > int32(sq)*int32(alp16) {
sq, ps, alp, ia, ib = sq2, ps2, alp16, j, i7v
}
}
}
i6, i7 = ia, ib
index[6], index[7] = ia, ib
// ---- pulses 8 & 9 (MR122 only) ----
if gsmefr {
alp0 = (int32(alp) << 15) + 0x8000
ti = 0
for i9v := ipos[9]; i9v < L; i9v += step {
rrRow := rr[int(i9v)*L : int(i9v)*L+L]
s := int32(rrRow[int(i9v)]) >> 1
s += int32(rrRow[int(i0)]) + int32(rrRow[int(i1)]) + int32(rrRow[int(i2)]) +
int32(rrRow[int(i3)]) + int32(rrRow[int(i4)]) + int32(rrRow[int(i5)]) +
int32(rrRow[int(i6)]) + int32(rrRow[int(i7)])
temp1[ti] = ps + dn[i9v]
temp1[ti+1] = int16((s + 4) >> 3)
ti += 2
}
sq, alp, ps, ia, ib = -1, 1, 0, ipos[8], ipos[9]
for j := ipos[8]; j < L; j += step {
rrRow := rr[int(j)*L : int(j)*L+L]
alp1 := alp0 + (int32(rrRow[int(j)]) << 9)
alp1 += int32(rr[int(i0)*L+int(j)]) << 10
alp1 += int32(rr[int(i1)*L+int(j)]) << 10
alp1 += int32(rr[int(i2)*L+int(j)]) << 10
alp1 += int32(rr[int(i3)*L+int(j)]) << 10
alp1 += int32(rr[int(i4)*L+int(j)]) << 10
alp1 += int32(rr[int(i5)*L+int(j)]) << 10
alp1 += int32(rr[int(i6)*L+int(j)]) << 10
alp1 += int32(rr[int(i7)*L+int(j)]) << 10
ps1 := dn[j]
ti = 0
for i9v := ipos[9]; i9v < L; i9v += step {
ps2 := ps1 + temp1[ti]
sq2 := int16((int32(ps2) * int32(ps2)) >> 15)
alp2 := alp1 + (int32(rrRow[int(i9v)]) << 10)
alp16 := int16((alp2 + (int32(temp1[ti+1]) << 13)) >> 16)
ti += 2
if int32(sq2)*int32(alp) > int32(sq)*int32(alp16) {
sq, ps, alp, ia, ib = sq2, ps2, alp16, j, i9v
}
}
}
index[8], index[9] = ia, ib
}
// ---- keep the best ----
if int32(alpk)*int32(sq) > int32(psk)*int32(alp) {
psk = sq
alpk = alp
copy(codvec[:nbPulse], index[:nbPulse])
}
// rotate ipos[1..nbPulse-1] left by one
pos := ipos[1]
for j := int16(1); j < nbPulse-1; j++ {
ipos[j] = ipos[j+1]
}
ipos[nbPulse-1] = pos
}
}