107 lines
2.7 KiB
Go
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
|
|
}
|
|
}
|