102 lines
3.0 KiB
Go
102 lines
3.0 KiB
Go
package amrnb
|
|
|
|
// Gain dequantization, ported from opencore-amrnb d_gain_p.cpp, d_gain_c.cpp and
|
|
// dec_gain.cpp. These turn the received gain indices into the per-subframe pitch
|
|
// gain and fixed-codebook gain, driving the gc_pred energy predictor. dGainPitch
|
|
// and dGainCode handle MR795/MR122; decGain handles the joint/scalar-VQ modes
|
|
// (MR475 joint, MR515/MR59 low-rate, MR67/MR74/MR102 high-rate). Bit-exact with
|
|
// the reference.
|
|
|
|
const cMR475_VQ_SIZE = 256
|
|
|
|
// dGainPitch returns the quantized pitch gain (Q14) for the given index.
|
|
// Mirrors d_gain_pitch.
|
|
func dGainPitch(mode int, index int16) int16 {
|
|
gain := qua_gain_pitch[index]
|
|
if mode == dMR122 {
|
|
gain &^= 3 // clear 2 LSBits
|
|
}
|
|
return gain
|
|
}
|
|
|
|
// dGainCode decodes the fixed-codebook gain for MR795/MR122 from the predicted
|
|
// gain (gc_pred) and the quantized correction factor, then updates the
|
|
// predictor. Mirrors d_gain_code.
|
|
func (pred *gcPredState) dGainCode(mode int, index int16, code []int16) (gainCode int16) {
|
|
r := pred.gcPred(mode, code)
|
|
exp, frac := r.expGcode0, r.fracGcode0
|
|
|
|
index &= 31 // index < 32, avoid buffer overflow
|
|
tblTmp := index + (index << 1)
|
|
p := qua_gain_code[tblTmp:]
|
|
|
|
if mode == dMR122 {
|
|
gcode0 := int16(pow2(exp, frac))
|
|
gcode0 = shl(gcode0, 4)
|
|
gainCode = shl(mult(gcode0, p[0]), 1)
|
|
} else {
|
|
gcode0 := int16(pow2(14, frac))
|
|
lTmp := L_mult(p[0], gcode0)
|
|
lTmp = L_shr(lTmp, sub(9, exp))
|
|
gainCode = int16(lTmp >> 16) // Q1
|
|
}
|
|
|
|
quaEnerMR122 := p[1]
|
|
quaEner := p[2]
|
|
pred.update(quaEnerMR122, quaEner)
|
|
return gainCode
|
|
}
|
|
|
|
// decGain decodes both the pitch gain and fixed-codebook gain for the
|
|
// scalar/joint-VQ modes (all except MR795/MR122), updating the predictor.
|
|
// evenSubfr selects the MR475 joint-gain half. Mirrors Dec_gain.
|
|
func (pred *gcPredState) decGain(mode int, index int16, code []int16, evenSubfr int16) (gainPit, gainCod int16) {
|
|
index = shl(index, 2)
|
|
|
|
var gCode, quaEnerMR122, quaEner int16
|
|
|
|
switch {
|
|
case mode == dMR102 || mode == dMR74 || mode == dMR67:
|
|
p := table_gain_highrates[index:]
|
|
gainPit = p[0]
|
|
gCode = p[1]
|
|
quaEnerMR122 = p[2]
|
|
quaEner = p[3]
|
|
case mode == dMR475:
|
|
index += (1 ^ evenSubfr) << 1 // evenSubfr is 0 or 1
|
|
if index > int16(cMR475_VQ_SIZE*4-2) {
|
|
index = int16(cMR475_VQ_SIZE*4 - 2)
|
|
}
|
|
p := table_gain_MR475[index:]
|
|
gainPit = p[0]
|
|
gCode = p[1]
|
|
// Predictor update values are recomputed (not stored in the 4.75 table):
|
|
// qua_ener_MR122 = log2(g), qua_ener = 20*log10(g)
|
|
e, f := log2(int32(gCode)) // Log2(x Q12) = log2(x) + 12
|
|
e -= 12
|
|
t1 := shr_r(f, 5)
|
|
t2 := shl(e, 10)
|
|
quaEnerMR122 = add(t1, t2)
|
|
lTmp := mpy32_16(e, f, 24660) // 24660 Q12 ~= 20*log10(2)
|
|
lTmp = L_shl(lTmp, 13)
|
|
quaEner = round_(lTmp)
|
|
default: // MR515, MR59
|
|
p := table_gain_lowrates[index:]
|
|
gainPit = p[0]
|
|
gCode = p[1]
|
|
quaEnerMR122 = p[2]
|
|
quaEner = p[3]
|
|
}
|
|
|
|
r := pred.gcPred(mode, code)
|
|
exp, frac := r.expGcode0, r.fracGcode0
|
|
gcode0 := int16(pow2(14, frac))
|
|
|
|
lTmp := L_mult(gCode, gcode0)
|
|
lTmp = L_shr(lTmp, 10-exp)
|
|
gainCod = int16(lTmp >> 16)
|
|
|
|
pred.update(quaEnerMR122, quaEner)
|
|
return gainPit, gainCod
|
|
}
|