207 lines
6.4 KiB
Go
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
|
|
}
|
|
}
|