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

263 lines
5.4 KiB
Go

package amrnb
// Per-mode algebraic (fixed) codebook decoders, ported from opencore-amrnb
// d2_9pf.cpp, d2_11pf.cpp, d3_14pf.cpp, d4_17pf.cpp, d8_31pf.cpp and
// d1035pf.cpp. Each reconstructs the 40-sample innovation vector cod[] from a
// mode's pulse-position and sign indices (GSM-style tracks, Gray-coded for the
// 4/8/10-pulse modes). Pulse amplitudes are ±8191/∓8192 (or ±4096 for MR122),
// matching the reference exactly.
// pulse amplitude for the ±1.0 codebook entries (MR122 uses ±4096).
const cPOS_CODE = 8191
// decode2i40_9bits decodes the 2-pulse codebook for MR475/MR515. Mirrors
// decode_2i40_9bits (d2_9pf.cpp); subNr is the subframe number.
func decode2i40_9bits(subNr, sign, index int16, cod []int16) {
var pos [2]int16
j := index & 64
j >>= 3
i := index & 7
k := shl(subNr, 1)
k += j
pos[0] = i*5 + startPos[k]
k++
index >>= 3
i = index & 7
pos[1] = i*5 + startPos[k]
for n := 0; n < cL_SUBFR; n++ {
cod[n] = 0
}
for j := 0; j < 2; j++ {
s := sign & 0x1
cod[pos[j]] = s*16383 - 8192
sign >>= 1
}
}
// decode2i40_11bits decodes the 2-pulse codebook for MR59. Mirrors
// decode_2i40_11bits (d2_11pf.cpp).
func decode2i40_11bits(sign, index int16, cod []int16) {
var pos [2]int16
j := index & 0x1
index >>= 1
i := index & 0x7
pos[0] = i*5 + j*2 + 1
index >>= 3
j = index & 0x3
index >>= 2
i = index & 0x7
if j == 3 {
pos[1] = i*5 + 4
} else {
pos[1] = i*5 + j
}
for n := 0; n < cL_SUBFR; n++ {
cod[n] = 0
}
for j := 0; j < 2; j++ {
s := sign & 1
cod[pos[j]] = s*16383 - 8192
sign >>= 1
}
}
// decode3i40_14bits decodes the 3-pulse codebook for MR67. Mirrors
// decode_3i40_14bits (d3_14pf.cpp).
func decode3i40_14bits(sign, index int16, cod []int16) {
var pos [3]int16
i := index & 0x7
pos[0] = i * 5
index >>= 3
j := index & 0x1
index >>= 1
i = index & 0x7
pos[1] = i*5 + j*2 + 1
index >>= 3
j = index & 0x1
index >>= 1
i = index & 0x7
pos[2] = i*5 + j*2 + 2
for n := 0; n < cL_SUBFR; n++ {
cod[n] = 0
}
for j := 0; j < 3; j++ {
s := sign & 1
cod[pos[j]] = s*16383 - 8192
sign >>= 1
}
}
// decode4i40_17bits decodes the 4-pulse Gray-coded codebook for MR74/MR795.
// Mirrors decode_4i40_17bits (d4_17pf.cpp).
func decode4i40_17bits(sign, index int16, cod []int16) {
var pos [4]int16
i := index & 0x7
i = dgray[i]
pos[0] = i * 5
index >>= 3
i = index & 0x7
i = dgray[i]
pos[1] = i*5 + 1
index >>= 3
i = index & 0x7
i = dgray[i]
pos[2] = i*5 + 2
index >>= 3
j := index & 0x1
index >>= 1
i = index & 0x7
i = dgray[i]
pos[3] = i*5 + 3 + j
for n := 0; n < cL_SUBFR; n++ {
cod[n] = 0
}
for j := 0; j < 4; j++ {
s := sign & 0x1
cod[pos[j]] = s*16383 - 8192
sign >>= 1
}
}
// decompress10 expands one compressed 10x10x10 track index into three pulse
// positions. Mirrors decompress10 (d8_31pf.cpp).
func decompress10(MSBs, LSBs, index1, index2, index3 int16, posIndx []int16) {
if MSBs > 124 {
MSBs = 124
}
ia := mult(MSBs, 1311)
ia = int16(int32(MSBs) - (L_mult(ia, 25) >> 1))
ib := mult(ia, 6554)
ib = ia - int16(L_mult(ib, 5)>>1)
ib = shl(ib, 1)
ic := LSBs - ((LSBs >> 2) << 2)
posIndx[index1] = ib + (ic & 1)
ib = mult(ia, 6554)
ib = shl(ib, 1)
posIndx[index2] = ib + (ic >> 1)
ib = LSBs >> 2
ic = mult(MSBs, 1311)
ic = shl(ic, 1)
posIndx[index3] = add(ib, ic)
}
// decompressCode expands the eight compressed MR102 pulse indices into linear
// signs and codeword positions. Mirrors decompress_code (d8_31pf.cpp).
func decompressCode(indx, signIndx, posIndx []int16) {
const nbTrack = 4
for i := 0; i < nbTrack; i++ {
signIndx[i] = indx[i]
}
MSBs := indx[nbTrack] >> 3
LSBs := indx[nbTrack] & 0x7
decompress10(MSBs, LSBs, 0, 4, 1, posIndx)
MSBs = indx[nbTrack+1] >> 3
LSBs = indx[nbTrack+1] & 0x7
decompress10(MSBs, LSBs, 2, 6, 5, posIndx)
MSBs = indx[nbTrack+2] >> 2
LSBs = indx[nbTrack+2] & 0x3
ia := int16(L_mult(MSBs, 25) >> 1)
ia += 12
MSBs0_24 := ia >> 5
ia = mult(MSBs0_24, 6554)
ia &= 1
ib := mult(MSBs0_24, 6554)
ib = MSBs0_24 - int16(L_mult(ib, 5)>>1)
if ia == 1 {
ib = 4 - ib
}
ib = shl(ib, 1)
ia = LSBs & 0x1
posIndx[3] = add(ib, ia)
ia = mult(MSBs0_24, 6554)
ia = shl(ia, 1)
posIndx[7] = ia + (LSBs >> 1)
}
// dec8i40_31bits decodes the 8-pulse codebook for MR102. Mirrors
// dec_8i40_31bits (d8_31pf.cpp).
func dec8i40_31bits(index, cod []int16) {
const nbTrack = 4
var linearSigns [nbTrack]int16
var linearCodewords [8]int16
for i := 0; i < cL_CODE; i++ {
cod[i] = 0
}
decompressCode(index, linearSigns[:], linearCodewords[:])
for j := int16(0); j < nbTrack; j++ {
pos1 := (linearCodewords[j] << 2) + j
var sign int16
if linearSigns[j] == 0 {
sign = cPOS_CODE // +1.0
} else {
sign = -cPOS_CODE // -1.0
}
if pos1 < cL_SUBFR {
cod[pos1] = sign
}
pos2 := (linearCodewords[j+4] << 2) + j
if pos2 < pos1 {
sign = negate(sign)
}
if pos2 < cL_SUBFR {
cod[pos2] += sign
}
}
}
// dec10i40_35bits decodes the 10-pulse Gray-coded codebook for MR122. Mirrors
// dec_10i40_35bits (d1035pf.cpp).
func dec10i40_35bits(index, cod []int16) {
const nbTrack = 5
for i := 0; i < cL_CODE; i++ {
cod[i] = 0
}
for j := int16(0); j < nbTrack; j++ {
tmp := index[j]
i := tmp & 7
i = dgray[i]
i = i * 5
pos1 := i + j
var sign int16
if (tmp>>3)&1 == 0 {
sign = 4096 // +1.0
} else {
sign = -4096 // -1.0
}
cod[pos1] = sign
i = index[j+5] & 7
i = dgray[i]
i = i * 5
pos2 := i + j
if pos2 < pos1 {
sign = negate(sign)
}
cod[pos2] += sign
}
}