Files
Cyrene_v2/internal/capability/transcode/amrnb/dsp_enc_qgainp.go
T
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

100 lines
2.5 KiB
Go

package amrnb
// Separate pitch/code gain quantizers (MR122; pitch also used by MR795), ported
// from opencore-amrnb q_gain_p.cpp (q_gain_pitch) and q_gain_c.cpp
// (q_gain_code). qGainPitch picks the nearest quantized pitch gain; qGainCode
// picks the code-gain index minimizing the error to the predicted gain. The
// exact encoder counterparts of dGainPitch / dGainCode. Bit-exact with the
// reference.
const (
cNB_QUA_PITCH = 16
cNB_QUA_CODE = 32
)
// qGainPitch quantizes the pitch gain (in place) to the nearest table entry
// within gpLimit, returning the index. For MR795 it also fills three candidate
// gains/indices. Mirrors q_gain_pitch.
func qGainPitch(mode int, gpLimit int16, gain *int16, gainCand, gainCind []int16) int16 {
errMin := abs_s(sub(*gain, qua_gain_pitch[0]))
index := int16(0)
for i := int16(1); i < cNB_QUA_PITCH; i++ {
if qua_gain_pitch[i] <= gpLimit {
err := abs_s(sub(*gain, qua_gain_pitch[i]))
if err < errMin {
errMin = err
index = i
}
}
}
if mode == dMR795 {
var ii int16
switch {
case index == 0:
ii = index
case index == cNB_QUA_PITCH-1 || qua_gain_pitch[index+1] > gpLimit:
ii = index - 2
default:
ii = index - 1
}
for i := 0; i < 3; i++ {
gainCind[i] = ii
gainCand[i] = qua_gain_pitch[ii]
ii++
}
*gain = qua_gain_pitch[index]
} else if mode == dMR122 {
*gain = qua_gain_pitch[index] &^ 3
} else {
*gain = qua_gain_pitch[index]
}
return index
}
// qGainCode quantizes the fixed-codebook gain (in place) against the predicted
// gain, returning the index and the predictor-update energies. Mirrors
// q_gain_code.
func qGainCode(mode int, expGcode0, fracGcode0 int16, gain *int16) (index, quaEnerMR122, quaEner int16) {
var gQ0 int16
if mode == dMR122 {
gQ0 = *gain >> 1 // Q1 -> Q0
} else {
gQ0 = *gain
}
gcode0 := int16(pow2(expGcode0, fracGcode0))
if mode == dMR122 {
gcode0 = shl(gcode0, 4)
} else {
gcode0 = shl(gcode0, 5)
}
errMin := gQ0 - int16((int32(gcode0)*int32(qua_gain_code[0]))>>15)
if errMin < 0 {
errMin = -errMin
}
index = 0
for i := int16(1); i < cNB_QUA_CODE; i++ {
err := gQ0 - int16((int32(gcode0)*int32(qua_gain_code[i*3]))>>15)
if err < 0 {
err = -err
}
if err < errMin {
errMin = err
index = i
}
}
p := int(index) * 3
temp := int16((int32(gcode0) * int32(qua_gain_code[p])) >> 15)
if mode == dMR122 {
*gain = temp << 1
} else {
*gain = temp
}
quaEnerMR122 = qua_gain_code[p+1]
quaEner = qua_gain_code[p+2]
return
}