128 lines
2.7 KiB
Go
128 lines
2.7 KiB
Go
package amrnb
|
|
|
|
// A(z) -> LSP conversion, ported from opencore-amrnb az_lsp.cpp (Chebps, Az_lsp).
|
|
// Az_lsp finds the line spectral pairs of an order-10 LP filter by locating the
|
|
// roots of the symmetric/antisymmetric polynomials F1(z)/F2(z) on the unit
|
|
// circle, evaluated via the Chebyshev recursion (Chebps) over the cosine grid.
|
|
// This is the encoder-side inverse of lspAz. Bit-exact with the reference.
|
|
|
|
const cNC = cM / 2 // 5
|
|
|
|
// chebps evaluates the Chebyshev series of f at x. Mirrors Chebps.
|
|
func chebps(x int16, f []int16, n int) int16 {
|
|
pf := 1
|
|
lTemp := int32(0x01000000)
|
|
t0 := (int32(x) << 10) + (int32(f[pf]) << 14)
|
|
pf++
|
|
b1h := int16(t0 >> 16)
|
|
b1l := int16((t0 >> 1) - (int32(b1h) << 15))
|
|
|
|
for i := 2; i < n; i++ {
|
|
t0 = int32(b1h) * int32(x)
|
|
t0 += (int32(b1l) * int32(x)) >> 15
|
|
t0 <<= 2
|
|
t0 -= lTemp
|
|
t0 += int32(f[pf]) << 14
|
|
pf++
|
|
lTemp = (int32(b1h) << 16) + (int32(b1l) << 1)
|
|
b1h = int16(t0 >> 16)
|
|
b1l = int16((t0 >> 1) - (int32(b1h) << 15))
|
|
}
|
|
|
|
t0 = int32(b1h) * int32(x)
|
|
t0 += (int32(b1l) * int32(x)) >> 15
|
|
t0 <<= 1
|
|
t0 -= lTemp
|
|
t0 += int32(f[pf]) << 13
|
|
|
|
if uint32(t0+33554432) < 67108863 {
|
|
return int16(t0 >> 10)
|
|
} else if t0 > 0x01ffffff {
|
|
return maxInt16
|
|
}
|
|
return minInt16
|
|
}
|
|
|
|
// azLsp converts order-10 LP coefficients a[0:M+1] to line spectral pairs
|
|
// lsp[0:M]. oldLsp is reused if fewer than M roots are found. Mirrors Az_lsp.
|
|
func azLsp(a, lsp, oldLsp []int16) {
|
|
var f1, f2 [cNC + 1]int16
|
|
f1[0] = 1024
|
|
f2[0] = 1024
|
|
for i := 0; i < cNC; i++ {
|
|
lt1 := int32(a[i+1])
|
|
lt2 := int32(a[cM-i])
|
|
x := int16((lt1 + lt2) >> 2)
|
|
y := int16((lt1 - lt2) >> 2)
|
|
x -= f1[i]
|
|
f1[i+1] = x
|
|
y += f2[i]
|
|
f2[i+1] = y
|
|
}
|
|
|
|
nf := 0
|
|
ip := 0
|
|
coef := f1[:]
|
|
|
|
xlow := grid[0]
|
|
ylow := chebps(xlow, coef, cNC)
|
|
|
|
j := 0
|
|
for nf < cM && j < 60 {
|
|
j++
|
|
xhigh := xlow
|
|
yhigh := ylow
|
|
xlow = grid[j]
|
|
ylow = chebps(xlow, coef, cNC)
|
|
|
|
if int32(ylow)*int32(yhigh) <= 0 {
|
|
for i := 4; i != 0; i-- {
|
|
xmid := (xlow >> 1) + (xhigh >> 1)
|
|
ymid := chebps(xmid, coef, cNC)
|
|
if int32(ylow)*int32(ymid) <= 0 {
|
|
yhigh = ymid
|
|
xhigh = xmid
|
|
} else {
|
|
ylow = ymid
|
|
xlow = xmid
|
|
}
|
|
}
|
|
|
|
x := xhigh - xlow
|
|
yv := yhigh - ylow
|
|
var xint int16
|
|
if yv == 0 {
|
|
xint = xlow
|
|
} else {
|
|
sign := yv
|
|
yv = abs_s(yv)
|
|
exp := norm_s(yv)
|
|
yv = shl(yv, exp)
|
|
yv = div_s(16383, yv)
|
|
yv = int16((int32(x) * int32(yv)) >> uint(19-exp))
|
|
if sign < 0 {
|
|
yv = -yv
|
|
}
|
|
xint = int16(int32(xlow) - ((int32(ylow) * int32(yv)) >> 10))
|
|
}
|
|
|
|
lsp[nf] = xint
|
|
xlow = xint
|
|
nf++
|
|
|
|
if ip == 0 {
|
|
ip = 1
|
|
coef = f2[:]
|
|
} else {
|
|
ip = 0
|
|
coef = f1[:]
|
|
}
|
|
ylow = chebps(xlow, coef, cNC)
|
|
}
|
|
}
|
|
|
|
if nf < cM {
|
|
copy(lsp[:cM], oldLsp[:cM])
|
|
}
|
|
}
|